C++ 无法访问错误的私有基类?

C++ 无法访问错误的私有基类?,c++,private,base-class,name-lookup,private-inheritance,C++,Private,Base Class,Name Lookup,Private Inheritance,使用g++4.2.1编译此代码: struct S { }; template<typename T> struct ST { }; template<typename BaseType> class ref_count : private BaseType { }; template<typename RefCountType> class rep_base : public RefCountType { }; class wrap_rep : pub

使用g++4.2.1编译此代码:

struct S { };
template<typename T> struct ST { };

template<typename BaseType>
class ref_count : private BaseType { };

template<typename RefCountType>
class rep_base : public RefCountType { };

class wrap_rep : public rep_base<ref_count<S> > {
  typedef rep_base<ref_count<S> > base_type;      // line 11
};
但是,如果我将
wrap_rep
类更改为使用
ST

class wrap_rep : public rep_base<ref_count< ST<int> > > {
  typedef rep_base<ref_count< ST<int> > > base_type;
};
class wrap\u rep:public rep\u base>{
typedef rep_base>base_type;
};
它编译得很好。或者,如果我将原始代码更改为:

class wrap_rep : public rep_base<ref_count<S> > {
  typedef rep_base<ref_count< ::S > > base_type;  // now using ::
};
class wrap\u rep:public rep\u base{
typedef rep_base>base_type;//现在使用::
};

它也编译得很好。对我来说,原始代码看起来很好。这是一个g++错误吗?如果没有,那么为什么使用模板有效呢?对于另一种情况,为什么需要
::S

在“Sun WorkShop 6 update 2 Compilers C++”中编译的原始代码很好。这是我办公室里唯一可以使用的。可以在您拥有的任何其他编译器上试用。

您的结构
S
wrap\u rep
的基类,这意味着它被注入到
wrap\u rep
中,就像存在匿名typedef一样

在typedef中使用
S
之前的运算符
将告诉编译器不要使用继承自的
S
,而是在全局命名空间中使用
S


请参阅。

这两个代码都无效(只有最后一个代码有效),但您的编译器(不符合要求)只诊断一个。另一个答案是,它使用注入的类名。类
S
被认为具有表示同一类的成员名
S
。例如(注意第一个示例中
S::S
前面的“class”关键字是强制引用注入的类名而不是默认构造函数所必需的):

类模板也有一个注入的类名。与注入的类名一样,它被继承到派生类,因此
ST
的格式不正确,因为它使用了注入的类名,但是无法访问该类名。如果使用GCC4.5,可能与GCC4.5有关:

G++现在实现dr176。以前,G++不支持使用模板基类的注入类名作为类型名,通过查找名称,可以在封闭范围内找到模板的声明。现在,查找名称会找到注入的类名,该类名可以用作类型或模板,具体取决于名称后面是否有模板参数列表。由于此更改,以前接受的某些代码可能格式错误,因为

  • 注入的类名不可访问,因为它来自私有基,或者
  • 注入的类名不能用作模板参数的参数
  • 在这两种情况下,都可以通过添加嵌套的名称说明符来明确命名模板来修复代码。第一个可以通过-fno访问控制来解决;第二种只是被拒绝了-迂腐


    为了让注入的类名更加有趣,请注意,注入的类名并不像人们首先想到的那样等同于typedef。注入的类名是类名,但未分类为typedef名称,这意味着它可以通过函数、对象或枚举器名称隐藏:

    // valid, the data-member hides the injected class name
    struct S { int S; };
    
    要引用注入的类名,您可以说
    classs::S
    (同样,在基类列表中,非类型名称被忽略,因此不需要特别注意),但对
    S::S
    的简单查找将引用数据成员

    class S { };
    
    class S::S object; // creates an S object
    class X : S::S::S::S { }; // derives from class S
    
    // valid, the data-member hides the injected class name
    struct S { int S; };