在运行时选择同一函数的版本
Select a version of the same function in runtime
我目前正在做一个项目,每次程序运行时都可以调用同一算法的 4 个版本之一(涉及不同的并行编程框架 + 其顺序类似物)。
所有这 4 个参数都是相同的,并行框架细节将在函数本身内部处理。
我是C++新手,所以真的不知道是否可以更改function()
指向的代码并根据命令行参数选择正确的版本。
警告:前面有可怕的伪代码:
switch(version){
case OMP:
// make function() point to 1st version
case CUDA:
// ... to function2()
case OCL:
// ... to function3()
case SEQ:
default:
// ... to function0()
}
// ...
while(condition){
// call function()
}
所以我试图找出一种优雅的方式来做到这一点,同时将不同的算法放在单独的文件中,只在主例程中处理 I/O。某种行为模式?
如果你有普通的函数并且不需要类层次结构,你可以使用std::function
:
std::function<void (int, float)> target;
switch(version){
case OMP: target = function1; break;
case CUDA: target = std::bind(function2, "hello", _1, _2); break;
case OCL: target = function3; break;
case SEQ: target = function4; break;
default: target = function0; break;
}
target(100, 3.14);
这是策略模式的典型示例。策略模式的基本思想是,您将拥有一个抽象的Strategy
它将具有纯虚拟execute
或run
方法。每个不同的算法或策略都会有具体的子类。
对于您的情况,大纲可以是这样的:
class BaseStrategy {
virtual void execute(params...) = 0;
}
class OMPStrategy : public BaseStrategy {
// implement execute method for OMP
}
class CUDAStrategy : public BaseStrategy {
// implement execute method for CUDA
}
// etc
现在,在需要选择一个版本的方法中,您将根据您的输入实例化正确的策略对象并对其调用execute
。
像这样:
BaseStrategy *strategy;
switch(version){
case OMP:
strategy = new OMPStrategy();
break;
case CUDA:
strategy = new CUDAStrategy();
break;
case OCL:
strategy = new OCLStrategy();
break;
case SEQ:
strategy = new SEQStrategy();
break;
default:
strategy = new DefaultStrategy();
}
// now call it
while(condition){
strategy->execute();
}
// delete strategy when done
delete strategy;
通过这种方式,您可以在不同的类中对不同的算法进行干净的单独实现。
注意:如注释中所述,如果引发异常,则可能会出现内存泄漏。如果您使用的是 c++11,那么使用 std::shared_ptr
或 std::unique_ptr
将比使用原始指针更好。
如果你使用的是 Linux(可能还有其他 Unix),你可以在运行时使用 dlopen() 加载正确的库函数,参见 'man 3 dlopen'。
dlopen 系列在您有一个主应用程序并希望能够使用例如较新版本的插件库进行热修补的情况下也很有用。原则上,甚至不必重新启动主应用程序即可升级插件。
自从我在Windows中入侵以来已经有一段时间了,但是Windows和Mac中也很有可能存在类似于dlopen的东西。(Mac是基于BSD变体的,所以即使是dlopen()也可以工作)。
- 用符号版本替换对函数的所有调用
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 有没有办法在不使用 #ifdef 的情况下不编译发布版本中的单元测试函数体?
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 用非纯虚拟版本重载纯虚函数
- 重载模板函数未为特定类型选择正确的版本
- Python 的 exec() 函数的 C++ 版本
- "std::function"的简单版本:函数对象的生存期?
- C++14 及更高版本是否允许 Lambda 函数的默认参数?如果是这样,怎么办?
- 在h文件上内联发布版本并在cpp上实现调试版本的函数
- 我可以删除对象的右值版本的函数吗?
- 传递 const int* 和 int* 时调用重载函数的不同版本(const int* const&/&&)
- 触发的断点(析构函数)与类模板类型是自身的一个版本
- opengl32.lib如何在Windows(仅1.1版本)上工作?它是否真正实现了OpenGL函数
- C++14 强制转换以返回成员函数的类型 - 简洁版本
- 所有版本的 GCC 都与默认成员初始值设定项作斗争,该初始值设定项捕获了这一点,并结合了继承的构造函数
- 根据运行时参数调用模板函数的不同版本
- 函数的内联版本返回的值与非内联版本不同
- std::bind()中static_cast的函数版本
- 派生类是否需要在基类上声明自己的虚函数版本