标准库中是否存在类型级别的左折叠元函数?

sys*_*pro 1 c++ template-meta-programming c++17

如果a,b,c,..表示 类型,则令 为我正在寻找地图的(a,b)类型, ,这样std::pair<a,b>F

    F : ((((a,b),c),d),...))) -> std::tuple<a,b,c,d...>
Run Code Online (Sandbox Code Playgroud)

它是否以标准库中的某个现有名称存在?如果没有,是否有另一个库可以做到这一点,或者这很容易实现,但我太笨了,不知道该怎么做?

Bar*_*rry 5

我认为这基本上必须是递归的。标准库中没有这样的东西,这一次我无法想出Boost.Mp11单行代码。

namespace impl {
    template <typename T>
    struct unfold_t {
        using type = std::tuple<T>;
    };

    template <typename A, typename B>
    struct unfold_t<std::pair<A, B>> {
        using type = mp_push_back<typename unfold_t<A>::type, B>;
    };
}

template <typename T>
using unfold = typename impl::unfold_t<T>::type;
Run Code Online (Sandbox Code Playgroud)

在TC的帮助下,最新版本的Mp11(1.73)有一个名为mp_iterate我们可以使用的算法。

给定std::pair<std::pair<X, Y>, Z>,如果我们mp_first重复应用(如R),我们会得到序列:

  • std::pair<std::pair<X, Y>, Z>
  • std::pair<X, Y>
  • X

然后,如果我们应用mp_second到该序列,我们会得到:

  • Z
  • Y
  • 不规范的

非常接近了。我们确实需要那个X。因此,我们需要一个更复杂的元函数F:如果可能的话,我们需要获取第二个值。有一个元函数可以实现这一点:

template <typename L>
using second_or_self = mp_eval_or<L, mp_second, L>;
Run Code Online (Sandbox Code Playgroud)

现在mp_iterate<T, second_or_self, mp_first>给我们mp_list<Z, Y, X>。此时我们需要做的就是反转它并将其变成std::tuple

template <typename L>
using unfold = mp_rename<mp_reverse<
    mp_iterate<L, second_or_self, mp_first>>,
    std::tuple>;
Run Code Online (Sandbox Code Playgroud)

现在 Boost.173 已在编译器浏览器、演示中


或者,我想,如果你真的讨厌你的读者,你可以将其设为一个别名

template <typename L>
using unfold = mp_rename<mp_reverse<
    mp_iterate_q<L,
        mp_bind<mp_eval_or_q, _1, mp_quote<mp_second>, _1>,
        mp_quote<mp_first>>>,
    std::tuple>;
Run Code Online (Sandbox Code Playgroud)