我正在尝试制作一个函数模板,它将接受下面列出的两个(或更多)嵌套可变参数类模板作为参数,并将它们放入另一个将接受不同类型(对或元组是什么)的数据结构中我很可能会使用)。以下是类和子类,以及我的函数的用法(该函数在下面进一步定义):
template<typename... Args> struct Entity {
template<typename... InnerEntArgs> struct InnerEntity {
InnerEntity(InnerEntArgs... inner_ent_args) {
... //do stuff w/ InnerEntArgs pack
... //do stuff that makes Inner dependent on Outer's Args pack
}
};
};
struct ThingA : Entity<int, string> {
... //construct ThingA
};
struct ThingB : Entity<string, string> {
... //construct ThingB
};
auto foo = my_func(
ThingA::InnerEntity<int, int, int>(1, 2, 3)
, ThingB::InnerEntity<string, int>("bar", 1)
);
下面是我为这个函数拼凑的代码,它编译得很好,但我不确定它是否设置正确。具体来说,我不太清楚 typename
和 ::template
如何让编译器在这种情况下满意,或者这个函数是否会按照我期望的方式运行:
template<
typename... ArgsA, typename... ArgsAInner
, typename... ArgsB, typename... ArgsBInner
> auto my_func(
typename Entity<ArgsA...>::template InnerEntity<ArgsAInner...> A
, typename Entity<ArgsB...>::template InnerEntity<ArgsBInner...> B
) -> tuple<decltype(A), decltype(B)> {
return make_tuple(A, B);
}
我认为我很好地掌握了参数包是如何推导/推断的,以及auto
、decltype
和尾随返回类型正在做他们的事情,但如果我弄错了,请告诉我怎么做。
此外,如果有人愿意演示此函数的可变参数版本,它可以接受任意数量的嵌套可变参数类模板并将它们放入合适的容器或数据结构中,那就太好了,但我主要关心的是充分理解 typename
和 ::template
。提前致谢!
*如果我对这个标题的措辞不正确或者我混淆了术语,请解释。 :) 我是来学习的。
最佳答案
这行不通,因为 Entity<Args>::InnerEntity
是一个非推导上下文。意思是ArgsA...
和 ArgsAInner...
不能推导出,同样对于其他参数。这是因为在编译器可以推断出 Args
之前, 它必须知道什么类型 InnerEntity
是的成员,但要知道那个,它必须推导出Args
.
你可以把这个函数作为友元函数模板放到Entity<Args...>
中并使其工作,只要两者都是同一模板的成员。但是上次我检查的时候,GCC 并没有找到定义在类模板中的友元函数。
template<typename ...Args>
class Entity {
template<typename ...ArgsInner>
class InnerEntity {
};
template<typename ...ArgsAInner, typename... ArgsBInner>
> friend auto my_func(
InnerEntity<ArgsAInner...> A
, InnerEntity<ArgsBInner...> B
) -> tuple<decltype(A), decltype(B)> {
return make_tuple(A, B);
}
};
您还可以在 InnerEntity
中声明一些成员 typedef指定外部类的类型,并制定my_func
就此而言,SFINAE 可以为非成员(member)解决这个问题。
template<typename ...Args>
class Entity {
template<typename ...ArgsInner>
class InnerEntity {
typedef Entity outer_entity;
};
};
template<typename A, typename B, typename Result>
struct require_entity { };
template<typename ...ArgsA, typename ...ArgsB, typename Result>
struct require_entity<Entity<ArgsA...>, Entity<ArgsB...>> {
typedef Result type;
};
template<template<typename...> class AInner, template<typename...> class BInner,
typename ...ArgsAInner, typename ...ArgsBInner>
> auto my_func(
AInner<ArgsAInner...> A
, BInner<ArgsBInner...> B
) -> typename require_entity<
typename AInner<ArgsAInner...>::outer_entity,
typename BInner<ArgsBInner...>::outer_entity,
tuple<decltype(A), decltype(B)>>::type
{
return make_tuple(A, B);
}
当然你不需要那个template<typename...> class AInner
如果您不需要访问 ArgsAInner
类型,如上my_func
.在这种情况下,您最好只接受 typename AInner
。写得少了。 SFINAE 仍将确保只接受正确的东西。
关于c++ - 接受嵌套的可变类模板作为函数模板的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3773047/