【问题标题】:Why does Visual C++ fail to compile a friend template inheriting from a private nested class?为什么 Visual C++ 无法编译继承自私有嵌套类的友元模板?
【发布时间】:2012-11-30 09:30:03
【问题描述】:

考虑以下代码:

class A {
  class B {};

  template <typename T>
  friend class C;
};

template <typename T>
class C : A::B {};

int main() { C<int> c; }

使用 GCC 和 Clang 可以正常编译,但 Visual C++ 2010 会报错:

test.cc(11) : error C2248: 'A::B' : cannot access private class declared in class 'A'

这是 Visual C++ 中的错误还是我遗漏了什么?

【问题讨论】:

    标签: c++ visual-c++ gcc compiler-errors g++


    【解决方案1】:

    1998 年标准和 2011 年标准都包含与示例基本相同的代码,分别在 14.5.3 #4 和 14.5.4 #3 中。

    class X {
      template<class T> friend struct A;
      class Y { };
    };
    template<class T> struct A { X::Y ab; }; // OK
    template<class T> struct A<T*> { X::Y ab; }; // OK
    

    显然这是一个错误。

    【讨论】:

    • 有趣的是,Comeau 的(在线)C++ 编译器也不喜欢 OP 的示例代码。不过它开始变得相当过时了。
    • 问题是,MSVC 2010 可以很好地编译您的示例(包括实例化 A&lt;int&gt; a1;A&lt;int*&gt; a2;),但它不会编译 OP 的示例。因此,MSVC 不喜欢两者之间存在一些差异,并且可能有一些合理的细节原因。
    • @MichaelBurr,很有趣,VS2010/VS2012/VS Nov 2012 CTP 在 OP 代码上给出错误,但在 template &lt;typename T&gt; class C : A::B { A::B x; }; 上成功:D
    【解决方案2】:

    是的。这肯定是 Visual C++ 编译器中的一个错误。

    脚注:GCC 编译器编译得很好。

    【讨论】:

      【解决方案3】:

      实际上,A::BA 私有的。

      这可能意味着,但这是我的解释,我必须用标准中的一段来支持它,你不能在全局范围内引用 A::B,更不用说声明任何 A::B 的子类,您也不能创建指向A::B 等的指针...

      另一方面,X 拥有A::B的访问权,因此可以声明它的子类:

      class A {
        class B {
        };
        template<typename T> friend class X;
        template<typename T> friend class Y;
      };
      
      template<typename T> class X : public A::B{};
      
      template<typename T>
      class Y {
        class B2 : public A::B {};
      };
      
      int main() { 
         X<int> x; 
         Y<int> y;
      }
      

      对于这个 sn-p,Comeau 没有告诉我 Y 不能被实例化。 VS2005 也没有。

      【讨论】:

      • 那么为什么template &lt;typename T&gt; class C : A::B { A::B x; }; 会像@chill 指出的那样工作?
      • @vitaut:他提到 vs2005 吗?
      • 不。我其实对vc2010很感兴趣,但是你的意思是vc2005也不接受这个吗?所以它要么是 vc2010 中引入的另一个不太可能的错误,要么是对原始错误的半熟修复。
      猜你喜欢
      • 2016-05-04
      • 1970-01-01
      • 2019-10-16
      • 2016-09-26
      • 1970-01-01
      • 2015-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多