【问题标题】:Specializating a function template that takes a universal reference parameter特化一个接受通用引用参数的函数模板
【发布时间】:2012-11-30 22:27:06
【问题描述】:

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

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 &amp;,所以参考折叠规则在这里对我没有帮助。我也许可以创建另一个采用Class &amp; 参数的专业化(我不确定),但这意味着为所有参数的右值/左值引用的每种可能组合复制foo 中包含的所有代码,这就是应该避免通用引用。

有没有办法做到这一点?

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

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

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

我希望能够拨打ServerNamespace::server_cast&lt;Destination&gt;(source) 之类的电话。这将允许我从Move 转换为std::stringServerMoveID。在内部,我可能需要制作副本(或从中移出),因为某些服务器要求我保留已发送消息的历史记录。通用引用似乎是解决这个问题的明显方法。

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

namespace ServerNamespace {

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

}

并且实现文件会将所有合法转换定义为模板特化。

【问题讨论】:

  • 应该ffoo 吗?另外,问题的背景是什么?您通常需要重载,而不是特化。
  • @GManNickG 也许我使用了错误的术语。我已经编辑了我的问题,更详细地说明了我要完成的工作
  • 有关此问题的非常好的文章,请参阅:mortoray.com/2013/06/03/…

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


【解决方案1】:

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

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

【讨论】:

  • 我得再考虑一下。
【解决方案2】:

最可扩展的事情是创建一个模板类特化。

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

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

我说这是最可扩展的原因是因为你可以在任何地方添加一个特化,无论是在定义什么的文件内部或外部。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2021-10-18
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多