updating/replacing `boost::hana::map` 中地图值的规范方式
Canonical way of updating/replacing a map value in `boost::hana::map`
在 boost::hana::map
中更新值 (给定键和新值) 的规范方法是什么?
我尝试使用 boost::hana::replace_if
但它在 map
上不起作用,因为它不是 Functor
- 我可以通过将 map
转换为一个tuple
然后回到一个map
,但听起来效率很低。
我目前使用的替代方法是调用 map::erase_key
followed by map::insert
。
是否有任何我可能遗漏的为此目的而设计的 replace
或 update
函数?或者这是 "canonical" 更新值的方式?
我认为目前没有规范的方法可以做到这一点。如果有有效的用例,也许我们可以在那里获得一个功能来支持它。 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
。
您需要更改值的类型吗?如果没有,并且如果你的值可以赋值给,你可以使用map[key] = new_value
或者等价的hana::at_key(map, key) = new_value
,作为hana::at_key
returns的参考。
如果您需要更改值的类型,那就更棘手了。我们将无法就地执行任何操作,因为替换值后映射的类型将不同于替换值之前的类型。因此,我们必须创建一个新地图或该地图的某种修改视图(但目前不支持视图)。使用 erase_key
和 insert
确实会导致创建两个地图,效率低下。相反,我们可以提供某种 update
函数来实现相同的效果,但只会创建地图的一个副本(结果)。我相信我们也可以通过提供自己的函数在编译时间方面做得比 erase_key
+ insert
更好。我打开 this issue 来跟踪您的请求,因为我认为提供这样的内容很重要;谢谢。
最后,我想评论Jason说的话:
On another note, perhaps hana::map should be a Functor.
hana::map
可以做成一个 Functor,但我不确定 transform
是否可以在仍然遵守 Functor 法则的情况下触摸地图的键。如果不是这种情况,您仍然不能说 "replace the value with XXX if the key satisfies some predicate" 使用例如hana::replace_if
。我试图(但到目前为止失败了)找到一个函数的例子,如果 hana::transform
基本上改变了底层 key/value 对的序列,就会违反法律,但我的直觉是有可能找到这样的例子.将在第 278 期继续。
在 boost::hana::map
中更新值 (给定键和新值) 的规范方法是什么?
我尝试使用 boost::hana::replace_if
但它在 map
上不起作用,因为它不是 Functor
- 我可以通过将 map
转换为一个tuple
然后回到一个map
,但听起来效率很低。
我目前使用的替代方法是调用 map::erase_key
followed by map::insert
。
是否有任何我可能遗漏的为此目的而设计的 replace
或 update
函数?或者这是 "canonical" 更新值的方式?
我认为目前没有规范的方法可以做到这一点。如果有有效的用例,也许我们可以在那里获得一个功能来支持它。 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
。
您需要更改值的类型吗?如果没有,并且如果你的值可以赋值给,你可以使用map[key] = new_value
或者等价的hana::at_key(map, key) = new_value
,作为hana::at_key
returns的参考。
如果您需要更改值的类型,那就更棘手了。我们将无法就地执行任何操作,因为替换值后映射的类型将不同于替换值之前的类型。因此,我们必须创建一个新地图或该地图的某种修改视图(但目前不支持视图)。使用 erase_key
和 insert
确实会导致创建两个地图,效率低下。相反,我们可以提供某种 update
函数来实现相同的效果,但只会创建地图的一个副本(结果)。我相信我们也可以通过提供自己的函数在编译时间方面做得比 erase_key
+ insert
更好。我打开 this issue 来跟踪您的请求,因为我认为提供这样的内容很重要;谢谢。
最后,我想评论Jason说的话:
On another note, perhaps hana::map should be a Functor.
hana::map
可以做成一个 Functor,但我不确定 transform
是否可以在仍然遵守 Functor 法则的情况下触摸地图的键。如果不是这种情况,您仍然不能说 "replace the value with XXX if the key satisfies some predicate" 使用例如hana::replace_if
。我试图(但到目前为止失败了)找到一个函数的例子,如果 hana::transform
基本上改变了底层 key/value 对的序列,就会违反法律,但我的直觉是有可能找到这样的例子.将在第 278 期继续。