目前我正在编写一个类,它支持使用预处理器定义在cpu
或gpu
上进行数据处理,以确定要包含哪个header
文件。
IE
#ifdef CPU_work
#include "cpu_backend.h"
#endif
#ifdef GPU_work
#include "gpu_backend.h"
#endif
class Work {
//Implementation dependant upon included header
}
然而,在某些情况下我可能需要两种变体。无论如何,我可以做类似......
namespace CPU {
#define CPU_work
//Generate implementation of WorkClass with cpu_backend.h
}
namespace GPU {
#define GPU_work
//Generate implementation of WorkClass with gpu_backend.h
}
并因此通过类似......
来确定我想要的实现CPU::Work cpuObject;
GPU::Work gpuObject;
对任何解决方案也很满意。 非常感谢JJ。
答案 0 :(得分:2)
这可能是使用模板方法设计的地方。您的基类实现了CPU和GPU共有的所有内容,然后在有差异的地方使用抽象函数。
Work
您现在无法使用基类foo
,因为它是抽象的,您不会无意中调用派生类bar
或FZAccordionTableView
,因为它们是私有成员基类。
答案 1 :(得分:0)
有趣的问题:)如果我理解你的目标是正确的,我可以建议一些解决方案。
首先使用模板特化,模板默认参数和(当然)一些宏。
检查出来:
Option Explicit
Sub Clear_Table(ct As Range)
ct.ClearContents
End Sub
Sub rite()
Clear_Table Range("E10")
Range("E10").Value = "dwsds"
End Sub
// cpu_backend.h
#define CPU_BACKEND
class UseCPU;
#ifndef GPU_BACKEND
template<class Method = UseCPU>
struct Backend;
#endif
template<>
struct Backend<UseCPU>
{
char* Info() { return "CPU"; }
};
// gpu_backend.h
#define GPU_BACKEND
class UseGPU;
#ifndef CPU_BACKEND
template<class Method = UseGPU>
struct Backend;
#endif
template<>
struct Backend<UseGPU>
{
char* Info() { return "GPU"; }
};
如果您使用MSVC,则可以简化上述示例,从而消除// main.cpp
// Try to swap comments on headers
// and see how output changes
#include "cpu_backend.h"
//#include "gpu_backend.h"
#include <iostream>
template<class ... Method>
struct Work
{
Work()
{
std::cout << "I use " << backend.Info() << std::endl;
}
private:
Backend<Method ...> backend;
};
int main()
{
Work<> work;
// Uncomment these two while including both headers
//Work<UseCPU> cpuWork;
//Work<UseGPU> gpuWork;
return 0;
}
和#define
。
技巧: MSVC(2017年和更早版本)允许省略那些宏阈值,只是忽略第二个声明,如果它们相遇 相同的编译单元,如下:
#ifndef
但这不符合标准。 Standard不允许两次指定默认模板args。
同时,这个解决方案有一些缺点:
当您同时包含两个标题时,有人仍然可以说template<class Method = UseCPU>
struct Backend;
template<class Method = UseGPU>
struct Backend;
使用 指定的第一个 标头指定的后端。
但是,如果编译器强迫某人指定一个,那会更好
在这种情况下显式后端类型,因为否则它
依赖于标题包含顺序,这是坏的(问好
宏)。
此外,它假设两个后端都具有相同的API(如Work<>
在我的情况下)
可能的修复:
我确信在两者都可以使编译器出错 包含标头,但没有指定明确的后端,但它 可能涉及更多的预处理器或一些SFINAE ......
如果您的后端有不同的API,那么您可以插入一些
Info()
需要或(最好)使用C ++ 17
#ifdef
如果您有权限
这样很酷的功能:)