使用模板外部 class 内嵌套 class 的默认模板参数继承

Inheriting with default template parameter of nested class within template outer class

我有一个模板外部 class(下面的 Outer)和一个 public 嵌套的模板 class(Inner)。 Inner 的模板参数有一个默认值。我特化了OuterSpecializedOuter),然后从嵌套的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"
  {}
};

用例

如果您想知道,在我的用例中,OuterOpenSceneGraph's osg::Geometry 的子class,而 Inner 是子class 共 osg::Drawable::UpdateCallback。为了方便起见,我正在尝试将样板移动到 Inner 中,并消除对 dynamic_castosg::GeometryOuter<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: //