带有两个参数的 C++ 参数包递归

dex*_*ter 4 c++ templates variadic-templates template-argument-deduction

我有一个使用两种类型的模板类:

template<typename T1,typename T2> class Foo { ... };
Run Code Online (Sandbox Code Playgroud)

我需要编写一个接受任意数量Foo变量的函数:

template <typename T1, typename T2, typename... Others> size_t getSize(Foo<T1,T2> *f, Foo<Others>*... o) { ... };
Run Code Online (Sandbox Code Playgroud)

如果我class Foo只使用一个模板参数来实现,它运行良好。但是对于两个(或更多)参数,编译器会抱怨Foo<Others>需要两个 args。

class Foo有多个模板参数时,是否可以实现参数包转发?

Jor*_*lon 5

你的错误是Foo<Others>*... o争论。为模板包解压缩该参数A, B, C, D, E将产生尽可能多的o参数:Foo<A>, Foo<B>, Foo<C>, ....

在我看来,如果您只是将参数声明为 asOther并让递归失败,如果它们稍后与任何Foo实例化不匹配,则会更简单:

template <typename T1, typename T2, typename... Others> size_t getSize(Foo<T1,T2> *f, Others... *o) { ... };
Run Code Online (Sandbox Code Playgroud)

在这里,Others包中的每种类型都会被推导为您传递的类型。如果您getSize使用减少的参数递归调用,它们最终都会与一个Foo<T1,T2>参数匹配:

return f->size() 
     + getSize(std::forward<Others>(o)...); // the first argument in the pack will
                                            // be Foo<T3,T4> type 
                                            // or the compilation will fail
Run Code Online (Sandbox Code Playgroud)

您还可以添加类型特征来直接进行检查:

template <class T> struct IsFoo : std::false_type {};
template <class T, class U> struct IsFoo<Foo<T,U>> : std::true_type {};

template </* ... */>
std::enable_if_t<std::conjunction<IsFoo<Others>::value...>::value, size_t> getSize(/* ... */)
Run Code Online (Sandbox Code Playgroud)


max*_*x66 5

关于什么

template <typename ... Ts1, typename ... Ts2>
std::size_t get_size (Foo<Ts1, Ts2> * ... fs)
 { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

或者可能,

template <typename T1, typename T2, typename ... Us1, typename ... Us2>
std::size_t get_size (Foo<T1, T2> * f, Foo<Us1, Us2> * ... fs)
 { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

如果你想要第一个Foo以不同的方式管理。