我有一个带有std::string
转换运算符的类。除了函数接收std::basic_string<T>
(在T
上模板化)之外,它适用于所有内容。
#include <string>
struct A{
operator std::string(){return std::string();}
};
void F(const std::basic_string<char> &){}
template<typename T> void G(const std::basic_string<T> &) {}
int main(){
A a;
F(a); // Works!
G(a); // Error!
return 0; // because otherwise I'll get a lot of comments :)
}
我收到的错误是
error: no matching function for call to 'G(A&)'
note: candidate is:
note: template<class T> void G(const std::basic_string<_CharT>&)
现在,我知道我可以将G
定义为结构A
中的朋友并且它可以正常工作,但我的问题是有很多已经存在的stl函数并且接收{{1 (例如,std::basic_string<T>
打印函数,或比较运算符,或许多其他函数。
我真的希望能够使用operator<<
,就好像它是A
一样。有没有办法做到这一点?
答案 0 :(得分:2)
编译器无法推断出那么远;您必须显式调用强制转换运算符或明确指定模板参数:
G(static_cast<std::string>(a));
G<char>(a);
要理解为什么编译器不能同时执行用户定义的转换和模板参数推导,让我们举个例子:
template<typename T>
struct Number {
Number(double n) {};
Number(int n) {};
};
struct A{
operator Number<double>(){return Number<double>(1.);}
operator Number<int>(){return Number<int>(1);}
};
template<typename T> void G(Number<T>& number) { }
int main(){
A a;
G(a); // What do I do ?!
return 0;
}
在这种情况下编译器应该做什么?
答案 1 :(得分:2)
我真的希望能够像使用
std::string
一样使用A.有没有办法做到这一点?
是的,但你确定你真的想要这个吗?解决方案是:
struct A : public std::string {
};
但请记住std::string
没有virtual
析构函数,因此不能多态使用。 你已被警告!!!
str()
是一个更好的解决方案,当您希望将A
传递给采用std::basic_string<T>
的函数时,您可以明确。
答案 2 :(得分:1)
执行模板参数推断时,不会考虑用户定义的转换。
G
的明确专业化将起作用。
G<char>(a);