Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何扩展对可变模板基类的调用?_C++_Templates_C++11_Metaprogramming_Variadic Templates - Fatal编程技术网

C++ 如何扩展对可变模板基类的调用?

C++ 如何扩展对可变模板基类的调用?,c++,templates,c++11,metaprogramming,variadic-templates,C++,Templates,C++11,Metaprogramming,Variadic Templates,我有一组非正交策略,它们都实现了一个通用的命名方法,这些策略添加了安全检查。 我希望用户能够组合策略以允许更复杂的验证,而无需手动为每个组合案例创建策略。 我的方法是创建一个新的策略类来合并其他策略类 下面的简化示例将C显示为合并类,这里合并了方法id。预期的结果是,在C上调用id时,顺序调用每个基类的id #include <iostream> using namespace std; struct A { void id() { cout << "A ";

我有一组非正交策略,它们都实现了一个通用的命名方法,这些策略添加了安全检查。 我希望用户能够组合策略以允许更复杂的验证,而无需手动为每个组合案例创建策略。 我的方法是创建一个新的策略类来合并其他策略类

下面的简化示例将C显示为合并类,这里合并了方法id。预期的结果是,在C上调用id时,顺序调用每个基类的id

#include <iostream>
using namespace std;

struct A 
{
    void id() { cout << "A ";}
};

struct B 
{
    void id() { cout << "B ";}
};

template<class A, class... As>
struct C : public A, public As... 
{
    void id()
    {
         A::id();
         As...::id(); // This line does not work, it is illustrative.
    }
};

int main()
{
    C<A, B> c;
    c.id();

    //expected: result A B 
}
#包括
使用名称空间std;
结构A
{

void()

using expander = int[];
(void) expander { 0, ((void) As::id(), 0)... };
  • 将模式向左展开;在本例中,模式是表达式
    ((void)As::id(),0)

  • 表达式中的
    是逗号运算符,它计算第一个操作数,丢弃结果,然后计算第二个操作数,并返回结果

  • As::id()
    上强制转换的
    (void)
    存在是为了防止重载的
    运算符,
    ,如果您确定没有任何
    As::id()
    调用会返回使逗号运算符重载的内容,则可以省略该命令
  • 逗号运算符右侧的
    0
    是因为
    expander
    int
    s的数组,所以整个表达式(用于初始化数组元素)的计算结果必须为
    int
  • 第一个
    0
    确保当
    As
    为空包时,我们不会试图创建非法的0大小数组



在C++17中(如果我们幸运的话),
C::id
的整个主体可以替换为:
(A::id(),…,(void)As::id();

哇,以前从来没有听说过这样的扩展。它非常好,实现起来非常干净,没有显式递归。:)这确实是一块宝石,希望我能多投票一次。