如何从右向左展开参数包

Ide*_*Hat 13 c++ c++11

我试图通过递归地分配给一个类来展开参数包。我想从右到左执行此操作,因为某些操作确实处于待处理状态。

template <typename... T>
class Foo;

template <typename T>
class Foo<T> {/* base case implementation*/};

template <typename T, typename R, typename... Rs>
class Foo<T, Rs..., R> {
   private:
     Foo<T, Rs...> foo_;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,以上让我:

类模板部分专业化包含无法推导的模板参数;
这种部分专业化将永远不会使用

这对我来说似乎很奇怪,我认为即使参数已切换顺序,Foo<T, Rs..., R>但仍应与模板专用化匹配。

我看过一些类似的问题:

特别是C ++模板的部分专业化:为什么我不能匹配可变参数模板中的最后一个类型?

但是,对我来说,最高票数(不被接受)的答案是没有意义的。当然,我知道模板参数包声明必须在声明的最后,但是我这样做是为了模板专门化。

我不确定为什么编译器无法映射Foo<T, Rs..., R>到初始模板声明,Foo<T...>并在那里执行参数包声明顺序。

该线程上的其他答案提供了如何提取最后一个值,但这仍然不允许您进行递归参数包展开,这是本文的重点。从右到左展开参数包是不可能的吗?

Dmi*_*don 6

这是一个用于以相反的模板参数顺序来实例化模板的实用程序:

#include <type_traits>
#include <tuple>

template <template <typename...> typename Template, typename ...Arg>
struct RevertHelper;

template <template <typename > typename Template, typename Arg>
struct RevertHelper<Template, Arg>
{
    using Result = Template<Arg>;
};

template <template <typename... > typename Template, typename Head, typename ...Tail>
struct RevertHelper<Template, Head, Tail...>
{
private:
    template <typename ...XArgs>
    using BindToTail = Template<XArgs..., Head>;

public:

    using Result = typename RevertHelper<BindToTail, Tail...>::Result;
};

static_assert(std::is_same_v<typename RevertHelper<std::tuple, int, double>::Result, std::tuple<double, int>>, "");
Run Code Online (Sandbox Code Playgroud)

因此,如果您需要在反转Foo模板包的Args...情况下实例化,则可以使用

typename RevertHelper<Foo, Args...>::Result
Run Code Online (Sandbox Code Playgroud)

要按照您想要的方式扩展参数包,请分派给相反的实现:

namespace internal {
  template <typename... T>
  class FooHelper;
  template <typename T>
  class FooHelper<T> {/* base implementation */}
  template <typename L, typename R, typename... Rs>
  class FooHelper<T> {
    private:
      Foo<T, Rs...> foo_helper_;
  };
}
template <typename... T>
class Foo {
  typename RevertHelper<internal::FooHelper, T...>::Result foo_helper_;
};
Run Code Online (Sandbox Code Playgroud)