在pre-11的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可变语法,以获得灵活的长度参数列表的好处。我理解使用递归解压缩模板arg list的概念,但我就是看不到正确的语法。这是我尝试过的:
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()函数的调用顺序是从左到右,但这并不重要。
发布于 2013-03-08 22:17:57
这应该是可行的:
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。
此外,每次执行一个递归步骤时,请记住删除一个参数。
发布于 2013-03-08 22:18:55
也许你可以试试这样的方法:
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
}发布于 2013-03-08 22:38:26
您的代码有两个问题。首先,相当平凡的:
return recinit<F,G...>(args...);您已经处理过F,请将其从参数列表中删除。
return recinit<G...>(args...);(此外,您可能应该完美地转发参数。)
其次,代码不会编译,因为您的递归在运行时有一个锚点,而不是在编译时。也就是说,编译器将尝试解压参数包G ad infinitum。为了防止这种情况,您需要为空的模板参数列表指定该函数。
https://stackoverflow.com/questions/15295874
复制相似问题