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) { ... }