Определение сопоставимых объектов во время компиляции с Boost.Hana

Я борюсь с наличием пользовательских типов в качестве ключей в hana::map,
Я сталкиваюсь с static_assert говоря, что сравнение должно быть возможным при
время компиляции. Я реализовал constexpr bool operator== для комбинаций
из (я верю) всех из них. В чем проблема? Так как мой operator== является constexprмои объекты должны быть сопоставимы во время компиляции, верно?

2

Решение

Вы должны вернуть integral_constant<bool, ...> от вашего оператора сравнения, а не constexpr bool, Следующие работы:

#include <boost/hana.hpp>
#include <cassert>
#include <string>
namespace hana = boost::hana;

template <int i>
struct UserDefined { };

template <int a, int b>
constexpr auto operator==(UserDefined<a>, UserDefined<b>)
{ return hana::bool_c<a == b>; }

template <int a, int b>
constexpr auto operator!=(UserDefined<a>, UserDefined<b>)
{ return hana::bool_c<a != b>; }

int main() {
auto m = hana::make_map(
hana::make_pair(UserDefined<0>{}, std::string{"zero"}),
hana::make_pair(UserDefined<1>{}, 1)
);

assert(m[UserDefined<0>{}] == "zero");
assert(m[UserDefined<1>{}] == 1);
}

Зачем?

Чтобы понять, почему constexpr bool Оператора сравнения недостаточно, рассмотрим псевдо-реализацию hana::map::operator[]:

template <typename ...implementation-defined>
struct map {
template <typename Key>
auto operator[](Key const& key) {
// what now?
}
};

внутри operator[], тип возвращаемого значения зависит от ключа. Мы должны как-то извлечь bool представляя, какое значение связано с этим ключом, но это bool должен быть известен во время компиляции (то есть быть константным выражением), чтобы возвращаемый тип зависел от этого. Так внутри operator[], нам нужно constexpr bool представляя ли key является ключом, связанным с данным значением карты. Тем не менее, так как нет возможности указать тот факт, что key это constexpr параметр, мы не можем извлечь constexpr bool из этого аргумента, даже если Key имеет constexpr bool operator== определены. Другими словами,

template <typename Key>
auto operator[](Key const& key) {
// impossible whatever some_other_key_of_the_map is
constexpr bool found = (key == some_other_key_of_the_map);

// return something whose type depends on whether the key was found
}

Единственный способ достичь вышеуказанного — это сделать что-то вроде

template <typename Key>
auto operator[](Key const& key) {
constexpr bool found = decltype(key == some_other_key_of_the_map)::value;

// return something whose type depends on whether the key was found
}

и, следовательно, требуют, чтобы Key::operator== возвращает IntegralConstant, Есть больше информации об этом и связанных с ним понятиях Вот а также Вот.

3

Другие решения

Других решений пока нет …