Suppose I have a template class ComplexNumber
that looks like this:
template<typename T>
class ComplexNumber {
public:
ComplexNumber() : A(), B() {}
ComplexNumber(const T& r, const T& i) : A(r), B(i) {}
~ComplexNumber(){}
void setA(T A1);
void SetB(T B1);
T getA() const {return A;};
T getB()const {return B;};
ComplexNumber<T> operator (const ComplexNumber<T> &C){
return ComplexNumber<T>( A C.getA(), B C.getB());
}
ComplexNumber<T> operator -(const ComplexNumber<T> &C) {
return ComplexNumber<T>(A - C.getA(), B - C.getB());
};
friend ostream & operator << (ostream &out, const ComplexNumber<T> &c)
{
out << c.A;
out << " i" << c.B << endl;
return out;
}
private:
T A;
T B;
};
And a main()
that constructs these complex numbers and stores them into a std::vector
:
ComplexNumber<int> complex1(10, 3);
ComplexNumber<int> complex2(2, 56);
ComplexNumber<int> complex3(3, 55);
vector<ComplexNumber<int>> testVector;
testVector.push_back(complex1);
testVector.push_back(complex2);
testVector.push_back(complex3);
If I want to sort testVector
from highest to lowest, comparing the real parts and then comparing the imaginary ones if the real parts are equal, how would I go about doing that?
I am unable to use the standard std::sort()
function. I would like to do this using a method or functor.
EDIT: Trying to add it to a function:
//This method is outside the scope of the ComplexNumber class
auto compare_by_magnitude = [](const auto& a, const auto& b) {
return a.A*a.A a.B*a.B < b.A*b.A b.B*b.B;
};
void sortComplex(vector<ComplexNumber<int>> &c){
std::sort(c.begin(),c.end(),compare_by_magnitude);
}
My error messages:
FAILED: complexNumber.exe
cmd.exe /C "cd . && C:\PROGRA~1\JETBRA~1\CLION2~1.3\bin\mingw\bin\G__~1.EXE -g CMakeFiles/complexNumber.dir/main.cpp.obj CMakeFiles/complexNumber.dir/ComplexNumber.cpp.obj -o complexNumber.exe -Wl,--out-implib,libcomplexNumber.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
C:\Program Files\JetBrains\CLion 2021.3.3\bin\mingw\bin/ld.exe: CMakeFiles/complexNumber.dir/ComplexNumber.cpp.obj: in function `ComplexNumber<int>::~ComplexNumber()':
C:/PROGRA~1/JETBRA~1/CLION2~1.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c /bits/stl_heap.h:223: multiple definition of `sortComplex(std::vector<ComplexNumber<int>, std::allocator<ComplexNumber<int> > >&)'; CMakeFiles/complexNumber.dir/main.cpp.obj:C:/Users/elira/Desktop/complexNumber/complexNumber/ComplexNumber.h:51: first defined here
C:\Program Files\JetBrains\CLion 2021.3.3\bin\mingw\bin/ld.exe: CMakeFiles/complexNumber.dir/ComplexNumber.cpp.obj:C:/Users/elira/Desktop/complexNumber/complexNumber/ComplexNumber.h:48: multiple definition of `compare_by_magnitude'; CMakeFiles/complexNumber.dir/main.cpp.obj:C:/Users/elira/Desktop/complexNumber/complexNumber/ComplexNumber.h:48: first defined here
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
CodePudding user response:
In order to work with std::sort()
, your class needs at least operator<
defined:
bool operator< (const ComplexNumber<T>& other) const {
return A < other.A || (A == other.A && B < other.B);
}
It's also good practice to define operator==
, but std::sort()
will work with operator<
alone.
When I make the above addition to your class, this main()
sorts by real and then imaginary, in ascending order:
int main() {
vector<ComplexNumber<float>> vc = { {4, 5}, {1, 3}, {4, 2} };
copy(vc.begin(), vc.end(), ostream_iterator<ComplexNumber<float>>(cout, " "));
cout << endl;
sort(vc.begin(), vc.end());
copy(vc.begin(), vc.end(), ostream_iterator<ComplexNumber<float>>(cout, " "));
cout << endl;
}
But, you mentioned you want to sort in descending order. It's bad practice to define operator<
in the reverse sense within the class, as you can imagine, so you can instead pass a comparison function to std::sort()
that reverses the sense of the comparison:
sort(vc.begin(), vc.end(),
[](const ComplexNumber<float> &f1, const ComplexNumber<float> &f2)
{ return ! (f1 < f2); }
);
These compilation and semantic concerns aside, when I look at the errors you're posting, I see a link error, and it appears that your class is being defined multiple times. This suggests that the include file which defines your class is missing an include guard.