use*_*084 12 c++ inheritance qt compiler-errors g++
我有一个基类,如下所示.
template<typename T>
class Base
{
public:
Base(int someValue);
virtual T someFunc() =0;
};
template<typename T>
Base<T>::Base(int someValue)
{}
Run Code Online (Sandbox Code Playgroud)
然后是以下内容.
#include "base.hpp"
class Foo
: public Base<Foo>
{
public:
Foo(int someValue);
virtual Foo someFunc();
};
Foo::Foo(int someValue)
: Base(someValue)
{}
Run Code Online (Sandbox Code Playgroud)
我从gcc 4.2.1得到以下错误.
error: class ‘Foo’ does not have any field named ‘Base’
Run Code Online (Sandbox Code Playgroud)
我应该提一下,在运行gcc 4.6.2的Fedora盒子上编译好.在我的os x Lion机器上编译时会发生此错误.
在此先感谢您的帮助.
编辑
问题似乎是我在调用构造函数时没有在Foo类中指出模板的类型.以下修复了os x中的错误.
: Base<Foo>(someValue, parent)
Run Code Online (Sandbox Code Playgroud)
编辑
是的,这确实看起来像一个bug.我之前提到的修复了os x下的错误,并且代码在fedora中使用该修复程序编译得很好.将去看看os x中是否有gcc更新.
第一:
[C++11: 12.6.2/3]:甲MEM-初始化列表可以使用任何初始化基类类或-decltype,它表示基础类类型.[ 例如:
Run Code Online (Sandbox Code Playgroud)struct A { A(); }; typedef A global_A; struct B { }; struct C: public A, public B { C(); }; C::C(): global_A() { } // mem-initializer for base A- 末端的例子 ]
并且Base应该是这里基数的有效注入类名(也就是说,您可以使用它来代替Base<T>):
[C++11: 14.6.1/1]:与普通(非模板)类一样,类模板具有注入类名(第9节).所述注入的类名可以被用作模板名称或类型名称.当它与template-argument-list一起使用时,作为模板模板参数的模板参数,或作为 友元类模板声明的详细类型说明符中的最终标识符,它引用类模板本身.否则,它等同于template-name,后跟括在其中的类模板的template-parameters<>.
[C++11: 14.6.1/3]:类模板或类模板特化的inject-class-name既可以用作模板名,也可以用作范围内的类型名.[ 例如:Run Code Online (Sandbox Code Playgroud)template <class T> struct Base { Base* p; }; template <class T> struct Derived: public Base<T> { typename Derived::Base* p; // meaning Derived::Base<T> }; template<class T, template<class> class U = T::template Base> struct Third { }; Third<Base<int> > t; // OK: default argument uses injected-class-name as a template- 末端的例子 ]
我没有发现任何迹象表明这不适用于ctor-initializer,所以我要说这是一个编译器错误.
我的精简测试用例在GCC 4.1.2和GCC 4.3.4中失败,但在GCC 4.5.1(C++ 11模式)中成功.它似乎是由GCC bug 189解决的; 在GCC 4.5发行说明中:
G ++现在实现了DR 176.以前,G ++不支持使用模板基类的inject-class-name作为类型名称,并且查找名称会在封闭范围内找到模板的声明.现在查找名称会找到inject-class-name,它可以用作类型或模板,具体取决于名称后面是否有模板参数列表.由于此更改,以前接受的某些代码可能格式不正确,因为
- 注入类名不可访问,因为它来自私有基础,或
- inject-class-name不能用作模板模板参数的参数.
在这两种情况中,可以通过添加嵌套名称说明符来明确命名模板来修复代码.第一个可以使用-fno-access-control解决; 第二个只是被拒绝了.
我使用Qt的精简测试用例抽象出来了:
template <typename T>
struct Base { };
struct Derived : Base<Derived> { // I love the smell of CRTP in the morning
Derived();
};
Derived::Derived() : Base() {};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11298 次 |
| 最近记录: |