在模板外部类中继承嵌套类的默认模板参数

时间:2017-05-24 13:00:50

标签: class c++11 templates inheritance default-value

我有一个模板外部类(下面是Outer),带有一个公共模板嵌套类(Inner)。 Inner的模板参数有默认值。我专门化OuterSpecializedOuter),然后从嵌套类(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"
  {}
};

用例

如果您想知道,在我的用例中,OuterOpenSceneGraph's osg::Geometry的子类,Innerosg::Drawable::UpdateCallback的子类。为方便起见,我正在尝试将样板移动到Inner,并且不需要dynamic_castosg::GeometryOuter<T>

1 个答案:

答案 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: //