Nested class declaration: template vs non-template outer class
我有一个C++模板类,里面有一个嵌套类,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | template<int d> class Outer_t { public: class Inner; Inner i; }; template<int d> class Outer_t<d>::Inner { public: float x; }; int main () { Outer_t<3> o_t; // 3 or any arbitrary int o_t.i.x = 1.0; return 0; } |
这编译没有任何问题。但是,一旦我声明了类似的非模板类,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Outer_1 { public: class Inner; Inner i; }; class Outer_1::Inner { public: float x; }; int main () { Outer_1 o1; o1.i.x = 1.0; return 0; } |
我开始得到以下错误(我使用的是GCC4.6.3):"错误:字段‘i’的类型不完整"。我知道,我可以通过在外部类内部直接定义内部类来解决这个问题:
1 2 3 4 5 6 7 8 9 10 | class Outer_2 { public: class Inner { public: float x; }; Inner i; }; |
这将编译,但我希望避免在内联中定义嵌套类。所以我有两个问题:模板和非模板嵌套类声明之间这种明显奇怪的差异的原因是什么?有没有一种优雅的方法来声明和使用外部类中的Nester类,同时避免以与模板类相同的风格内联定义它?提前感谢您的帮助!
为什么会出现编译错误?
编译器需要知道成员变量类型的大小才能进行对象布局。对于
另一方面,类模板在模板实例化发生之前不会被定义。在您的示例中,隐式实例化发生在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | template<int d> class Outer_t { public: class Inner; Inner i; }; template class Outer_t<3>; // explicit instantation template<int d> class Outer_t<d>::Inner { public: float x; }; int main () { Outer_t<3> o_t; // 3 or any arbitrary int o_t.i.x = 1.0; return 0; } |
Clang产生以下错误:
1 2 3 4 5 6 7 8 9 | a.cc:7:11: error: implicit instantiation of undefined member 'Outer_t<3>::Inner' Inner i; ^ a.cc:10:16: note: in instantiation of template class 'Outer_t<3>' requested here template class Outer_t<3>; ^ a.cc:5:11: note: member is declared here class Inner; ^ |
解决方案
如果您想提取嵌套类的定义,我建议的解决方案是像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | template <typename Dummy = void> class Outer_1_Impl { public: class Inner; Inner i; }; template <typename Dummy> class Outer_1_Impl<Dummy>::Inner { public: float x; }; using Outer_1 = Outer_1_Impl<>; int main () { Outer_1 o1; o1.i.x = 1.0; } |
在定义类时,对象中只能有具有完整定义的非静态成员。在您的非模板示例中,
现在,为什么在使用类模板时不出现这个问题?答案是:当您在