Home > Blockchain >  Assignment operator overloading with a C class template
Assignment operator overloading with a C class template

Time:12-14

I have a C class template for representing real- and complex valued 2D fields. I'd like to overload the assignment operator to achieve deep-copying the data from one field to another. For now, I've restricted the data to either double or std::complex<double>. This means there are 4 different cases to consider: double-to-double, double-to-std::complex<double>, std::complex<double>-to-double and std::complex<double>-to-std::complex<double>. I want to handle the std::complex<double>-to-double case by taking the real part of the complex value; for the other cases it's just a trivial assignment. I'm however struggling to get the code to compile. The following is a simple mock version that captures the issues:

#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;
}

Compiler output:

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;
               ^

I can't seem to figure out how to implement the assignment overloads. I have tried to find a solution for my problem (e.g. from "Similar questions") and have come across many helpful questions and answers, and have incorporated many things from them to my code. I however haven't found a solution to my specific problem and seem to be stuck. Any suggestions? Thanks!

CodePudding user response:

It actually says what it expects in the line:

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

You need one 'template<>' to specialize T in class template and one more to specialize U in member function template:

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