I'm currently struggeling to make my concept check for overloaded operators. I managed to check for the "normal" <=> operator but I'm failing to check for the <=> operator which uses a std::shared_ptr and compares it with T
#include <compare>
#include <list>
#include <memory>
#include <concepts>
#include <stdexcept>
template<typename T>
concept Sortable_T = requires(T a, T b)
{
{ a <=> b } -> std::same_as<std::strong_ordering>;
{ a <=> std::shared_ptr(b) } -> std::same_as<std::strong_ordering>; //< this restraint is causing the problem
};
template<Sortable_T Element_T>
class SortableList
{
public:
//some other stuff goes first...
//list is actually private but to keep things simple we make it public here
std::list<Element_T> m_ls;
};
class MySortableElement
{
public:
auto operator<=>(const MySortableElement& rhs) const;
auto operator<=>(const std::shared_ptr<MySortableElement> rhs) const;
};
inline auto MySortableElement::operator<=>(const MySortableElement& rhs) const
{
//just a dummy
throw std::runtime_error("not implemented");
}
inline auto MySortableElement::operator<=>(const std::shared_ptr<MySortableElement> rhs) const
{
//just a dummy
throw std::runtime_error("not implemented");
}
Now if i invoke my class using
SortableList<MySortableElement> ls;
I'm getting an error that my concept is not satisfied. Do you know what I'm missing here? Godbolt Link: https://godbolt.org/z/c5nW71j7P
thx guys :)
First error is this:
<source>(15): note: the concept 'Sortable_T<MySortableElement>' evaluated to false
<source>(11): note: the concept 'std::same_as<void,std::strong_ordering>' evaluated to false
C:/data/msvc/14.39.33321-Pre/include\concepts(35): note: 'void' and 'std::strong_ordering' are different types
Your dummy implementations of operator<=>
are too dummy. There is no return
, so compiler deduces void
as return type. That's part of the reason why I don't like the Almost Always Auto approach.
Fix this by stating return type explicitly and/or implementing the operators in a way the compiler can deduce return type:
inline std::strong_ordering MySortableElement::operator<=>(const MySortableElement& rhs) const
{
//just a dummy
throw std::runtime_error("not implemented");
}
Then we see this error:
<source>(12): note: cannot deduce template arguments for 'std::shared_ptr'
std::shared_ptr
cannot be created from an object. It's constructor would take a pointer to an object. But that constructor itself is a template, so it cannot deduce type of std::shared_ptr
- you have to provide that explicitly.
{ a <=> std::shared_ptr<T>(&b) } -> std::same_as<std::strong_ordering>;
But the simpler option would be to just provide an object of this kind in the context of concept:
template<typename T>
concept Sortable_T = requires(T a, T b, std::shared_ptr<T> sptr)
{
{ a <=> b } -> std::same_as<std::strong_ordering>;
{ a <=> sptr } -> std::same_as<std::strong_ordering>;
};