专门化采用通用引用参数的函数模板



如何专门化接受通用引用参数的函数模板?

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 &参数(我不确定),但这意味着为所有参数的右值/左值引用的每一个可能组合复制foo中包含的所有代码,这是通用引用应该避免的。

有什么办法可以做到这一点吗?

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

我有一个可以连接到多个游戏服务器的程序,在大多数情况下,每个服务器都用相同的名称调用所有内容。然而,它们在一些方面的版本略有不同。这些东西可以是几个不同的类别:移动、项目等。我已经编写了一个通用的"移动字符串到移动枚举"函数集,供内部代码调用,我的服务器接口代码也有类似的功能。然而,有些服务器有自己的内部ID进行通信,有些服务器使用字符串,有些服务器在不同的情况下同时使用这两个ID。

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

我希望能够调用类似ServerNamespace::server_cast<Destination>(source)的东西。这将允许我从Move转换为std::stringServerMoveID。在内部,我可能需要复制(或从中移出),因为有些服务器要求我保留发送消息的历史记录。通用参考文献似乎是这个问题的明显解决方案。

我现在想到的头文件会简单地暴露如下:

namespace ServerNamespace {
template<typename Destination, typename Source>
Destination server_cast(Source && source);
}

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

在我看来,最好的解决方案是使用一个标签调度系统,在该系统中重载标签而不是实际类型:

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());
}

要做的最可扩展的事情是创建一个模板类专用化。

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

我之所以说这是最具可扩展性的,是因为您可以在任何地方添加专门化,无论是在定义Whatever的文件内部还是外部。

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

最新更新