我有一个模板函数,用于将对象转换为字符串(这是来自库,我不能改变它):
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
的{{1}}函数。我必须使用与std::vector<Cell>
版本相同的主体进行另一个明确的专门化。
转换std::vector<Gene>
的逻辑不依赖于实际的内容类型(int,std::vector
,Gene
,其他Cell
等),因此创建一个可以与任何std::vector
一起使用的模板专业化是有意义的。但我无法找到一种简单的方法来做到这一点。目前,我目前有一个std::vector
功能,并转发来自VectorToString
和ToString(std::vector<Gene>>)
的来电,但这仍然要求我为每种元素类型实施专门化。
那么,对于实际的问题:是否可以为任意ToString(std::vector<Cell>)
创建单一的专业化,我将如何做到这一点?而且,作为一个奖金问题,这可以推广到任何支持std::vector
和std::begin
的任意集合吗?
我看过这个this question并试图宣布这样的专业化:
std::end
但这与C2768失败:非法使用显式模板参数(&#34;编译器无法确定函数定义是否应该是函数模板的显式特化,或者函数定义是否应该是对于一个新的功能。&#34;),这是有道理的,因为我们有相同的功能名称和模板参数的数量,以及类似的签名。
供参考,我使用的是Visual C ++ 2015 RC,原始模板函数来自本机测试库。
答案 0 :(得分:2)
你差不多正确地做了但是如果你不应该把它们专门化,你应该像这样重载它们:
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。
答案 1 :(得分:2)
我有下一个例子给你。尝试使用下一个:
template<typename E> std::string ToString(const std::vector<E>& t)
{
std::stringstream resStr;
for (const E& element : t)
{
resStr << element << " ";
}
return resStr.str();
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> v1;
v1.push_back(22);
v1.push_back(33);
std::vector<double> v2;
v2.push_back(54.656);
v2.push_back(44.656);
auto strInt = ToString(v1);
auto strDouble = ToString(v2);
return 0;
}
答案 2 :(得分:0)
我将以下内容用于基类型的向量:
namespace Microsoft
{
namespace VisualStudio
{
namespace CppUnitTestFramework
{
template<typename E>
std::wstring ToString(const std::vector<E> & t)
{
std::wstringstream result;
result << L"Size: " << t.size();
if (t.size())
{
result << L", Elements: ";
for (const auto & element : t)
{
result << L"{ " << element << L" } ";
}
}
return result.str();
}
}
}
}
对于失败的测试,您可以清楚地看到矢量的大小及其包含的元素。为了您的目的,您可以使用:
namespace Microsoft
{
namespace VisualStudio
{
namespace CppUnitTestFramework
{
template<typename E>
std::wstring ToString(const std::vector<E> & t)
{
return L"Size: " + std::to_wstring(t.size());
}
}
}
}