带模板函数的转换运算符

时间:2013-08-07 14:45:56

标签: c++ templates stl

我有一个带有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一样。有没有办法做到这一点?

3 个答案:

答案 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);