使用模板外部 class 内嵌套 class 的默认模板参数继承
Inheriting with default template parameter of nested class within template outer class
我有一个模板外部 class(下面的 Outer
)和一个 public 嵌套的模板 class(Inner
)。 Inner
的模板参数有一个默认值。我特化了Outer
(SpecializedOuter
),然后从嵌套的class(SpecializedOuter::Inner
)派生来定义一个新的class(SpecializedInner
)。如果我在 SpecializedInner
的定义中指定 Inner
的模板参数,编译就没问题。但是,如果我在 SpecializedInner
中省略 Inner
的模板参数,即使指定了默认值 (Inner<U=void>
),g++ 也不会编译代码。
对于 g++ 和 VS2013 有没有办法解决这个问题?我查看了 Google 结果和其他问题,但无法获得能够区分 "default" 和 "template" 的所有可能用途的搜索词:) .
代码和错误消息
以下 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
{}
};
但是,如果我从 public SpecializedOuter::Inner<void>
和 : SpecializedOuter::Inner<void>
中删除 <void>
,则会出现编译错误。我希望编译器会使用 Inner
定义中的默认值 typename U = void
。代码和错误是:
// ... 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
的子class,而 Inner
是子class 共 osg::Drawable::UpdateCallback
。为了方便起见,我正在尝试将样板移动到 Inner
中,并消除对 dynamic_cast
从 osg::Geometry
到 Outer<T>
.
的需要
好吧,发帖后我在 this question. I'll leave it here in case it is useful for anyone else. When using the defaults, you still have to put <>
at the end of the class name to turn it from the name of a template into the name of an instantiated class (per 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: //
我有一个模板外部 class(下面的 Outer
)和一个 public 嵌套的模板 class(Inner
)。 Inner
的模板参数有一个默认值。我特化了Outer
(SpecializedOuter
),然后从嵌套的class(SpecializedOuter::Inner
)派生来定义一个新的class(SpecializedInner
)。如果我在 SpecializedInner
的定义中指定 Inner
的模板参数,编译就没问题。但是,如果我在 SpecializedInner
中省略 Inner
的模板参数,即使指定了默认值 (Inner<U=void>
),g++ 也不会编译代码。
对于 g++ 和 VS2013 有没有办法解决这个问题?我查看了 Google 结果和其他问题,但无法获得能够区分 "default" 和 "template" 的所有可能用途的搜索词:) .
代码和错误消息
以下 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
{}
};
但是,如果我从 public SpecializedOuter::Inner<void>
和 : SpecializedOuter::Inner<void>
中删除 <void>
,则会出现编译错误。我希望编译器会使用 Inner
定义中的默认值 typename U = void
。代码和错误是:
// ... 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
的子class,而 Inner
是子class 共 osg::Drawable::UpdateCallback
。为了方便起见,我正在尝试将样板移动到 Inner
中,并消除对 dynamic_cast
从 osg::Geometry
到 Outer<T>
.
好吧,发帖后我在 this question. I'll leave it here in case it is useful for anyone else. When using the defaults, you still have to put <>
at the end of the class name to turn it from the name of a template into the name of an instantiated class (per 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: //