[英]Variadic template partial specialization of a class to restrict type of template arguments
我有一个类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...>
{
...
};
但是对另一个问题的这个答案的阅读让我想知道我对可变参数模板的了解以及有时如何避免递归。
我的问题是,模板参数是否需要采用相对严格的格式才能实现Foo
的部分特化,这种特殊化不会是递归的,并且可以有效地处理Foo<Arg<...>,Arg<...>,...>
形式的所有Foo
Foo<Arg<...>,Arg<...>,...>
?
这有效:
#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";
}
虽然在该表单中使用模板参数可能会或可能不容易或不方便,具体取决于您要对它们执行的操作。
你可以用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...> {};
现在Foo
是一个FooImpl
,它测试你的前提条件是否都满足。
你必须编写is_all_true
和is_valid_arg
,其中is_valid_arg
测试T
的形式是否为Arg<int, Type>
。
例如,在C ++ 17中, is_all_true
只是return (true && ... && bs);
(如果我没记错的话, true
是多余的,但为了清楚起见,我喜欢它)。 在C ++ 11/14中,它会更难。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.