Исходя из C++17 и пытаясь интегрировать оператор. Я наткнулся на загадку. Кажется, не существует способа реализовать универсальный класс, подобный контейнеру, где его T является взаимно рекурсивным std::variant. С обычным набором операторов сравнения до C++20 все в порядке, вероятно, потому, что они полностью определены в любой момент времени. Событие, если T заранее объявлено в точке объявления шаблона.
Я собрал упрощенный набор тестовых примеров, которые делают эту проблему очевидной. Здесь Array и Map не являются шаблонными, а представляют собой простые структуры, для простоты основанные на std::vector и std::map. Это по-прежнему ясно показывает, что тип категории сравнения должен быть известен заранее. Или оператор придется вообще исключить, но есть недостатки (доступно на godbolt.com).
Исходя из C++17 и пытаясь интегрировать оператор. Я наткнулся на загадку. Кажется, не существует способа реализовать универсальный класс, подобный контейнеру, где его T является взаимно рекурсивным std::variant. С обычным набором операторов сравнения до C++20 все в порядке, вероятно, потому, что они полностью определены в любой момент времени. Событие, если T заранее объявлено в точке объявления шаблона. Я собрал упрощенный набор тестовых примеров, которые делают эту проблему очевидной. Здесь Array и Map не являются шаблонными, а представляют собой простые структуры, для простоты основанные на std::vector и std::map. Это по-прежнему ясно показывает, что тип категории сравнения должен быть известен заранее. Или оператор придется вообще исключить, но есть недостатки (доступно на godbolt.com). [code]#include #include #include #include #include
/// Set 1-8, to choose between cases #define CASE 1 #define WANT_DEFAULT_WHEN_MEMEBER 0
/// Must be forward declared, as, e.g., using `std::vector` in Var's declaration would not be possible struct Array; struct Map;
using Var = std::variant;
/// [CASE 1] Deduced comparison category type + default /// [COMPILES] No compiler #if CASE == 1
/// [CASE 5] Template hack to delay instantiation, concrete comparison category type /// [COMPILES] All compilers /// [LIMITATION] Requires knowing comparison category type, won't work if deducation is needed (template class) #elif CASE == 5
/// [CASE 6] As friends, no template hacks, declared before the type is defined /// [COMPILES] Only MSVC 19 /// [LIMITATION] Only as out of class friend (not critical) #elif CASE == 6
/// [CASE 7] As friends, no template hacks, declared before the type is defined, concrete comparison category type /// [COMPILES] Only MSVC 19 /// [LIMITATION] Only as out of class friend (not critical) /// [LIMITATION] Requires knowing comparison category type, won't work if deducation is needed (template class) #elif CASE == 7
/// [CASE 8] The full set of operators (pre C++20 way) /// [COMPILES] All compilers /// [LIMITATION] No `` therefore, when contained by another class, that class can't default its ``, /// at least in clang, but others seem incorrect as there is no way to deduce comparison category type /// I.e. won't work with `WANT_DEFAULT_WHEN_MEMEBER == 1` #elif CASE == 8
struct Array { /// Can't be defaulted: some type would be forward declared at that point. bool operator==(const Array & that) const; bool operator