我有一个用于将对象转换为字符串的模板函数(这是来自库,我无法更改它):
template <typename Q> std::wstring ToString(const Q& q) { static_assert(false, "Must specialise"); }
现在,我想用 std::vector<Gene>
的参数调用它, 其中Gene
是一个简单的类,其细节并不重要。当然,为此,我需要专门化模板,所以我这样做:
template<> std::wstring ToString(const std::vector<Gene>& q){...}
假设我有另一个类,Cell
,我想专门研究 ToString
std::vector<Cell>
的函数.我将不得不进行另一个明确的特化,与 std::vector<Gene>
具有相同的主体。版本。
转换 std::vector
的逻辑不依赖于实际内容类型(一个 int、一个 Gene
、一个 Cell
、另一个 std::vector
等),因此创建一个可以与任何 std::vector
一起使用的模板特化是有意义的.但我想不出一个简单的方法来做到这一点。现在,我目前有一个 VectorToString
函数,并转发来自 ToString(std::vector<Gene>>)
的调用和 ToString(std::vector<Cell>)
,但这仍然需要我为每种元素类型实现专门化。
因此,对于实际问题:是否可以为任意 std::vector
创建一个特化,我该怎么做?而且,作为一个额外的问题,这是否可以推广到任何支持 std::begin
的任意集合?和 std::end
?
我看过这个this question并尝试像这样声明特化:
template<typename E> std::wstring ToString<std::vector<E>>(const std::vector<E>& t){...}
但这在 C2768 中失败了:非法使用显式模板参数(“编译器无法确定函数定义是否应该是函数模板的显式特化,或者函数定义是否应该用于新的函数。”),这是有道理的,因为我们有相同的函数名称和模板参数数量,以及相似的签名。
供引用,我使用的是Visual C++ 2015 RC,原始模板函数来源于原生测试库。
最佳答案
你几乎做对了,但如果是你不应该专门化它们的函数,你应该像这样简单地重载它们:
template <typename Q> std::wstring ToString(const Q& q) {
return L"Original";
}
template<typename E> std::wstring ToString(const std::vector<E>& t) {
return L"overload";
}
参见 http://ideone.com/G3r0Vt一个正在运行的例子。
之所以可行,是因为在选择要调用的重载时,const std::vector<E>
被认为比const Q&
“更好”因此使用了重载。
在您的代码中使用这些方法时,您应该考虑 ADL .
关于c++ - 专门用于任意类型 vector 的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31234988/