使用带有隐式转换的非基础数据类型的operator <<时出错

dte*_*ell 6 c++ template-argument-deduction

我有一个结构作为其他类型的包装器,如下所示:

template<typename T>
struct A {
  A& operator=(const T& value){
    m_value = value;
    return *this;
  }

  operator T() const {
    return m_value;
  }

private:
  T m_value;
};
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

int main() {
  A<int> a;
  a = 5;                  // Copy assignment constructor
  std::cout << a << "\n"; // Implicit conversion to int
}
Run Code Online (Sandbox Code Playgroud)

它按预期工作.使用非基本类型时出现问题,如下例所示:

int main() {
  A<std::complex<int>> c;
  c = std::complex<int>(2, 2);  
  std::cout << c << "\n";
}
Run Code Online (Sandbox Code Playgroud)

上面的代码段会引发invalid operands to binary expression错误.

为什么会出现此错误?为什么不超载运营<<的std::complex<int>与隐式转换使用A<std::complex<int>>?

Nat*_*ica 6

流运算符std::complex是模板函数.除非您std::complex在模板参数推断中实际没有转换,否则不会调用它们.这意味着编译器将找不到合适的重载来打印aA<std::complex<int>>

你是第一个工作的情况,因为std::basic_ostream::operator <<重载需要一个int,你被允许一个用户定义的转换是重载决议.


作为一个工作环,你可以定义自己operator <<的包装器并转发到底层类型operator <<.那看起来像

template<typename T>
std::ostream& operator <<(std::ostream& os, const A<T>& a)
{
    return os << static_cast<T>(a);
}
Run Code Online (Sandbox Code Playgroud)

  • @datell,最简单的解决方法是定义`template <typename T> operator <<(std :: ostream&,A <T> const&);`. (2认同)