在编译时选择实现
Choose between implementations at compile time
假设一个人想创建一个具有两个独立实现的C++类(比如一个在CPU和GPU上运行),并且希望在编译时发生这种情况。
可以使用什么设计模式?
一本好书是:现代C++设计:通用编程和设计模式应用,作者是Andrei Alexandrescu。
基本上,他说你可以使用基于策略的类(一种策略模式,但在编译时完成)来实现你想要的东西。贝娄是一个简单的例子,展示了这一点:
#include <iostream>
using namespace std;
template <typename T>
struct CPU
{
// Actions that CPU must do (low level)
static T doStuff() {cout << "CPU" << endl;};
};
template <typename T>
struct GPU
{
// Actions that GPU must do (low level)
// Keeping the same signatures with struct CPU will enable the strategy design patterns
static T doStuff() {cout << "GPU" << endl;};
};
template <typename T, template <class> class LowLevel>
struct Processors : public LowLevel<T>
{
// Functions that any processor must do
void process() {
// do anything and call specific low level
LowLevel<T>::doStuff();
};
};
int main()
{
Processors<int, CPU> cpu;
Processors<int, GPU> gpu;
gpu.process();
cpu.process();
}
最简单的
解决方案示例,使用 Strategy 模式(但是,选择编译时还是运行时都无关紧要):
class BaseStrategy
{
public:
virtual void doStuff() = 0;
};
class Strategy1 : public Base
{
public:
void doStuff();
};
class Strategy2 : public Base
{
public:
void doStuff();
};
class SomeKindOfAMainClass
{
public:
SomeKindOfAMainClass(BaseStrategy* s)
{
this->s = s;
}
void doStuff()
{
s->doStuff();
}
private:
BaseStrategy* s;
};
然后你只需做new SomeKindOfAMainClass(new Strategy1())
或new SomeKindOfAMainClass(new Strategy2())
.
特征的简单示例:
struct WithStrategy1 {};
struct WithStrategy2 {};
template<typename T>
class SomeKindOfAMainClass;
template<>
class SomeKindOfAMainClass<WithStrategy1>
{
//use Strategy1 here
};
template<>
class SomeKindOfAMainClass<WithStrategy2>
{
//use Strategy2 here
};
您只需在程序开始时实例化SomeKindOfAMainClass<WithStrategy1>
或SomeKindOfAMainClass<WithStrategy2>
。
或者你可以得到奥马哈给出的解决方案#ifdef
.
您可以使用一个简单的模板。(抱歉粗略的实现,这只是一个例子)
#include <iostream>
struct example
{
void cpu() { std::cout << "Cpun"; }
void gpu() { std::cout << "Gpun"; }
template<bool useGpu = true>void go() { gpu(); }
};
template<>void example::go<false>() { cpu(); }
int main()
{
example().go<false>(); //<-- Prints 'Cpu'
example().go(); // <-- Prints 'Gpu'
}
如果要做出编译时决策,则始终存在旧的备用数据库:预处理器。 使用 #ifdef
/#endif
块和编译器参数来指定所需的代码。
相关文章:
- 在运行时选择父类的实现
- 如何在类中实现可选择的类似命名空间的功能?
- 如何实现链表并允许用户选择要使用 C++ 删除的特定节点?
- 在运行时选择要使用的 CRTP 实现
- 有没有办法根据模板参数的类型在不同的类实现之间进行选择
- 在使用Bazel Build构建项目期间,处理/选择界面的不同实现
- C++选择排序的实现不正确.任何建议
- 在C 复杂性和实现中选择位向量
- Cocoa 选择器的行为可以在 C++ 中重新实现吗?
- 为什么选择我的自定义OP的CPU实现
- 我是否应该使用功能指针在构造函数中选择实现
- 如何利用遗传算法求C中数的平方根来实现选择和交叉
- 我如何实现 N 选择 K,允许元素重复,并对具有重复元素的输出进行低优先级
- 使用列表C++实现选择排序
- 在C++中实现选择排序时出错
- C++11:根据项目计数在 std::array 和 std::unordered_map 之间实现选择器
- 使用函数实现选择排序
- 如果我不想在 QAbstractItemView 中实现选择,我应该返回哪些值?
- 在基于数组的列表上实现选择排序
- 使用数组列表实现选择排序