В настоящее время я изо всех сил пытаюсь проверить свою концепцию на наличие перегруженных операторов. Мне удалось проверить «нормальный» оператор <=>, но мне не удалось проверить оператор <=>, который использует std::shared_ptr и сравнивает его с 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");
}
Теперь, если я вызову свой класс, используя
SortableList<MySortableElement> ls;
Я получаю сообщение об ошибке, что моя концепция не удовлетворена. Знаешь, чего мне здесь не хватает? Ссылка на Godbolt: https://godbolt.org/z/c5nW71j7P
спасибо, ребята :)
MySortableElement::operator<=>
имеют возвращаемый тип void
, потому что нет оператора возврата. Воспроизведение слишком упрощено?
«Мне удалось проверить наличие «нормального» оператора <=>» не с помощью показанного кода. Хотя нет проблем, код полон и соответствует ссылке godbolt.
Первая ошибка заключается в следующем:
<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
Ваши фиктивные реализации operator<=>
слишком фиктивные. return
нет, поэтому компилятор выводит void
как возвращаемый тип. Это одна из причин, почему мне не нравится подход «Почти всегда автоматически».
Исправьте это, явно указав тип возвращаемого значения и/или реализовав операторы таким образом, чтобы компилятор мог определить тип возвращаемого значения:
inline std::strong_ordering MySortableElement::operator<=>(const MySortableElement& rhs) const
{
//just a dummy
throw std::runtime_error("not implemented");
}
Затем мы видим эту ошибку:
<source>(12): note: cannot deduce template arguments for 'std::shared_ptr'
std::shared_ptr
не может быть создан из объекта. Его конструктор будет принимать указатель на объект. Но этот конструктор сам по себе является шаблоном, поэтому он не может определить тип std::shared_ptr
— вам нужно указать это явно.
{ a <=> std::shared_ptr<T>(&b) } -> std::same_as<std::strong_ordering>;
Но более простым вариантом было бы просто предоставить объект такого типа в контексте концепции:
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>;
};
T b
можно даже отбросить и просто использовать a <=> a
.
Две проблемы в коде. Вы позволяете вывести тип возвращаемого значения, но return
нет, поэтому он выводится как void
. Далее мне пришлось изменить a <=> std::shared_ptr(b)
, потому что shared_ptr
конструктор не делает CTAD.
Это компилирует:
#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::make_shared<T>(b) } -> std::same_as<std::strong_ordering>;
};
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:
std::strong_ordering operator<=>(const MySortableElement& rhs) const;
std::strong_ordering operator<=>(const std::shared_ptr<MySortableElement> rhs) const;
};
inline std::strong_ordering MySortableElement::operator<=>(const MySortableElement& rhs) const
{
//just a dummy
throw std::runtime_error("not implemented");
}
inline std::strong_ordering MySortableElement::operator<=>(const std::shared_ptr<MySortableElement> rhs) const
{
//just a dummy
throw std::runtime_error("not implemented");
}
int main()
{
SortableList<MySortableElement> ls;
return 0;
}
«a <=> std::make_shared<T>(b)
» Требовалось бы, чтобы T
можно было копировать, если std::make_shared
ограничено ;-)
std::shared_ptr(b)
выглядит не так. Возможно вы имеете в видуstd::shared_ptr<T>{}
?