具有两个参数的 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
以不同方式管理。
我有一个使用两种类型的模板 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
以不同方式管理。