I'm trying to detect if a type is of type A (with any template parameters). I'm using a helper struct and template specialization for it. I did the following:
#include <iostream>
template<typename,typename,typename,typename,int... pars> struct A{};
template<typename T> struct check: std::false_type{} ;
template<typename... T>
struct check<A<T...>> : std::true_type{}; // specialization is not applied
template<typename... T, int... pars>
struct check<A<T...,pars...>> : std::true_type{}; // same
// the following would get applied for any A:
// template<typename T1, typename T2, typename T3, typename T4, int... pars>
// struct check<A<T1,T2,T3,T4,pars...>> : std::true_type{};
int main(){
std::cout << check<A<int,char,double,int,1,2,3>>::value << std::endl;
}
However, it will print out 0, so the uncommented specializations are not applied. Is it not supposed to work or am I missing something here? Is there a similar or alternative way of detecting for any type A, without having to write out all the typename T1
etc for the class A as in the commented line above?
Even though our human brains can deduce a parameter pack of types next to a parameter pack of non-types, the compiler is not willing to try to figure out where one parameter pack ends, and another begins.
In general, there's just not a good way to mix a variable number of type and non-type arguments. The general workaround is, if you can modify A
, to promote the non-type arguments to types:
template <int... pars>
using make_pars = std::integer_sequence<int, pars...>;
And then, the check is much simpler
template <typename... Ts>
struct check : std::false_type {};
template <typename... Ts>
struct check<A<Ts...>> : std::true_type {};
And there's not much extra boilerplate when using:
std::cout << check<A<int,char,double,int,make_pars<1,2,3>>>::value << std::endl;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.