【问题标题】:Canonical way of updating/replacing a map value in `boost::hana::map`在`boost::hana::map`中更新/替换地图值的规范方法
【发布时间】:2016-09-20 01:26:07
【问题描述】:

boost::hana::map 中更新值(给定一个键和一个新值) 的规范方法是什么?

我尝试使用boost::hana::replace_if,但它不适用于map,因为它不是Functor - 我可以通过将map 转换为tuple 然后再转换回@ 来使其工作987654331@,但听起来效率低下。

我目前使用的替代方法是调用map::erase_key,然后调用map::insert

是否有任何为此目的而设计的 replaceupdate 函数我可能会丢失?或者这是更新值的“规范”方式?

【问题讨论】:

    标签: c++ boost metaprogramming c++14 boost-hana


    【解决方案1】:

    我认为目前没有规范的方法可以做到这一点。如果有有效的用例,也许我们可以在那里获得一个函数来支持它。 hana::erase_key 的问题是您将创建一个新地图,然后再次使用hana::insert。目前,使用hana::unpack 然后创建新地图可能是您最好的选择。

    #include <boost/hana.hpp>
    
    namespace hana = boost::hana;
    
    template <typename NewPair>
    struct replace_helper_t
    {
      NewPair const& new_pair;
    
      template <typename Pair>
      constexpr decltype(auto) operator()(Pair&& p) const
      {
        return hana::if_(
          hana::equal(hana::first(new_pair), hana::first(p)),
          new_pair,
          std::forward<Pair>(p)
        );
      }
    };
    
    struct replace_t
    {
      template <typename Map, typename NewPair>
      constexpr auto operator()(Map&& m, NewPair&& new_pair) const
      {
        return hana::unpack(std::forward<Map>(m),
          hana::on(
            hana::make_map,
            replace_helper_t<NewPair>{std::forward<NewPair>(new_pair)}
          )
        );
      }
    };
    
    constexpr replace_t replace{};
    
    int main()
    {
      auto my_map = hana::make_map(
        hana::make_pair(hana::int_c<7>, 7),
        hana::make_pair(hana::int_c<13>, 13),
        hana::make_pair(hana::int_c<23>, 23)
      );
    
      auto new_map = replace(my_map, hana::make_pair(hana::int_c<13>, 14.0f));
    
      BOOST_HANA_RUNTIME_ASSERT(new_map ==
        hana::make_map(
          hana::make_pair(hana::int_c<7>, 7),
          hana::make_pair(hana::int_c<13>, 14.0f),
          hana::make_pair(hana::int_c<23>, 23)
        )
      );
    }
    

    另一方面,hana::map 应该是 Functor

    【讨论】:

    • 我相信你需要你的hana::hash(hana::first(new_pair)) == hana::hash(hana::first(p)) 测试是hana::equal(hana::first(new_pair), hana::first(p))。否则,如果您替换与哈希与映射中的任何其他键冲突的键关联的值,您将替换共享相同哈希的所有键的值,即使键不同也是如此。基本上,您将替换同一存储桶中所有键的值。还有一个挑剔,但对于通用代码使用hana::equal 可能比== 更好,因为它可以与例如std::integral_constant.
    • 啊,没错。我修复了我的示例并更改了值的类型,以证明它不是简单地改变值。
    【解决方案2】:

    您需要更改值的类型吗?如果没有,并且您的值可以分配给,您可以使用map[key] = new_value 或等效的hana::at_key(map, key) = new_value,因为hana::at_key 返回一个引用。

    如果您需要更改值的类型,那就更棘手了。我们将无法就地执行任何操作,因为替换值后的映射类型将不同于替换值之前的类型。因此,我们必须创建一个新地图或该地图的某种修改视图(但当前不支持视图)。使用erase_keyinsert确实会导致创建两个map,效率低下。相反,我们可以提供某种update 函数来实现相同的效果,但只会创建地图的一个副本(结果)。我相信通过提供我们自己的函数,我们也可以在编译时间方面做得比erase_key + insert 更好。我打开this issue 来跟踪您的请求,因为我认为提供这样的东西很重要;谢谢。

    最后,我想评论一下 Jason 所说的话:

    另一方面,也许 hana::map 应该是一个 Functor。

    hana::map 可以成为 Functor,但我不确定 transform 是否可以在仍然遵守 Functor 定律的同时触摸地图的键。如果不是这种情况,您仍然无法使用例如说“如果键满足某个谓词,则将值替换为 XXX”。 hana::replace_if。如果hana::transform 基本上转换了底层键/值对的序列,我尝试(但到目前为止失败)找到一个违反法律的函数示例,但我的直觉是可以找到这样的示例。将在第 278 期继续。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-20
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多