我试图通过递归地分配给一个类来展开参数包。我想从右到左执行此操作,因为某些操作确实处于待处理状态。
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...>并在那里执行参数包声明顺序。
该线程上的其他答案提供了如何提取最后一个值,但这仍然不允许您进行递归参数包展开,这是本文的重点。从右到左展开参数包是不可能的吗?
这是一个用于以相反的模板参数顺序来实例化模板的实用程序:
#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)