Я борюсь с наличием пользовательских типов в качестве ключей в hana::map
,
Я сталкиваюсь с static_assert
говоря, что сравнение должно быть возможным при
время компиляции. Я реализовал constexpr bool operator==
для комбинаций
из (я верю) всех из них. В чем проблема? Так как мой operator==
является constexpr
мои объекты должны быть сопоставимы во время компиляции, верно?
Вы должны вернуть 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
, Есть больше информации об этом и связанных с ним понятиях Вот а также Вот.
Других решений пока нет …