C++11 继承和参数模板包。诀窍是什么?

C++11 继承和参数模板包。诀窍是什么?,c++11,variadic-templates,C++11,Variadic Templates,我看到一些代码()使用递归“继承”来破坏模板参数包。这个建筑背后的想法是什么?它是如何工作的?前言 尽管模板递归通常是必要的,但没有什么需要使用继承。这就是说,使用该模式已变得相当标准: template <typename T, typename = void> struct has_trait : std::false_type {}; template <typename T> struct has_trait<T, std::enable_if_t<

我看到一些代码()使用递归“继承”来破坏模板参数包。这个建筑背后的想法是什么?它是如何工作的?

前言

尽管模板递归通常是必要的,但没有什么需要使用继承。这就是说,使用该模式已变得相当标准:

template <typename T, typename = void>
struct has_trait : std::false_type {};

template <typename T>
struct has_trait<T, std::enable_if_t<some_predicate>> : std::true_type {};
非类型参数
B
为“匹配”参数
T
是我们感兴趣的匹配参数;
ARGS…
是参数包

我们将使用此模板的专门化来处理各种情况

空参数包

让我们以参数包为空的情况为例。在这种情况下,专门化如下所示:

template <bool B, typename T>
struct pack_with_type_impl<B,T> : std::false_type {};
template <typename T, typename ... ARGS>
struct pack_with_type_impl<true, T, ARGS...> : std::true_type {};
递归

现在是有趣的部分。到目前为止,我们还没有进行递归,因为上述情况代表终止条件:其中参数包为空,因此没有更多的事情要做;还有一个已经找到匹配项的地方,所以没什么可做的了。但是现在让我们来做我们还没有找到匹配项的部分。在这种情况下,我们将有如下内容:

template <typename T, typename H, typename ... TAIL>
struct pack_with_type_impl<false, T, H, TAIL...> :
   pack_with_type_impl<std::is_same<T,H>::value, T, TAIL...> {};
pack_with_type_impl<false,int,char,double,float> 
  ==> pack_with_type_impl<false,int,double,float> 
    ==> pack_with_type_impl<false,int,float> 
      ==> pack_with_type_impl<false,int> # and since the parameter pack is empty now...
        ==> std::false_type
另一方面,如果我提供了参数
char,int,double
,继承链将是:

pack_with_type_impl<false,int,char,int,float> 
  ==> pack_with_type_impl<false,int,int,float> 
    ==> pack_with_type_impl<true,int,float> # and since the first argument is true 
      ==> std::true_type
pack\u与\u类型\u impl
==>使用类型进行打包
==>pack_with_type_impl#并且由于第一个参数为true
==>标准::真实类型
评论

当然还有更优雅的方法来做到这一点。对于初学者,我可能会创建一些alias模板,如下所示:

template <typename ... ARGS>
using has_int = pack_with_type_impl<false,int,ARGS...>;
模板
使用has\u int=pack\u和类型\u impl;
这样我就可以打电话:

template <typename ... ARGS>
void increment_int(std::tuple<ARGS...>& tup) {
   static_assert(has_int<ARGS...>::value,
                 "Can only call increment_int on tuples with an int type!");
   ...
}
模板
无效增量_int(标准::元组和元组){
静态\u断言(具有\u int::value,
“只能对int类型的元组调用increment_int!”);
...
}

但这是第一次尝试解释这个棘手的问题。

在泛型代码中,您无法创建具有N个直接成员的类。但是,您可以创建一个包含一个直接成员和继承成员的类,通过专门化
N==1
结束递归

示例:假设您想要创建一个类,使得
Foo
包含3个成员函数
void Foo::f(int);void Foo::f(int);void Foo::f(std::string)
。这是不可能的,因为N=3。但是,您可以从
Foo
派生
Foo
,并添加一个成员
void f(int)

模板
Foo类:公共Foo
{

public:void f(HEAD h){std::你是在问这种方法的动机吗?还是在问它是如何工作的?后者。我在另一个主题上看到了类似的方法。@user877329难以用文字解释:)
template <typename ... ARGS>
void increment_int(std::tuple<ARGS...>& tup) {
   static_assert(has_int<ARGS...>::value,
                 "Can only call increment_int on tuples with an int type!");
   ...
}
template<typename HEAD, typename... Tail>
class Foo : public Foo<Tail...>
{
    public: void f(HEAD h) { std::cout << h; }
};

template<typename HEAD>
class Foo<HEAD>
{
    public: void f(HEAD h) { std::cout << h; }
};