我试图想办法循环一个模板参数列表,但没有成功
我不能使用c ++ 11可变参数模板功能,需要在编译时完成
我可以假设在否定之后没有正面的论据
任何想法?
template< int F1, int F2 ,int F3>
struct TemplatedClass
{
TemplatedClass();
update()
{
/*
for each positive template argument
call a method
*/
}
};
答案 0 :(得分:5)
您可以将所有参数放入数组中并迭代遍历,而不是编写一系列if
语句。这种方式编译器将无法优化您的代码(您没有指定是否需要这样做),但我认为它看起来会更清晰。 E.g。
template<int F1, int F2 ,int F3>
struct TemplatedClass
{
TemplatedClass();
update()
{
const int array[] = {F1, F2, F3};
// replace this with std::for_each(...) with functors you need
for (int i = 0; i < sizeof(array)/sizeof(array[0]); ++i)
{
myfunc(array[i]);
}
}
}
答案 1 :(得分:3)
由于您将拥有有限数量的模板参数,因此您可以使用一系列if
语句。
template<int F1, int F2 ,int F3>
struct TemplatedClass
{
TemplatedClass();
update()
{
if (F1 > 0) myfunc();
if (F2 > 0) myfunc();
if (F3 > 0) myfunc();
// etc.*
}
}
答案 2 :(得分:2)
修复了模板参数的数量后,这样的简单代码将执行:
update()
{
if (F1 > 0) callAMethod();
if (F2 > 0) callAMethod();
if (F3 > 0) callAMethod();
}
if
语句中的表达式是编译时常量,因此优化器会将其优化为相当于调用方法“unguarded”(没有分支)或不调用方法的代码所有。换句话说,优化器在编译时将决定是否调用该方法,而不会产生运行时成本。
答案 3 :(得分:1)
如果您不确定优化程序是否会删除if
s,请使用帮助程序模板:
void functionToCall(int number) { /* ... */ }
template<bool doCall>
struct FuncCaller {
template<typename Callable>
FuncCaller(Callable func, int number) { func(number); }
};
template<>
struct FuncCaller<false> {
template<typename Callable>
FuncCaller(Callable, int) {}
};
update()
{
FuncCaller<(F1 > 0)>(functionToCall, F1);
FuncCaller<(F2 > 0)>(functionToCall, F2);
FuncCaller<(F3 > 0)>(functionToCall, F3);
}
答案 4 :(得分:0)
您可以尝试使用Boost Metaprogramming库,但需要您更改类的模板定义,以便为Boost MPL参数腾出空间。
你想用Boost :: MPL做的一个例子是:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/if.hpp>
#include <iostream>
using namespace boost::mpl;
template<class T>
class Test {
public:
void funcToCall() {
std::cout << "I'm called\n";
}
void update();
};
template<class Y, class T>
struct Update {
static void update(T* t) {
typedef typename pop_back<Y>::type vec_less;
if (back<Y>::type::value > 0)
t->funcToCall();
Update<typename if_<empty<vec_less>, void, vec_less >::type, T>::update(t);
}
};
template<class T>
struct Update<void ,T> {
static void update(T* t) {}
};
template<class T>
void Test<T>::update() {
Update<T, Test<T> >::update(this);
}
int main() {
Test<vector<int_<0>,int_<4>, int_<9> > > t;
t.update();
return 0;
}
“Test”类将是您原来的“TemplatedClass”。现在,您只需获取一个boost :: mpl :: vector参数,而不是获取int模板参数列表。这包含你想要传递的所有int,然后你调用update函数,它将从struct“Update”递归调用更新方法,如果int大于0,它将负责调用“funcToCall()”方法。
我粘贴的程序的输出是:
MacBook-Pro-di-Marcello:~Kariddi $ ./test
我被称为
我被称为
当然,您需要Boost库才能使用此示例。
您可以在此处找到有关MPL的信息:
http://www.boost.org/libs/mpl/doc/index.html
干杯, 马塞罗