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

C++ argument pack recursion with two arguments

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

template<typename T1,typename T2> class Foo { ... };

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

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

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

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

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

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

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

在这里,包中的每个 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

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

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(/* ... */)

怎么样

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

?

或者,也许,

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

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