2

标记调度在Switch 传递类型 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>();

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

谢谢

4

3 回答 3

3

您可以使用std::enable_ifand std::is_same(C++11),或者它们的 boost 等价物:

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()
{ ... }
于 2012-08-20T14:17:21.287 回答
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";}
于 2012-08-20T14:37:24.710 回答
0

get无法推断出第二个模板参数,因为它只显示为返回类型:谁说这get<Tag1>()是对特定的调用get<Tag1, double>而不是对 eg的调用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();

whereresult_of::get将是计算预期结果类型的元函数。get为了让事情更简单,我们将把所有的鸡蛋都放在result_of::get篮子里,而不是专门化函数模板:

namespace result_of {

template<typename T>
struct get;

}

template<typename T>
typename result_of::get<T>::type get()
{ return result_of::get<T>::apply(); }

namespace result_of {

template<>
struct get<Tag1> {
    typedef double type;

    static type apply()
    { return 1.3; }
};

template<>
struct get<Tag2> {
    typedef const char* type;

    static type apply()
    { return "hello"; }
};

}

一般来说,特化类模板而不是函数模板更为常见,并且看起来需要特化函数模板的情况通常通过让函数模板将其实现完全委托给类模板来简化。

于 2012-08-20T15:23:25.817 回答