【问题标题】:boost::hana: Why can't I filter a set?boost::hana: 为什么我不能过滤一个集合?
【发布时间】:2018-09-30 12:15:17
【问题描述】:

我正在使用 boost::hana,我想过滤一个 boost::hana::set。

#include <boost/hana.hpp>
#include <type_traits>

int main(){
    using namespace boost::hana;
    auto a = make_set(1,'a',3);
    auto b = remove_if(a, [](const auto& x){return bool_c<std::is_same_v<decltype(x), char>>;});
    // expects b to be make_set(1, 3);
}

这会导致 static_assert 失败。它告诉我:

static assertion failed: hana::remove_if(xs, predicate) requires 'xs' to be a MonadPlus

         static_assert(hana::MonadPlus<M>::value, 

为什么会失败?为什么集合不能是 MonadPlus,即使定义了空集合和连接操作?

【问题讨论】:

  • 可能是因为集合不是序列,因为set s 必须包含唯一元素。如果你想要更具体的东西,那么你可以在hana 的代码中找到hana::MonadPlus 的定义,然后再返回看看hana::set 缺少哪些先决条件。
  • 这是一个完全合法且可以回答的问题。为什么它被否决了?

标签: c++ template-meta-programming boost-hana


【解决方案1】:

如果你想过滤一个列表,你应该使用hana::tuple。 Set 的概念比 MonadPlus 甚至 Monad 更普遍。您断言hana::set 具有hana::concathana::empty 的实现是不正确的,此外它还要求数据结构是Monad。

根据您的示例,您正在寻找的可能是hana::difference,但hana::set 本身对此毫无用处。它的操作需要hana::Comparable 并且不能很好地适应运行时状态。

如果您想按类型“过滤”集合并维护运行时值,我建议使用同样支持集合操作的hana::map。您可以将其键设为其值的hana::type。这仍然需要其类型的唯一性。

这是一个例子:

#include <boost/hana.hpp>

namespace hana = boost::hana;

constexpr auto typed_set = [](auto&& ...x) {
  return hana::make_map(
    hana::make_pair(hana::typeid_(x), std::forward<decltype(x)>(x))...
  );
};

int main() {
  auto a = typed_set(1, 'a', 3.0f);
  auto b = typed_set('c');
  auto c = hana::difference(a, b);

  BOOST_HANA_RUNTIME_ASSERT(c == typed_set(1, 3.0f));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-15
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    相关资源
    最近更新 更多