是否可以使用标签分派来确定返回类型

时间:2012-08-20 14:09:13

标签: c++ templates

Switch passed type from template中提到了代码发送。

是否有可能(以及如何)做类似的事情:

struct Tag1 {};
struct Tag2 {};

template<class T, typename R>
R get();

template<>
double get<Tag1>() {return 1.3;}

template<>
char const *get<Tag2>() {return "hello";}

double aDouble = get<Tag1>();
char const *aString = get<Tag2>();

上面的代码导致编译器抱怨对重载函数的模糊调用,但我希望最后两行能够传达使用意图。

THX

3 个答案:

答案 0 :(得分:3)

你可以使用std::enable_ifstd::is_same(C ++ 11),或者他们的提升等价物:

template <typename Tag>
typename std::enable_if<std::is_same<Tag, Tag1>::value, double>::type get()
{ ... }

template <typename Tag>
typename std::enable_if<std::is_same<Tag, Tag2>::value, char const *>::type get()
{ ... }

答案 1 :(得分:1)

具有不同数量的模板参数的函数模板彼此重载,因此您不是定义特化而是重载。这样的事情应该有效:

struct Tag1 {};
struct Tag2 {};

template<class T> struct MapResult;

template<> struct MapResult<Tag1> { typedef double Result; };
template<> struct MapResult<Tag2> { typedef char const* Result; };

template<class T>
typename MapResult<T>::Result get();

template<> double get<Tag1>() {return 1.2;}
template<> char const *get<Tag2>() {return "hello";}

答案 2 :(得分:0)

get的第二个模板参数无法推断,因为它只显示为返回类型:谁说get<Tag1>()是对get<Tag1, double>的具体调用,而不是get<Tag1, int>?如果你打电话,例如get<Tag1, double>()然后呼叫将被解析为正确的专业化。

但是我怀疑你并不希望get成为具有两个模板参数的函数模板:返回类型可能是第一个参数的函数。因此,我建议您像这样声明get

namespace result_of {

template<typename T>
struct get;

}

template<typename T>
typename result_of::get<T>::type get();

其中result_of::get将是计算预期结果类型的元函数。为了使事情变得更简单,我们将把所有鸡蛋放在get篮子里,而不是专门化功能模板{/ 1>:

result_of::get

一般来说,专门化类模板而不是函数模板更为常见,并且通过让函数模板将其实现完全委托给类模板,通常可以使得需要专门化函数模板的情况变得更简单。