C ++模板:我可以调用名称基于输入类型名称的函数吗?

时间:2016-11-01 16:10:57

标签: c++ templates

我有一个代码库,其中包含许多返回单例的枚举相关函数。他们的名字是公式化的:

enum Foo {...};
const MySingleton* Foo_Singleton();
enum Bar {...};
const MySingleton* Bar_Singleton();
...

是否可以编写一个C ++模板,在没有明确列出所有选项的情况下选择正确的getter函数名?

template <typename EnumT>
inline const MySingleton* Get() {
  return EnumT ## _Singleton();
}

我知道我在这里使用了一个荒谬的预处理器指令,但我希望它能传达我的目标。我知道我可以为每个枚举写一个重载,但是它们中有很多并且维护很难,所以我宁愿避免这种解决方案。

3 个答案:

答案 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 )