Dan*_*vil 6 c++ templates variadic-templates c++11
如何迭代可变参数模板类的所有基类并为每个类调用一个函数.
这是一个最小的例子:
struct A { void foo() { std::cout << "A" << std::endl; } };
struct B { void foo() { std::cout << "B" << std::endl; } };
struct C { void foo() { std::cout << "C" << std::endl; } };
template<typename... U>
struct X : public U...
{
void foo() {
static_cast<U*>(this)->foo()...; // ??? should call `foo` for all `U`
}
};
int main() {
X<A,B,C> x;
x.foo();
}
Run Code Online (Sandbox Code Playgroud)
你通常不能没有C++ 17的折叠表达式.那里的省略号无效,星号后面的省略号会创建一个指针模板参数列表.对于要重复的适当模式,省略号必须位于语句的末尾,这在此处不起作用.我发现这篇文章是一个很好的资源包扩展资源.
相反,有是因为它不需要建立任何事情递归一招:
int arr[] = {(static_cast<U*>(this)->foo(), 0)...};
Run Code Online (Sandbox Code Playgroud)
这将调用每个函数,然后将结果与逗号运算符一起使用以生成所需的ints.不幸的是,这可能会导致未使用的变量警告.解决这个问题的一个最小方法是使用一个std::array(或者一些可以使用初始化列表初始化的类)并将其中的一个未命名的类型void转换为(转换为void一般用于防止警告的常用技术).
这是一种方式:
struct thru{template<typename... A> thru(A&&...) {}};
struct A { void foo() { std::cout << "A" << std::endl; } };
struct B { void foo() { std::cout << "B" << std::endl; } };
struct C { void foo() { std::cout << "C" << std::endl; } };
template<typename... U>
struct X : public U...
{
void foo() { thru{(U::foo(), 0)...}; }
};
Run Code Online (Sandbox Code Playgroud)
但是如果你关心电话的顺序,请注意这里讨论的已知gcc bug .