9

如何特殊化采用通用参考参数的函数模板?指定采用通用参考参数的函数模板

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中包含的所有代码,以获取所有参数的rvalue/lvalue引用的每种可能组合,这是通用引用的假设避免。

有没有办法做到这一点?

更具体谈谈我的问题的情况下,有一个更好的办法来解决这个问题:

我有一个可以连接到多个游戏服务器程序,每个服务器,在大多数情况下,调用由一切同名。但是,它们的几个版本略有不同。有几个不同的类别,这些东西可以是:移动,项目等。我写了一个通用的“移动字符串来移动枚举”功能的内部代码调用,并且我的服务器接口代码也有类似功能。但是,有些服务器有自己的内部ID,它们可以通信,有些使用字符串,有些使用两种情况。

现在我想要做的是让这个更通用一点。

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

头文件我在想,现在只想这暴露:

namespace ServerNamespace { 

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

} 

和实现文件将定义所有合法的转换为模板特。

+1

应该'f'是'foo'?此外,问题的背景是什么?你通常需要重载,而不是专门化。 – GManNickG

+0

@GManNickG也许我使用了错误的术语。我已经编辑了我的问题,并详细说明了我正在努力完成的任务 –

+0

对于关于此问题的非常好的文章,请参阅:https://mortoray.com/2013/06/03/overriding-the-broken-universal-reference -t/ –

回答

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

我得多想一想。 –

1

最具扩展性的事情就是创建一个模板类专业化。

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

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

我说这是最具扩展性的原因是因为您可以在定义任何内容的文件内部或外部的任何地方添加专门化。

这是对Pubby建议的标签分发解决方案的免费而不是排他性的。