首页 > 解决方案 > 如何使 std::vector 类成为一个序列,以便可以将其传递给 boost::hana::group?

问题描述

我希望以下代码能够编译和工作:

#include <boost/hana/group.hpp>
#include <functional>
#include <vector>
int main() {
    std::vector<int> x = {1,1,3,4};
    auto groups = boost::hana::group(x, std::equal_to<>{});
}

尝试编译这样的错误:

$ g++ -std=c++2a deleteme.cpp && ./a.out
In file included from deleteme.cpp:1:
/usr/include/boost/hana/group.hpp: In instantiation of ‘constexpr auto boost::hana::group_t::operator()(Xs&&, Predicate&&) const [with Xs = std::vector<int>&; Predicate = std::equal_to<void>]’:
deleteme.cpp:6:44:   required from here
/usr/include/boost/hana/group.hpp:55:42: error: static assertion failed: hana::group(xs, predicate) requires 'xs' to be a Sequence
   55 |         static_assert(hana::Sequence<S>::value,
      |                                          ^~~~~
/usr/include/boost/hana/group.hpp:59:28: error: use of deleted function ‘static constexpr auto boost::hana::deleted_implementation::apply(T&& ...) [with T = {std::vector<int, std::allocator<int> >&, std::equal_to<void>}]’
   59 |         return Group::apply(static_cast<Xs&&>(xs),
      |                ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
   60 |                             static_cast<Predicate&&>(pred));
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/hana/core/dispatch.hpp:14,
                 from /usr/include/boost/hana/drop_front.hpp:18,
                 from /usr/include/boost/hana/concept/iterable.hpp:20,
                 from /usr/include/boost/hana/at.hpp:16,
                 from /usr/include/boost/hana/group.hpp:15,
                 from deleteme.cpp:1:
/usr/include/boost/hana/detail/dispatch_if.hpp:21:31: note: declared here
   21 |         static constexpr auto apply(T&& ...) = delete;
      |                               ^~~~~

因此,我理解原因是std::vector不满足 的概念Sequence,但我如何强制执行它呢?

我一直在看/usr/include/boost/hana/fwd/concept/sequence.hppand /usr/include/boost/hana/concept/sequence.hpp,但是现在这些文件中的模板元元编程对于我来说在没有任何帮助的情况下理解它仍然有点沉重。

这是 Hana 文档的摘录,我认为它解决了这个问题。关键是我不知道如何将这些处方翻译成代码:

出于这个原因,有必要在 Hana 的命名空间中专门化 Sequence 元函数来告诉 Hana 一个类型确实是一个序列。显式特化序列元函数可以看作是一个印章,上面写着“这种数据类型满足 a 的附加定律Sequence”,因为 Hana 无法自动检查这些定律。

标签: c++functional-programmingc++14template-meta-programmingboost-hana

解决方案


虽然可以在 Boost.Hana 中使用涉及仅在运行时知道的不同维度的类型来实现某些概念,但 Boost.Hana.Sequence 和作为其“最小完整定义”一部分的一些概念需要长度以及在编译时要知道的元素。

  • Foldable要求在编译时知道长度。
  • Iterable要求每个元素在编译时都可以访问。
  • Sequence需要FoldableIterable

group需要 a的函数Sequence和运行时长度std::vector使这成为不可能。

Boost.Hana 手册中的计算象限部分详细介绍了需要编译时与运行时信息的算法。

(这个Group概念可能是可行的,但我认为这不是问题的一部分。)

关于专门针对标准类型的第三方模板的评论,这是可能的,但被认为是错误的形式。解决方案是制作某种包装器类型或提供您自己的概念。

编辑:

一条评论建议了一个实现std::array为 a的示例,Sequence因为它的长度在编译时是已知的。虽然我在禁止同质类型列表的“法律”中找不到灵丹妙药,但Sequence我可以说它的前提Sequence是使用异构类型的数据结构。元素可能包含运行时数据,但算法中的所有谓词都完全依赖于“编译时”信息,因此类似的函数group对于std::array. (这在上述链接中进行了解释)


推荐阅读