2017-07-16 138 views
3

我有一个类Foo需要有可变数量的模板参数,但这些参数需要是某种泛型类型,而不是完全任意的。例如变量模板部分特化类限制模板参数的类型

template < int I, typename T> struct Arg; 
using type1 = Foo<Arg<3, double>>; 
using type2 = Foo<Arg<1, int>, Arg<7, float>, Arg<1, int>>; 

我想知道什么是最好的方式来实现这一点。我想我需要用一个简单的可变参数模板第一次启动

template < typename ...T > 
class Foo; 

从那里,我可以按照递归路

template < int I, typename T, typename ...Others> 
template Foo<Arg<I, T>, Others...> 
{ 
    ... 
}; 

this answer另一个问题读给我留下想知道我的知识可变参数模板以及如何递归有时可以避免。

我的问题是,这是否模板参数预计将在一个相对刚性的格式事实启用Foo部分专业化这不会是递归的,这将有效地处理所有Foo S中的形式Foo<Arg<...>,Arg<...>,...>的?

回答

6

这工作:

#include <iostream> 

template <int i, typename T> struct Arg; 

template <typename ...T> 
class Foo; 

template <int ...Is, typename ...Ts> 
class Foo<Arg<Is, Ts>...> 
{ 
public: 
    static constexpr unsigned int N = sizeof...(Is); 
}; 

int main() 
{ 
    using type2 = Foo<Arg<1, int>, Arg<7, float>, Arg<1, int>>; 
    std::cout << type2::N << "\n"; 
} 

虽然它可能会或可能不容易或方便地使用模板参数以这样的形式,这取决于你想与他们做什么。

+0

人们仍然可以将参数放在一个元组中,并在需要时访问它们,所以我不会说它们很难使用。简单地添加N并输入到'Arg'来输出它们。 – skypjack

2

你可以用SFINAE做到这一点。这里是一个草图:

template<class...Bs> 
constexpr bool is_all_true(Bs...); // write this 

template<class T> 
constexpr bool is_valid_arg(); // write this 

template < class=void, class...Ts > 
class FooImpl; 

template <class...Ts> 
class FooImpl<std::enable_if_t<is_all_true(is_valid_arg<Ts>()...) >, Ts...> { 
    // code 
}; 

template<class...Ts> 
class Foo:FooImpl<void, Ts...> {}; 

现在FooFooImpl,测试,如果你的前提条件都得到满足。

你必须写is_all_trueis_valid_arg,其中is_valid_arg测试,如果T的形式Arg<int, Type>的。作为一个例子,在C++ 17中,is_all_true只是return (true && ... && bs);(如果我没有记错的话,true是多余的,但为了清晰起见,我喜欢它)。在C++ 11/14中它会更难。

相关问题