专门化一个带有通用引用参数的函数模板

时间:2012-11-30 22:27:07

标签: c++ templates c++11 template-specialization universal-reference

如何专门化一个采用通用参考参数的函数模板?

foo.hpp:

template<typename T>
void foo(T && t)    // universal reference parameter

Foo.cpp中

template<>
void foo<Class>(Class && class) {
    // do something complicated
}

此处,Class不再是推断类型,因此恰好是Class;它不可能是Class &,所以参考折叠规则对我没有帮助。我也许可以创建另一个带有Class &参数的专门化(我不确定),但是这意味着为每个可能的rvalue / lvalue引用组合重复foo中包含的所有代码所有参数,这是普遍的参考应该避免的。

有没有办法实现这个目标?

如果有更好的解决方法,请更具体地说明我的问题:

我有一个可以连接到多个游戏服务器的程序,并且每个服务器在大多数情况下都会使用相同的名称调用所有内容。但是,对于一些事情,它们的版本略有不同。这些东西可以有几个不同的类别:移动,项目等。我写了一个通用的&#34;移动字符串来移动枚举&#34;内部代码调用的函数集,我的服务器接口代码具有类似的功能。但是,有些服务器有自己的内部ID,它们与之通信,有些使用字符串,有些服务器在不同情况下使用。

现在我想做的是让它更通用一点。

我希望能够调用类似ServerNamespace::server_cast<Destination>(source)的内容。这样我就可以从Move投射到std::stringServerMoveID。在内部,我可能需要制作副本(或从中移动),因为某些服务器要求我保留已发送消息的历史记录。通用引用似乎是解决这个问题的明显方法。

我现在想到的头文件只会暴露出这个:

namespace ServerNamespace {

template<typename Destination, typename Source>
Destination server_cast(Source && source);

}

实施文件会将所有合法转化定义为模板专业化。

2 个答案:

答案 0 :(得分:2)

我认为最好的解决方案是使用标签调度系统,在标签调度系统上重载标签而不是实际类型:

struct foo {
    struct tag {};
};

struct bar {
    struct tag {};
};

template<typename Destination, typename Source>
Destination server_cast(Source && source, foo::tag) {
    // foo
}

template<typename Destination, typename Source>
Destination server_cast(Source && source, bar::tag) {
    // bar
}

template<typename Destination, typename Source>
Destination server_cast(Source && source) {
    return server_cast<Destination>(std::forward<Source>(source), typename std::remove_reference<Source>::type::tag());
}

答案 1 :(得分:1)

最易扩展的事情是创建模板类专门化。

template< class X > struct Whatever {
    void f(){ ... }
};

template<> struct Whatever<UserType> {
    void f(){ ... }
};

我说这是最具扩展性的原因是因为您可以在定义Whatever的文件内部或外部的任何位置添加特化。

这是Pubby建议的标签发送解决方案的补充,而非排他性。