我有一组类,每个类都定义了一个总是具有相同名称的嵌套类。
class A {
public:
class Common {};
...
};
class B {
public:
class Common {};
...
};
我正在尝试编写这样的模板函数(不编译代码):
template<typename T, typename... ARGS>
void foo(T::Common tc, ARGS... args) {
T t(tc, args...);
// do stuff
}
我想用它如下:
{
...
A::Common ac();
foo(ac, 42, "Hello");
....
}
如何从传递给函数的内部类实例上的类型中提取外部类类型?也许与<traits>
,但我是新手...
答案 0 :(得分:3)
在以下功能模板中:
template<typename T, typename... ARGS>
void foo(T::Common tc, ARGS... args);
T
处于不可扣除的背景中。因此,做:
foo(ac, 42, "Hello");
不会编译,因为T
无法从函数调用参数中推断出来。您需要将A
作为参数显式传递给T
模板参数:
foo<A>(ac, 42, "Hello");
但请注意,T::Common
实际上必须以关键字typename
开头,因为Common
是与类型相关的名称:
template<typename T, typename... ARGS>
void foo(typename T::Common tc, ARGS... args);
您可以声明一个outer_class_of<>
类模板来提取外部类。此模板将由内部类类型参数化:
// primary template
template<typename>
struct outer_class_of;
然后,为A::Common
和B:Common
专门设定此模板:
// specialization for A::Common
template<>
struct outer_class_of<A::Common> {
using type = A; // outer class of A::Common
};
// specialization for B::Common
template<>
struct outer_class_of<B::Common> {
using type = B; // outer class of B::Common
};
您可以声明一个别名模板,以实现类似C ++ 14的_t
类型特征:
template<typename T>
using outer_class_of_t = typename outer_class_of<T>::type;
这样,outer_class_of_t<A::Common>
对应A
和outer_class_of_t<B::Common>
对B
。
最后,您需要将foo()
函数模板定义更改为:
template<typename TCommon, typename... ARGS>
void foo(TCommon tc, ARGS... args) {
outer_class_of_t<TCommon> t(tc, args...);
}
使用foo()
或A::Common
对象作为函数参数调用B::Common
时,TCommon
将推断为A::Common
或B::Common
,分别。然后在outer_class_of<>
上应用TCommon
以获取外部类的类型。
此外,请在C++'s most vexing parse中使用
A::Common ac();
你想要的实际上是:
A::Common ac{};
否则,在foo()
的调用中,TCommon
将推断为A::Common(*)()
(即:指向函数的指针),而不是A::Common
,因为前者正在声明一个不带参数并返回A::Common
对象的函数,而后者实际上是声明一个A::Common
对象。
答案 1 :(得分:0)
上面的答案很好,但有点复杂。
或许更简单的答案(您正在寻找)是您可以通过显式模板规范调用而不是隐式演绎来实现。这是一个你在哪里权衡复杂性的问题。
调用者可能会在调用中指定A并写入:
foo(ac,42,&#34; Hello&#34;);
你仍然应该输入typename关键字和一个好评论来帮助你的界面用户
template<typename T, typename... ARGS>
void foo(typename T::Common tc, ARGS... args); /// Call with foo<T>(tc, ...)