I'm trying to use std::sort() on a vector of shared_ptr<Card>. I created a function that implements the spaceship operator. I couldn't simply overload it on Card because the container refers to shared_ptr<Card>, not the Card itself. The std::sort() works with a function that implements a < comparison, but not a <=> comparison.
std::strong_ordering compare(std::shared_ptr<Card> left, std::shared_ptr<Card> right)
{
int leftManaCost = left->getManaCost();
int rightManaCost = right->getManaCost();
return std::tie(leftManaCost) <=> std::tie(rightManaCost);
}
bool compareJustMinor(std::shared_ptr<Card> left, std::shared_ptr<Card> right)
{
return (left->getManaCost() < right->getManaCost());
}
void Deck::Print()
{
std::sort(cards.begin(), cards.end(), compare); //works with compareJustMinor
I´ll summarize the information that may be relevant
Deckis a class that has a memberstd::vector<std::shared_ptr<Card>> cards;Cardis a base class with a pure virtual function
I'm kind of rusty on C++ and new to the <=> operator, so I may be missing/misunderstanding something obvious.
Here is the error log:
>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7363,21): error C2678: binary '!': no operator found which takes a left-hand operand of type 'std::strong_ordering' (or there is no acceptable conversion)
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7355,1): message : could be 'built-in C++ operator!(bool)'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7355,1): message : while trying to match the argument list '(std::strong_ordering)'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7425): message : see reference to function template instantiation 'std::pair<_RanIt,_RanIt> std::_Partition_by_median_guess_unchecked<_RanIt,std::strong_ordering(__cdecl *)(std::shared_ptr<Card>,std::shared_ptr<Card>)>(_RanIt,_RanIt,_Pr)' being compiled
1> with
1> [
1> _RanIt=std::shared_ptr<Card> *,
1> _Pr=std::strong_ordering (__cdecl *)(std::shared_ptr<Card>,std::shared_ptr<Card>)
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7455): message : see reference to function template instantiation 'void std::_Sort_unchecked<std::shared_ptr<Card>*,std::strong_ordering(__cdecl *)(std::shared_ptr<Card>,std::shared_ptr<Card>)>(_RanIt,_RanIt,__int64,_Pr)' being compiled
1> with
1> [
1> _RanIt=std::shared_ptr<Card> *,
1> _Pr=std::strong_ordering (__cdecl *)(std::shared_ptr<Card>,std::shared_ptr<Card>)
1> ]
1>D:\C++ Projects\MTG\Deck.cpp(99): message : see reference to function template instantiation 'void std::sort<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,std::strong_ordering(__cdecl *)(std::shared_ptr<Card>,std::shared_ptr<Card>)>(const _RanIt,const _RanIt,_Pr)' being compiled
1> with
1> [
1> _Ty=std::shared_ptr<Card>,
1> _RanIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<std::shared_ptr<Card>>>>,
1> _Pr=std::strong_ordering (__cdecl *)(std::shared_ptr<Card>,std::shared_ptr<Card>)
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7363,15): error C2088: '!': illegal for struct
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7367,81): error C2678: binary '!': no operator found which takes a left-hand operand of type 'std::strong_ordering' (or there is no acceptable conversion)
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7355,1): message : could be 'built-in C++ operator!(bool)'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7355,1): message : while trying to match the argument list '(std::strong_ordering)'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7367,75): error C2088: '!': illegal for struct
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7378,29): error C2451: a conditional expression of type 'std::strong_ordering' is not valid
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7378,29): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7391,29): error C2451: a conditional expression of type 'std::strong_ordering' is not valid
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\algorithm(7391,29): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
The comparator which
std::sortexpects should satisfy the requirement of a Compare, i.e. it should behave like a<operator.Your code should work if you pass
compare_just_minortostd::sortinstead ofcompare. Here is a working example:See live example at Compiler Explorer.
That being said, the
<=>operator is normally defined directly for a class, not for a smart pointer of that class:The use of
std::shared_ptris also questionable. Chances are you could just usestd::vector<Card>directly.See also: What are the basic rules and idioms for operator overloading?