鉴于此代码:
#include <string>
#include <vector>
#include <iostream>
template <typename T>
std::string stringify(const T&) {
return "{?}";
}
template <typename T>
std::string proxy(const T& in) {
return stringify(in);
}
// trying to specialize "stringify()"
template <typename T>
std::string stringify(const std::vector<T>& in) {
return "vector specialization!";
}
template <>
std::string stringify(const std::vector<int>& in) {
return "INT vector specialization!";
}
int main() {
std::cout << proxy(1); // calls the 1st
std::vector<int> intVec;
std::cout << proxy(intVec); // calls the 1st
std::vector<double> dblVec;
std::cout << proxy(dblVec); // calls the 1st
return 0;
}
如何在stringify()
之后为vector<>
专门化proxy<>
?
目前我得到{?}{?}{?}
如果我删除了这个 - stringify(const std::vector<T>& in)
,则vector<int>
开始被调用,因为它将是第一个的专门化。
然后我会得到{?}INT vector specialization!{?}
有没有办法调用proxy()
中的2个向量特化字符串化函数中的任何一个 - 如果它们是最后定义的 - 在proxy()
函数之后?
有没有办法部分专注于vector<>
,仍然可以从proxy<>
调用?
我不想专注于vector<int>
,vector<double>
,vector<UserType>
......
编辑:忘记提及C++98
答案 0 :(得分:3)
首先,避免专门化功能模板,更喜欢重载。有关潜在的陷阱,请参阅Herb Sutter's article。
其次,您遇到的问题涉及名称查找如何在函数模板中为依赖名称工作。在proxy<T>
内,stringify
是一个从属名称 - 它取决于T
。该名称将在模板定义点(将查找stringify<T>(const T&)
而不是其他重载)中查找,并再次在参数的关联命名空间中实例化时({{1} }})。这些查找都没有找到您的其他功能。
这是我们可以利用的查找的第二部分 - 依赖于参数的查找。让我们把所有东西都放在一个命名空间中(我任意命名std
,随意重命名):
N
好的,到目前为止,我们完全没有改变。在所有情况下,我们仍会获得namespace N {
struct helper { };
template <typename T>
std::string stringify(helper, const T&) {
return "{?}";
}
}
template <typename T>
std::string proxy(const T& in) {
return stringify(N::helper(), in);
}
。但是现在我们可以在{?}
的定义之后仍然在stringify
中继续{strong>重载(非专业化)proxy
:
namespace N {
template <typename T>
std::string stringify(helper, const std::vector<T>& ) {
return "vector overload!";
}
std::string stringify(helper, const std::vector<int>& ) {
return "INT vector overload!";
}
}
这两个重载将在名称查找的第二阶段找到,因为N
是helper
的关联命名空间。现在proxy(intVFec)
将找到stringify
的所有三个重载,而不仅仅是一个。{1}}。现在您的代码打印出来了:
{?}INT vector overload!vector overload!
根据需要。以上都不需要C ++ 11。