【发布时间】:2022-08-18 23:06:24
【问题描述】:
我有一个嵌入式 C++03 代码库,需要支持不同供应商的小工具,但一次只能支持一个。几个小工具之间的大部分功能重叠,但也有一些独占功能,而这些独占功能正在产生我需要解决的问题。
下面是一个使用预处理器条件的笨拙代码示例:
#define HW_TYPE1 0
#define HW_TYPE2 1
#define HW_TYPE HW_TYPE1
struct GadgetBase {
void FncA();
// Many common methods and functions
void FncZ();
};
#if HW_TYPE==HW_TYPE2
struct Gadget : public GadgetBase {
bool Bar() {return(true);}
};
#else
struct Gadget : public GadgetBase {
bool Foo() {return(false);}
};
#endif
Gadget A;
#if HW_TYPE==HW_TYPE2
bool Test() {return(A.Bar());}
#else
bool Test() {return(A.Foo());}
这是我在没有预处理器指令的情况下将上述代码转换为 C++ 模板的尝试。
由于在我的特定平台上Test() 的定义出错,以下代码无法编译,因为根据Type 的值,Foo() 或Bar() 未定义。
enum TypeE {
eType1,
eType2
};
const TypeE Type= eType1; // Set Global Type
// Common functions for both Gadgets
struct GadgetBase {
void FncA();
// Many common methods and functions
void FncZ();
};
// Unique functions for each gadget
template<TypeE E= eType1>
struct Gadget : public GadgetBase {
bool Foo() {return(false);}
};
template<>
struct Gadget<eType2> : public GadgetBase {
bool Bar() {return(true);}
};
Gadget<Type> A;
template<TypeE E= eType1>
bool Test() {return(A.Foo());}
template<>
bool Test() {return(A.Bar());}
我想使用模板来做到这一点,以在添加新类型或附加功能时减少代码更改的数量。目前有五种类型,预计很快还会再增加两种。预处理器实现代码很臭,我想在它变得笨拙之前清理它。
小工具代码仅占总代码库的一小部分,因此按小工具拆分整个项目可能也不理想。
即使每个项目只会使用一种类型,但未使用的类型仍然必须编译,我如何使用 C++03 最好地设计它(没有 constexpr、const if 等)?我完全错误地接近这个吗?我愿意进行彻底的检修。
编辑:Tomek 下面的解决方案让我怀疑它是否违反了 LSP。实际上,另一种看待这个问题的方法是让Test() 成为需要实现的接口的一部分。所以,这个例子可以重新考虑如下:
struct GadgetI {
virtual bool Test()=0;
};
template<TypeE E= eType1>
struct Gadget : public GadgetBase, public GadgetI {
bool Foo() {return(false);}
bool Test() {return Foo();}
};
template<>
struct Gadget<eType2> : public GadgetBase, public GadgetI {
bool Bar() {return(true);}
bool Test() {return Bar();}
};
template<>
struct Gadget<eType3> : public GadgetBase, public GadgetI {
bool Test() {} // Violation of LSP?
};
或与编辑后的示例类似:
template<typename T>
bool Test(T& o) {} // Violation?
template<>
bool Test(Gadget<eType1> &o) {return(o.Foo());}
template<>
bool Test(Gadget<eType2> &o) {return(o.Bar());}
Test(A);
我可能想多了,我只是不想现在糟糕的设计以后再咬我。
标签: c++ preprocessor template-specialization c++03