我有一个代码库,其中包含许多返回单例的枚举相关函数。他们的名字是公式化的:
enum Foo {...};
const MySingleton* Foo_Singleton();
enum Bar {...};
const MySingleton* Bar_Singleton();
...
是否可以编写一个C ++模板,在没有明确列出所有选项的情况下选择正确的getter函数名?
template <typename EnumT>
inline const MySingleton* Get() {
return EnumT ## _Singleton();
}
我知道我在这里使用了一个荒谬的预处理器指令,但我希望它能传达我的目标。我知道我可以为每个枚举写一个重载,但是它们中有很多并且维护很难,所以我宁愿避免这种解决方案。
答案 0 :(得分:4)
最简单的方法是更改命名政策:
enum Foo {...};
const MySingleton* Get(Foo); // instead of const MySingleton* Foo_Singleton();
enum Bar {...};
const MySingleton* Get(Bar); // instead of const MySingleton* Bar_Singleton();
所涉及的机制称为标签调度。现在你可以通过简单的方式得到合适的单例实例:
Get(Foo{});
答案 1 :(得分:2)
其中一种可能性:
// template specification (to be specialized)
template <typename EnumT>
const MySingleton* Get();
#define JOIN_IMPL(a, b) a ## b
#define JOIN(a, b) JOIN_IMPL(a, b)
// template specialization for particular enum
#define DEFINE_GET_SINGLETON(EnumT) \
template<> \
inline const MySingleton* Get<EnumT>() { \
return JOIN(EnumT, _Singleton)(); \
}
DEFINE_GET_SINGLETON(Foo)
DEFINE_GET_SINGLETON(Bar)
通过使用宏,您可以节省一些输入(以调试为代价 - 大多数调试器无法单步执行宏)。
答案 2 :(得分:1)
我怀疑在这里可以使用混合宏和模板的解决方案。
基于模板的解决方案可以使用,但需要为每种类型声明包装函数。
首先,定义这些功能:
const MySingleton* GetSingleton( Foo* var ) { return Foo_Singleton(); }
const MySingleton* GetSingleton( Bar* var ) { return Bar_Singleton(); }
然后就这样做:
template <typename EnumT>
inline const MySingleton* Get() {
EnumT e;
return GetSingleton( &e );
}
然后编译器会选择相应的GetSingleton
,具体取决于EnumT
。
注意,您可以使用宏来声明该功能,但我不确定它是否会非常有用:
#define DECLARE_WRAPPER(TYPE) const MySingleton* GetSingleton( TYPE* var ) { return TYPE##_Singleton(); }
DECLARE_WRAPPER( Foo )
DECLARE_WRAPPER( Bar )