【问题标题】:template private inheritance in vc++10 is not accessiblevc++10中的模板私有继承不可访问
【发布时间】:2026-02-02 18:15:01
【问题描述】:

以下代码使用 GCC 4.4.6 和 Comeau 4.3.10 编译。

#include <iostream>

struct A { int name; };
template<typename T> struct C : T { using T::name; };
struct B : private A { friend struct C<B>; };

int main()
{
    C<B> o;
    o.name = 0;
}

VC++10 报如下错误:

main.cpp(4): error C2877: 'A::name' is not accessible from  'A'
main.cpp(10): error C2247: 'A::name' not accessible because 'B' uses 'private' to inherit from 'A'

允许o.name = 0; 的好的交叉编译器解决方法是什么?

注意:using A::name 添加到B 可以解决问题,但会将A::name 成员发布给所有人,而它应该只对特定模板实例化可见,即@ 987654328@.

【问题讨论】:

  • 不应该是using T::name; 吗?这个语言功能怎么称呼?
  • 访问声明,见*.com/questions/2084801/…
  • 如果将using A::name; 添加到B 中会发生什么?
  • @Nick:添加using A::name 没有任何缺点。按照标准应该是没有必要的,但绝对没有不良影响。名称查找出现在访问控制之前。但它也不会造成伤害,也不会妨碍您,所以请随意将其留在里面。
  • 其实你可以说B确实有一个成员,即私有继承的A实例。

标签: c++ templates visual-c++ private-inheritance


【解决方案1】:

解决方法是@kerrekSB 建议的,在B 类中添加using A::name;

struct A { int name; };
template<typename T> struct C : T { using T::name; };

struct B : private A { 
using A::name; 
friend struct C<B>;
};

您的初始示例不起作用,因为类 AB 私有的,而类 C&lt;B&gt;B 的朋友,但是当您从 C&lt;B&gt; 的对象访问成员 name 时,行 @987654330 @ 产生问题,因为类 B 中没有任何成员 name。当您尝试通过 B 类的对象访问成员 name 时,它是范围搜索

编辑:

使用 A::name 添加到 B 可以解决问题,但会发布 A::name 成员对每个人,而它应该只对一个人可见 特定模板实例化,即C

如果是这种情况,那么只需在 B 类的私有部分中声明语句 using A::name;

struct B : private A {
protected: using A::name; 
public:
friend struct C<B>;
};

【讨论】:

  • 有趣的是,当您尝试一个没有模板的简化示例时(例如,从 B 派生的 C 类,它从具有成员名称的 A 私有派生,然后 gcc 和 VC++ 都抱怨using B::name in C - 当然,因为 name 不是 B 的成员...但是为什么 gcc 在 OP 的示例中不抱怨对我来说是个谜,VC++ 的行为在我看来是正确的。
  • @nyarlathotep gcc 有这个错误我想说虽然上面的例子在 gcc 中有效
  • 为什么不使用protected: using A::name;?这将完全解决我的问题并保持预期的隔离级别。
【解决方案2】:

在使用 member using-declarations 时,gcc 和 VC++ 之间的可见性考虑似乎存在根本差异;检查这个没有模板的简化示例:

struct A { int name; };
struct B: private A { friend struct C; };
struct C: B {using B::name; };

int main()
{
   C o;
   o.name = 0;
}

它将在 gcc 上编译,但不能在 VC++ 上编译(与问题中的错误基本相同)。将不得不咨询谁做对的标准......

【讨论】:

  • 您是否考虑了friend struct C&lt;B&gt; 行?
  • @Nick:那条线有什么改变吗?我认为不会;请参阅我对这个问题的评论。 C 仍然是 B(没有任何成员)的朋友,而不是 A(为了访问 A::name 而需要它)。但是请随意说服我;)
  • 该行使 GCC 能够编译。
  • 啊,是的,VC++ 可能对using 有更严格的名称解析规则,因为我上面的简化示例也不会在 VC++ 中编译,而在 gcc 中可以。