递归折叠参数包以解析占位符类型 [英] Recursively folding a parameter pack to resolve placeholder types

查看:93
本文介绍了递归折叠参数包以解析占位符类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在问过有关参数包折叠成对的问题,我注意到我需要保留以前折叠类型的完整类型作为左对类型。

After asking this question about parameter pack folding into pairs, I noticed that I need to retain the complete type of the previously folded type as the left pair type.

例如:

Fold<char, int, long, double> f;

必须评估为

std::tuple<
    std::pair<char
             , int>,
    std::pair<std::pair<char, int> /* <-- the previous resulting type */
             , long>,
    std::pair<std::pair<std::pair<char, int>, long> /* the previous type again */
             , double>
> f;



此问题的背景



原因我之所以需要它,是因为必须折叠的类型可以是占位符类型。仅当左侧同时具有完全展开的类型和未展开的类型时,才能知道占位符真实类型。
最左边的类型从不包含占位符。

Context to this problem

The reason why I need this, is because the types which have to be "folded" can be placeholder types. The placeholders "real" type can only be known when both having the fully expanded type to the left as well as the unexpanded type. The leftmost type never contains placeholders.

让我用一个简单的例子说明一下:

Let me illustrate this with a quick example:

struct CopyTypeFromPreviousArgumentTag { };

template<typename T = CopyTypeFromPreviousArgumentTag>
struct Foo;

template<typename T...>
struct Bar {
    /* Here fold will not use std::pair, but a resolver type that takes both A and B and gives back the resolved B */
    Fold<T...> expanded;
};

现在 Bar 可以这样使用:

Bar< Foo<int>
   , Foo<>
   , Foo<>
   , Foo<double>
   , Foo<>
   > f;

以及内部类型 decltype(f :: expanded)将为:

std::tuple< Foo<int>
          , Foo<int>
          , Foo<int>
          , Foo<double>
          , Foo<double>
          >;

编辑: Bar 类实际上并不限于它可能拥有的任何类类型。它可以是几种类型的混合物。因此,请参见 Foo 类作为某些类型 Foo 的占位符,其中给定先前的已解析类型,其中存在解析器类型特征: ResolveType< PreviouslyResolvedType,CurrentType> :: Type 将正确给出解析的类型。因此, std :: pair 习惯用法。

The Bar class is actually not restricted to any class type it might hold. It can be a mixture of several types. So see the Foo class as a placeholder for some type Foo where a resolver type traits exists given the previous resolved type: ResolveType<PreviouslyResolvedType, CurrentType>::Type will give the resolved type correctly. Hence the std::pair idiom.

我试图通过基于链接问题的答案来实现递归,但无法使其正常工作。

I tried to implement the recursion by building upon the answer from the linked question, but can't get it to work.

namespace Detail {

template<typename, typename...>
struct Fold;

template
    < size_t... Indices
    , typename... Types
> struct Fold<std::index_sequence<Indices...>, Types...> {
    using Tuple = std::tuple<Types...>;
    using Type = std::tuple<std::pair /* use std::pair just to match the first example */
        //< std::tuple_element_t<Indices, Tuple>
        < typename Fold
            < std::tuple_element_t<Indices, Tuple>
            , std::make_index_sequence<Indices>
            , Types...>::Type; /* Tuple can't be expanded :( */
        , std::tuple_element_t<Indices + 1, Tuple>
        >::Type...>;
};

} /* namespace Detail */


template<typename... Types>
using Fold = typename Detail::Fold<std::make_index_sequence<sizeof...(Types) - 1>, Types...>::Type;


推荐答案

我通过构建一些知道如何创建第n个类型的东西来开始我的解决方案,它只是先前创建的类型和当前源类型的一对,所以:

I start my solution by building something that knows how to create the nth type. It's just a pair of the previous created type, and the current source type, so:

template <std::size_t I, class T>
struct element {
  using type = std::pair<typename element<I - 1, T>::type,
                         std::tuple_element_t<I + 1, T>>;
};

template <class T>
struct element<0, T> {
  using type =
      std::pair<std::tuple_element_t<0, T>, std::tuple_element_t<1, T>>;
};

我们现在真正需要做的就是将输入类型放入一个元组,获取一个整数包,然后输入元组并通过 element 将整数包展开为新的元组。没问题:

All we really need to do now is put the input types into a tuple, grab an integer pack, and feed the tuple and unfold the integer pack through element, into a new tuple. No problem:

template <class I, class... Ts>
class fold_helper;

template <std::size_t... Is, class... Ts>
class fold_helper<std::index_sequence<Is...>, Ts...> {

  using tup = std::tuple<Ts...>;

public:
  using type = std::tuple<typename element<Is, tup>::type...>;
};

template <class... Ts>
using Fold = typename fold_helper<std::make_index_sequence<sizeof...(Ts)-1>,
                                  Ts...>::type;

最后,让我们检查一下它的作用:

Finally, let's check this works:

int main() {

  static_assert(
      std::is_same<Fold<char, int, long, double>,
                   std::tuple<std::pair<char, int>, //
                              std::pair<std::pair<char, int>, long>,
                              std::pair<std::pair<std::pair<char, int>, long>,
                                        double>>>::value,
      "");

  return 0;
};

该程序为我编译。

这篇关于递归折叠参数包以解析占位符类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆