2016-02-26 48 views
1

比方说,我们有3种类型(S1,S2和S3):如何使用可变模板转发类型和值模板参数?

//type 1 (good type) 
template<typename T1, typename T2, typename T3> 
struct S1{}; 

//type 2 (good type) 
template<typename T1, typename T2, typename T3, int T4> 
struct S2{}; 

//type 3 (bad type) 
template<typename T1, typename T2, typename T3> 
struct S3{}; 

//any other type is also a "bad type" 

我们想创造一种特质,以确定是否类型是S1或S2。
为了简便起见,我们使用可变参数模板,为T#细节不是很重要:

//a type trait to determine if a type is either "type 1" or "type 2" 
//We expect ::value to be true if we can match either type. 
//false otherwise. 
//*ignore cv-qualifier related details 
template <typename T>  struct test:std::false_type{}; 
template <typename... Args> struct test<S1<Args...>>:std::true_type{}; 
template <typename... Args> struct test<S2<Args...>>:std::true_type{}; 

如果我们来测试这种类型的特点,我们可以看到,它并不适用于S2工作:

std::cout << std::boolalpha; 
    std::cout << test<S1<int,int,int>>::value << '\n'; 
    std::cout << test<S2<int,int,int,5>>::value << '\n'; 
    std::cout << test<S3<int,int,int>>::value << '\n'; 

打印:

true 
false 
false 

它不会对S2工作,因为模板类型中的一种已经定义了(在这种情况下,T4已经是一个int)。

是否可以使用可变模板来匹配所有模板类型?
无论它们是类型名称还是实际类型。

回答

4
template <class A0,class A1, class A2, int x> struct test<S2<A0,A1,A2,x>>:std::true_type{}; 

一般来说,带有非类型模板参数的元元编程是一个痛苦。

考虑使用像integral_constant之类的东西,如果你做了很多它:将值作为类型而不是值传递。你甚至可以将模板作为类型传递。

1

这里是一个解决方案,让您需要的输出,而无需重新设计你的S2:

#include <iostream> 
#include <type_traits> 

template<typename T1, typename T2, typename T3> 
struct S1{}; 

//type 2 (good type) 
template<typename T1, typename T2, typename T3, int T4> 
struct S2{}; 

//type 3 (bad type) 
template<typename T1, typename T2, typename T3> 
struct S3{}; 

template <typename T>  struct test : std::false_type{}; 
template <typename... Args> struct test<S1<Args...>> : std::true_type{}; 

template <template <typename, typename, typename, int> class P, typename A, typename B, typename C, int N> 
struct test<P<A,B,C,N>> : std::conditional< 
    std::is_same<P<A,B,C,N>, S2<A,B,C,N>>::value, 
    std::true_type, 
    std::false_type 
>::type {}; 

template <typename T1, typename T2, typename T3, int T4> struct S2Wannabe {}; 

int main() { 
    std::cout << std::boolalpha; 
    std::cout << test<S1<int,int,int>>::value << '\n'; // true 
    std::cout << test<S2<int,int,int,5>>::value << '\n'; // true 
    std::cout << test<S3<int,int,int>>::value << '\n'; // false 
    std::cout << test<S2Wannabe<int,int,int,5>>::value << '\n'; // false 
} 

但重新设计S2可以更容易地解决你的问题。

相关问题