使用 C++ 类模板的赋值运算符重载

Assignment operator overloading with a C++ class template

提问人:Petri Hirvonen 提问时间:12/10/2022 更新时间:12/10/2022 访问量:135

问:

我有一个 C++ 类模板,用于表示实值和复值 2D 字段。我想重载赋值运算符,以实现将数据从一个字段深度复制到另一个字段。目前,我已将数据限制为 或 。这意味着需要考虑 4 种不同的情况:-to-, -to-, -to- 和 -to-。我想通过取复杂值的实部来处理 -to- case;对于其他情况,这只是一个微不足道的任务。然而,我正在努力编译代码。以下是捕获问题的简单模拟版本:doublestd::complex<double>doubledoubledoublestd::complex<double>std::complex<double>doublestd::complex<double>std::complex<double>std::complex<double>double

#include <complex>

template<class T>
class Number {
  private:
  // should make Number<T>.m_value visible to Number<U>
  template<class U>
  friend class Number;
    T m_value;
  public:
    Number(const T value) : m_value{value} {
      // restricting the data
      static_assert(
        std::is_same<T, double>::value || std::is_same<T, std::complex<double>>::value,
        "Error: Number::Number: Only 'double' and 'std::complex<double>' are supported currently!"
      );
      // no copying allowed
      Number(const Number& orig) = delete;
    };
    // general case
    template<class U>
    Number<T>& operator=(const Number<U>& another) {
      m_value = another.m_value;
      return *this;
    }
};

// specialization
template<> Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) {
  m_value = std::real(another.m_value);
}

int main(int argc, char** argv) {
  const std::complex<double> I{0.0, 1.0};
  Number<double> n{0.0};
  Number<std::complex<double>> m{1.0 + I*2.0};
  n = m;
  return 0;
}

编译器输出:

g++    -c -g -std=c++14 -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.cpp
main.cpp:28:28: error: template-id ‘operator=<>’ for ‘Number<double>& Number<double>::operator=(const Number<std::complex<double> >&)’ does not match any template declaration
 template<> Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) {
                            ^
main.cpp:28:97: note: saw 1 ‘template<>’, need 2 for specializing a member function template
 template<> Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) {
                                                                                                 ^
main.cpp: In instantiation of ‘Number<T>& Number<T>::operator=(const Number<U>&) [with U = std::complex<double>; T = double]’:
main.cpp:36:5:   required from here
main.cpp:23:15: error: cannot convert ‘const std::complex<double>’ to ‘double’ in assignment
       m_value = another.m_value;
               ^

我似乎无法弄清楚如何实现分配重载。我试图为我的问题找到解决方案(例如,从“类似问题”中),并遇到了许多有用的问题和答案,并将其中的许多内容合并到我的代码中。然而,我还没有找到解决我的具体问题的方法,似乎被卡住了。有什么建议吗?谢谢!

C++ 模板 重载 assignment-operator

评论

0赞 PaulMcKenzie 12/10/2022
这意味着需要考虑 4 种不同的情况:double-to-double、double-to-std::complex<double>、std::complex<double>-to-double 和 std::complex<double>-to-std::complex<double> -- 这听起来像是一个错误避风港。赋值运算符也将被编译器使用,可能在你不知情的情况下。这就是为什么您会看到诸如将一种类型转换为另一种类型的函数,而不是依赖于赋值运算符和强制转换运算符的原因。to_whatever
0赞 user17732522 12/10/2022
在这种情况下,避免该问题的简单方法是始终采取 .它是非复杂类型的恒等函数。std::real
0赞 Petri Hirvonen 12/10/2022
@user17732522,但我不能在分配时接受 - 在这种情况下,我不想失去虚构的部分。std::realstd::complex<double>std::complex<double>
0赞 Petri Hirvonen 12/10/2022
@PaulMcKenzie,你可能是对的。但是,如果我尝试实现用于复制数据的通用函数和专用函数,我是否会面临相同的编译错误?
1赞 PaulMcKenzie 12/10/2022
@PetriHirvonen -- 最后一点,如果程序员可以做到这一点:那么他们希望这也可用:Foo f1; Foo f2; f2 = f1;Foo f1; Foo f2 = f1;

答:

2赞 dewaffled 12/10/2022 #1

它实际上说出了它在行中的期望:

main.cpp:28:97: note: saw 1 ‘template<>’, need 2 for specializing a member function template

您需要一个“模板<>”来专攻类模板,还需要一个专攻成员函数模板:TU

template<>
template<>
Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) { ... }

评论

0赞 Petri Hirvonen 12/14/2022
感谢您@dewaffled的回答,它奏效了!编译器可能经常非常直接地说出它想要的东西,但无论我是否理解,这都是另一回事......我绝对没有猜到这是需要的。