2015-10-19 59 views
2

我正在努力将用户定义类型作为hana::map中的键。 我遇到static_assert,说比较必须在 编译时间。我确实为constexpr bool operator==组合了(我相信)他们所有人的组合 。有什么问题?由于我的operator==constexpr,我的对象在编译时应该是可比较的,对吧?使用Boost.Hana定义编译时可比较的对象

回答

3

您必须从比较运算符中返回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是否与地图给定值关联。但是,由于无法指定keyconstexpr参数的事实,因此即使Key已定义constexpr bool operator==,我们也无法从该参数中提取constexpr bool。换句话说,

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。有关于这个和相关的概念herehere的更多信息。