Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to statically check if type T of a template is std::vector<U>, where U is either float, double or integral

How can I check that arguments in parameter pack have type of either of float, double, integral, or a std::vector of thereof?

For example T={int, long, std::vector<double>} is fine,

while T={int, long, std::vector<long double>} is not, because we don't allow std::vector to be of long double type.

I got this far

template<class ...T>
void foo(T... t)
{
    static_assert(std::is_same<float, T...>::value
               || std::is_same<double, T...>::value
               || std::is_integral<T...>::value
            /* || std::is_same<std::vector<float/double/integral>, T>::value ? */
               , "unsupported type!");
}

and not sure how to express the restriction of std::vector.

It would be nice to reuse the float/double/integral check somehow, so that we wouldn't need to type them twice. Something like

bool basic_check = std::is_same<float, T...>::value
               || std::is_same<double, T...>::value
               || std::is_integral<T...>::value;

static_assert(basic_check
              || std::is_same<std::vector<basic_check>, T>
              , "unsupported type!");

I also want the assert to succeed (i.e. pass the build) when T={}.

like image 315
Flying Hat Avatar asked Mar 22 '15 06:03

Flying Hat


People also ask

How do you determine a vector type?

Given a vector, you can determine its type with typeof() , or check if it's a specific type with an “is” function: is. character() , is.

What is the difference between Typename and class in template?

There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.

Is a template a vector?

vector is a template class, which can be instantiated with a type, in the format: vector<int> , vector<double> , vector<string> . The same template class can be used to handle many types, instead of repeatably writing codes for each of the type.

What is template type parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.


2 Answers

You can create your own check, using template specialization. I've broadened the check to include long double just to reduce the size of the code.

#include <type_traits>
#include <vector>

template<class T>
struct is_ok {
    static constexpr bool value =
        std::is_floating_point<T>::value ||
        std::is_integral<T>::value;
};

template<class T>
struct is_ok<std::vector<T>> {
    static constexpr bool value =
        std::is_floating_point<T>::value ||
        std::is_integral<T>::value;
};

Here is a demo:

#include <cstdio>
#define TEST(x) \
    std::printf("%s: %s\n", #x, is_ok<x>::value ? "true" : "false")

int main() {
    TEST(int);
    TEST(float);
    TEST(char *);
    TEST(std::vector<int>);
    TEST(std::vector<float>);
    TEST(std::vector<char *>);
    return 0;
}

Output:

int: true
float: true
char *: false
std::vector<int>: true
std::vector<float>: true
std::vector<char *>: false
like image 133
Dietrich Epp Avatar answered Oct 22 '22 20:10

Dietrich Epp


First write a trait that tests one type:

template<class T>
struct is_ok : std::is_arithmetic<T> { };

template<class T, class A>
struct is_ok<std::vector<T, A>> : std::is_arithmetic<T> { };

Then test that the trait holds true for every type in the pack. I prefer to use @Columbo's bool_pack trick:

template<bool...> class bool_pack;
template<bool... b>
using all_true = std::is_same<bool_pack<true, b...>, bool_pack<b..., true>>;

template<class ...T>
void foo(T... t)
{
    static_assert( all_true<is_ok<T>::value...>::value, "unsupported type!");
}
like image 39
T.C. Avatar answered Oct 22 '22 21:10

T.C.