我正在运行模拟,要求我使用int
参数的模板(D =我系统的维度)。典型的模拟功能是
template <int D> void simulation();
当我想专门化这个模板时,我使用了一个开关
switch(d){
case 2:
simulation<2>();
break;
case 3:
simulation<3>();
break;
// etc.
}
据我有一个模拟功能,没关系。但想象一下我有10个(simul1,simul2,... simul10),d可以从2到10。我必须写十次相同的开关!
我想知道是否有可能将其分解,并且有类似的东西:
template <void (*fun)()> runSimulation(int d){
switch(d){
case 2:
fun<2>();
}
}
当然<void (*fun)()>
没有做我想要的,因为fun
是template<int>
。有办法吗?
答案 0 :(得分:2)
当您可以使用静态方法将模拟函数更改为类时:
struct sim1
{
template<int D> static void apply();
};
然后应该有以下工作:
template <typename Sim> runSimulation(int d){
switch(d){
case 2:
Sim::template apply<2>();
case 3:
Sim::template apply<3>();
// ...
}
}
哪个是通用的,可以使用runSimulation<sim1>(d);
或runSimulation<sim2>(d);
等来调用
答案 1 :(得分:0)
这是一个使用模板递归将运行时信息转换为编译时信息的简单方案:
template<int N> void runSimulation() { std::cout<<"runSimulation " << N << std::endl; }
constexpr size_t max_index = 100;
namespace detail
{
//overload for maximum index
void callSimulation_impl(size_t i, std::integral_constant<size_t, max_index>) {}
template<size_t N>
void callSimulation_impl(size_t i, std::integral_constant<size_t, N>)
{
if(i==N)
{
runSimulation<N>();
}
else
{
callSimulation_impl(i, std::integral_constant<size_t, N+1>());
}
}
}
void callSimulation(size_t i)
{
detail::callSimulation_impl(i, std::integral_constant<size_t, 0>());
}
int main(int argc, char *argv[])
{
callSimulation(10); // calls runSimulation<10>();
//or also:
callSimulation(rand()%max_index); //calls a random simulation
}
正如您生成的手动切换一样,它需要按照传递索引的大小线性努力(使用二进制搜索也可以实现类似的算法实现)。
如果效率很重要,您也可以使用魔术开关进行O(1)
工作,请参阅here和here - 我&#39;马云的粉丝。
编辑:此方案可与@Daniel Frey的其他答案结合使用,以便为多种模拟类型和任意多种切换案例提供单一功能。
答案 2 :(得分:0)
如果C ++接受模板函数作为模板参数会很好,但我不知道如何表达它。但是,它接受模板类作为模板参数。
如果您愿意将您的模拟系列(simul1,simul2等)打包成每个系列的一个包装模板(Wrapper1,Wrapper2,...),您可以执行以下操作:
template<template<int D> class SimulationFunctionWrapper> struct Caller {
static void simulation(int d) {
switch(d) {
case 2: SimulationFunctionWrapper<2>::run(); break;
case 3: SimulationFunctionWrapper<3>::run(); break;
}
}
};
#include <iostream>
// normal simul1 declarations and definitions
template<int D> void simul1();
template<> void simul1<2>() { std::cout << "simul1<2>\n"; }
template<> void simul1<3>() { std::cout << "simul1<3>\n"; }
// Enables dispatching to the right simul1 based on the template integer
template<int D> struct Wrapper1 { static void run() { simul1<D>(); } };
// normal simul2 declarations and definitions
template<int D> void simul2();
template<> void simul2<2>() { std::cout << "simul2<2>\n"; }
template<> void simul2<3>() { std::cout << "simul2<3>\n"; }
// Enables dispatching to the right simul2 based on the template integer
template<int D> struct Wrapper2 { static void run() { simul2<D>(); } };
int main(int argc, const char *argv[]) {
Caller<Wrapper1>::simulation(argc);
Caller<Wrapper2>::simulation(argc);
return 0;
}
这显示了如何使用相同的代码(Caller
)来决定调用哪个函数。不幸的是,它需要样板包装器。