Search code examples
c++c++11templatestype-traitsfunction-templates

Why the std::is_array in template function is not distinguishing between int and array type?


In the following code, I am using a template function and type traits to distinguish between an integer type (else case) and array type. I would expect the output to be int and array respectively, instead I get int int with the two calls that instantiates the template functions respectively with an int type and an array type:

Why is that?

#include <iostream>
#include <array>

template <typename T>
inline static void constexpr SetCoordinates()
{
    if (std::is_array<T>::value)
        std::cout<<"array\n";
    else
        std::cout<<"int\n";
}


int main()
{
 int a = 6;
 std::array<int, 4> arr = {1,2,3,4};
 SetCoordinates<decltype(a)>();
 SetCoordinates<decltype(arr)>();
 return 0;
}

Solution

  • The std::is_array does not include the case of std::array; Rather, it only checks if the type is just a normal array type(i.e T[], T[N]). Hence, your if statement lands in the false branch.

    You have to provide a custom traits for the std::array for this to happen:

    #include <type_traits> // std::true_type, std::false_type, std::is_array
        
    template <typename T> struct is_std_array : std::false_type{};
    template < typename T, std::size_t N>
    struct is_std_array<std::array<T, N> > : std::true_type { };
    
    template <typename T>
    inline static void constexpr SetCoordinates()
    {
        if (std::is_array<T>::value || is_std_array<T>::value)
            //                       ^^^^^^^^^^^^^^^^^^^^^^^^^-->and check
            std::cout << "array\n";
        else
            std::cout << "int\n";
    }
    

    See a demo