可变模板基类调用转移
Variadic template base class call forwarding
在c++版本之前,我有这样的代码:
template<class T,class U,class V>
struct Foo : T,U,V {
bool init() {
if(!T::init() || !U::init() || !V::init())
return false;
// do local init and return true/false
}
};
我想将其转换为c++ 11可变语法,以获得灵活长度参数列表的好处。我理解使用递归解包模板参数列表的概念,但我只是看不到语法正确。以下是我尝试过的:
template<typename... Features>
struct Foo : Features... {
template<typename F,typename... G>
bool recinit(F& arg,G&& ...args) {
if(!F::init())
return false;
return recinit<F,G...>(args...);
}
bool init() {
// how to call recinit() from here?
}
};
我更喜欢调用基类init()函数的顺序从左到右,但这并不重要。
应该可以:
template<typename F, typename... T>
struct recinit;
template<typename F>
struct recinit<F> {
static bool tinit(F *) {
return true;
}
};
template<typename F, typename T, typename... G>
struct recinit<F, T, G...> {
static bool tinit(F *ptr) {
if (!ptr->T::init())
return false;
return recinit<F, G...>::tinit(ptr);
}
};
template<typename... Features>
struct Foo : Features... {
bool init() {
bool res = recinit<Foo, Features...>::tinit(this);
//use res wisely
}
};
你的问题是你不能写函数的部分特化,只能写类/结构的部分特化。辅助结构体必须在Foo
之外,否则它将从封闭结构体中获取模板参数,这将是糟糕的。
你没有说,但我假设init
是一个非静态成员函数。如果是这样的话,args
的论点就没有什么意义了:它们都应该是this
!跳过这一次,避免在参数中使用包。我试着传递this
作为void*
,但这可能会很麻烦,所以我只是添加了一个额外的模板参数到recinit
,这将是Foo
。
而且,每次执行一个递归步骤时,请记住删除一个参数
也许你可以试试这样做:
template<typename... Features>
struct Foo : Features...
{
bool init()
{
// Courtesy of Xeo :-)
auto il = {(static_cast<bool (Foo::*)()>(&Features::init))...};
return std::all_of(il.begin(), il.end(),
[this] (bool (Foo::*f)()) { return (this->*f)(); }
);
}
};
这里是另一个使用可变模板的更详细的版本:
template<typename... Features>
struct Foo : Features...
{
bool init()
{
return combine_and((&Features::init)...);
}
private:
bool combine_and()
{
return true;
}
template<typename F>
bool combine_and(F f)
{
return (this->*f)();
}
template<typename F1, typename... Fs>
bool combine_and(F1 f1, Fs... fs)
{
return ((this->*f1)() && combine_and(fs...));
}
};
无论您选择哪种解决方案,都可以这样使用:
#include <iostream>
using namespace std;
struct A { bool init() { cout << "Hello " << endl; return true; } };
struct B { bool init() { cout << "Template " << endl; return true; } };
struct C { bool init() { cout << "World!" << endl; return true; } };
int main()
{
Foo<A, B, C> f;
bool res = f.init(); // Prints "Hello Template World!"
cout << res; // Prints 1
}
您的代码有两个问题。首先,相当普通的:
return recinit<F,G...>(args...);
您已经处理了F
,请将其从参数列表中删除。
return recinit<G...>(args...);
(另外,您可能应该完美地转发参数。)
其次,代码不会编译,因为你的递归在运行时有一个锚,而在编译时没有。也就是说,编译器将尝试无限地解压缩参数packG
。为了防止这种情况,你需要专门化函数用于空模板参数列表
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 可变模板基类调用转移