Group built in types to category I've created the following program to assist me in some template stuff I'm working on.

The function get_type returns 0, 1, 2, 3 or nullopt corresponding to which group the argument T belongs to.

This is my first template style project, so I'm looking for any critique possible. (Note the functions are marked static intentionally, as this will only be used inside this particular file, and should not be visible to users.)

namespace ae
{
    namespace details
    {
        template &lt;class T&gt;
        [[nodiscard]]
        static inline constexpr auto is_integer() noexcept
        {
            return std::is_same_v&lt;T, short&gt;
                || std::is_same_v&lt;T, int&gt;
                || std::is_same_v&lt;T, long&gt;
                || std::is_same_v&lt;T, long long&gt;
                || std::is_same_v&lt;T, unsigned short&gt;
                || std::is_same_v&lt;T, unsigned int&gt;
                || std::is_same_v&lt;T, unsigned long&gt;
                || std::is_same_v&lt;T, unsigned long long&gt;;
        }

        template &lt;class T&gt;
        [[nodiscard]]
        static inline constexpr auto is_floating_point() noexcept
        {
            return std::is_same_v&lt;T, float&gt;
                || std::is_same_v&lt;T, double&gt;
                || std::is_same_v&lt;T, long double&gt;;
        }

        template &lt;class T&gt;
        [[nodiscard]]
        static inline constexpr auto is_charachter() noexcept
        {
            return std::is_same_v&lt;T, char&gt;
                || std::is_same_v&lt;T, unsigned char&gt;
                || std::is_same_v&lt;T, wchar_t&gt;;
        }

        template &lt;class T&gt;
        [[nodiscard]]
        static inline constexpr auto is_boolean() noexcept
        {
            return std::is_same_v&lt;T, bool&gt;;
        }

        // Returns 0 for integer, 1 for floating_point,
        // 2 for charachter, 3 for boolean, and nullopt otherwise
        template &lt;class T&gt;
        [[nodiscard]]
        static inline constexpr auto get_type() noexcept
        {
            if constexpr (is_integer&lt;T&gt;())        
                return std::optional&lt;unsigned int&gt;(0u);
            else if constexpr (is_floating_point&lt;T&gt;()) 
                return std::optional&lt;unsigned int&gt;(1u);
            else if constexpr (is_charachter&lt;T&gt;())     
                return std::optional&lt;unsigned int&gt;(2u);
            else if constexpr (is_boolean&lt;T&gt;())       
                return std::optional&lt;unsigned int&gt;(3u);
            else return std::nullopt;
        }
    }
}


Example usage

template &lt;typename T&gt;
static typename std::enable_if&lt;ae::details::is_integer&lt;T&gt;(), T&gt;::type test()
{
    // Do something if T is integer
}

template &lt;typename T&gt;
static typename std::enable_if&lt;ae::details::is_charachter&lt;T&gt;(), T&gt;::type test()
{
    // Do something if T is charachter
}

int main()
{
    test&lt;int&gt;(); //..

    return 0;
}
In is_charachter (which is misspelled; it should be is_character), you left out signed char (which is a distinct type from char). The same applies for all of the fixed width types (char8_t, char16_t, char32_t).

get_type returns some arbitrary magic number values.  You could create named constants to represent the type.  If you add a "unknown_type" value, then you wouldn't need to use std::optional.