我有一个模板外部类(下面是Outer
),带有一个公共模板嵌套类(Inner
)。 Inner
的模板参数有默认值。我专门化Outer
(SpecializedOuter
),然后从嵌套类(SpecializedOuter::Inner
)派生来定义一个新类(SpecializedInner
)。如果我在Inner
的定义中指定SpecializedInner
的模板参数,则编译很好。但是,如果我在Inner
中省略SpecializedInner
的模板参数,g ++将无法编译代码,即使指定了默认值(Inner<U=void>
)。
有没有什么方法可以解决这个问题对于g ++和VS2013?我查看了Google搜索结果和其他问题,但是我无法获得能够区分“默认”和“模板”的所有可能用途的搜索字词:)。
以下test.cpp
编译时没有错误或警告g ++ 5.4.0,g++ -std=c++11 -Wall -c test.cpp -o test.o
:
template<typename T>
class Outer {
public:
template<typename U = void> // The default I want to take advantage of
class Inner {
Outer *outer_;
public:
Inner(Outer *outer): outer_(outer) {}
};
}; //Outer
typedef Outer<int> SpecializedOuter;
class SpecializedInner: public SpecializedOuter::Inner<void> {
// also works with int or double instead of void - I just have to specify some type.
public:
SpecializedInner(SpecializedOuter *so)
: SpecializedOuter::Inner<void>(so) // type also expressly specified here
{}
};
但是,如果我从<void>
和public SpecializedOuter::Inner<void>
删除: SpecializedOuter::Inner<void>
,我会收到编译错误。我希望编译器使用typename U = void
定义中的默认Inner
。代码和错误是:
// ... definitions of Outer, Inner, SpecializedOuter as above ...
class SpecializedInner: public SpecializedOuter::Inner { // without <void>
// => "expected class-name before `{' token"
public:
SpecializedInner(SpecializedOuter *so)
: SpecializedOuter::Inner(so) // without <void>
// => "expected class-name before `(' token"
// => "expected `{' before `(' token"
{}
};
如果您想知道,在我的用例中,Outer
是OpenSceneGraph's osg::Geometry
的子类,Inner
是osg::Drawable::UpdateCallback
的子类。为方便起见,我正在尝试将样板移动到Inner
,并且不需要dynamic_cast
从osg::Geometry
到Outer<T>
。
答案 0 :(得分:1)
好吧,发布后我在this question找到了答案。我会留在这里,以防它对其他人有用。使用默认值时,您仍然必须将<>
放在类名末尾,将其从模板名称转换为实例化类的名称(每个this answer到上面的问题) 。这成功编译:
template<typename T>
class Outer {
public:
template<typename U = void>
class Inner {
Outer *outer_;
public:
Inner(Outer *outer): outer_(outer) {}
};
}; //Outer
typedef Outer<int> SpecializedOuter;
class SpecializedInner: public SpecializedOuter::Inner<> {
// without <void>, but with <> => OK
public:
SpecializedInner(SpecializedOuter *so)
: Inner<>(so) // without <void>, with <> => OK. Plus, don't have to
{} // re-specify `SpecializedOuter::`!
};
// vi: set ts=2 sts=2 sw=2 et ai: //