您必须从比较运算符返回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[]内部,返回值的type取决于key。我们必须以某种方式提取一个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。有更多关于这个和相关概念的信息here 和 here。