Home > Mobile >  How to use type_traits is_same for std::array
How to use type_traits is_same for std::array

Time:10-08

I am trying to write a validation method for a template input, which tests if the input is a std::string, std::vector, or an std::array. However for the latter I am having an issue as I must provide a constant length for the type definition.

So when I call std::is_same<T, std::array<uint8_t, container.size()>>::value the compiler of cause gets angry (makes sense container.size() is not static). Is there are way to get around this?
I don't know the size of the container in advance and I will never know it :(

    template<typename T> bool valid_container_type(const T& container)
    {
        (void) container; 
        if constexpr (std::is_same<T, std::vector<uint8_t>>::value)
        {
            return true; 
        }
        else if constexpr (std::is_same<T, std::vector<char>>::value)
        {
            return true; 
        }
        else if constexpr (std::is_same<T, std::array<char, container.size()>>::value)
        {
            return true; 
        }
        else if constexpr (std::is_same<T, std::array<uint8_t, container.size()>>::value)
        {
            return true; 
        }                
        else if constexpr (std::is_same<T, std::string>::value)
        {
            return true;
        }     
        return false; 
    }

CodePudding user response:

The problem is that container.size() is not a constant expression and can't be used as non-type template argument.

You can add a type trait to get the size at compile-time (or use std::tuple_size directly as @康桓瑋 commented). E.g.

template <typename>
struct get_array_size;
template <typename T, size_t S>
struct get_array_size<std::array<T, S>> {
    constexpr static size_t size = S;
};

Then use it as:

if constexpr (std::is_same<T, std::array<uint8_t, get_array_size<T>::size>>::value)

Note that you have to move the if branch for std::string before the one before std::array. Otherwise you need to define size (and give it a default value) in the primary template too.

CodePudding user response:

You can check if some T is an std::arary with elements of type uint8_t like this:

#include <iostream>
#include <array>
#include <type_traits>

template <typename T>
struct is_uint8_t_array : std::false_type {};

template <size_t S>
struct is_uint8_t_array< std::array<uint8_t,S> > : std::true_type {};


int main() {
    std::cout << is_uint8_t_array<std::array<uint8_t,32>>::value << "\n";  // 1
    std::cout << is_uint8_t_array<std::array<int,42>>::value << "\n";      // 0 
    std::cout << is_uint8_t_array<int>::value << "\n";                     // 0
}
  • Related