【问题标题】:Template + Friend (a deadly combination) [duplicate]模板+朋友(致命组合)[重复]
【发布时间】:2011-05-16 00:33:04
【问题描述】:

可能重复:
Making an undefined class as friend, and defining it later.

我有以下代码

template<typename T> 
class A
{
        class B;
        B b; 
};

int main() 
{
        return 0;       
}

代码不会发出任何错误,因为 A 没有被实例化。我说的对吗?

但是看看第二个代码示例

template<typename T>
class A
{
  protected:
        class a 
        {
            int x;
            int y;
          private:
            friend class b;  
        };
        template <typename U > class b
        {  
          int z;
          U y;
        };

};

int main()
{
    A<int>  a;
    return 0;
}

在这种情况下,A 被实例化,但 b 没有。所以代码不应该发出任何错误,对吧?但是我在 msvc++2008 专业版中遇到了重新声明错误。它在 gcc 上编译得很好。

错误的原因可能是什么?

对不起大家。在阅读了 cmets 并查看了我的原始代码之后,我发现我在输入第二个代码示例时犯了一个错误。 我错过了构造函数的定义和语句 a *object = new a;在构造函数内部。道歉。这意味着我的代码与其他用户发布的其他代码完全相同。但现在由于现有答案,我现在无法删除我的问题。

【问题讨论】:

  • 对于它的价值,Visual C++ 2010 接受了第二个示例。我没有在这台笔记本电脑上安装 Visual C++ 2008,但如果它给出错误,我会冒险猜测这段代码,很可能是 Visual C++ 2010 中修复的错误。
  • stackoverflow.com/questions/4274386/…其实身体几乎一模一样!
  • 此问题与this one 完全相同。投票关闭。 @James:仅供参考,代码没有在 Comeau 上编译。
  • @Prasoon:Comeau 没有错误地接受第二个示例。它不接受第一个示例,这是可以接受的(我不记得是否需要拒绝第一个示例,或者仅当模板被实例化时才被拒绝就足够了。我必须看看。)
  • 虽然代码可能相似,但我不认为它是完全重复的

标签: c++ templates scope friend


【解决方案1】:

代码不会发出任何错误 因为 A 没有被实例化。我是不是 对吧?

我不确定,但我不这么认为。发出错误的编译器也与不发出错误的编译器同样符合标准。

下面的引用以及紧随其后的示例是我认为的证明

$14.6/7 - "[注意:如果模板是 实例化,错误将被诊断 根据此中的其他规则 标准。正是当这些错误 被诊断是一种品质 实施问题。 ]"

【讨论】:

  • 当编译器甚至不知道模板中使用的类型时,它会很难产生错误。事实上,我认为在这里诊断任何类型的错误都不符合标准,原因与 SFNAE 原则有效的原因相同,但我并不肯定。
  • @Billy:我敢猜测,即使模板没有实例化,编译器也肯定会查找非依赖名称。
【解决方案2】:

根据当前标准§11.8,a 类无法访问封闭类的成员。但是标准对此有a defect report。因此,一些编译器根据原始标准工作,而其他编译器则根据缺陷报告的建议解决方案工作。

【讨论】:

    【解决方案3】:

    关于你的第二个代码 sn-p ...

    template<typename T>
    class A
    {
      protected:
            class a 
            {
                int x;
                int y;
              private:
                friend class b;  
            };
            template <typename U > class b
            {  
              int z;
              U y;
            };
    
    };
    
    int main()
    {
        A<int>  a;
        return 0;
    }
    

    ...很可能是无效代码,因为您之前在 SO 问题 "Making an undefined class as friend, and defining it later" 中发布的非常相似的代码 sn-p 无效。但我不确定。

    不同之处在于。您之前的问题只是在另一个问题中使用了嵌套类a,因此被实例化了。

    但是,您在 MSVC 8.0 中遇到的重新声明错误并不一定意味着该编译器将代码识别为无效的标准 C++。这可能是一个编译器错误,只是偶然导致它(可能)正确地将代码识别为无效。 可能上面的代码,没有使用a,是有效的……

    所以,它非常微妙,是语言律师的东西。

    最好的建议是远离语言中这些相当黑暗的角落。

    编辑:前面的问题不是 Pavel 的问题(但它是相同的代码);见 cmets。

    干杯,

    【讨论】:

    • 我没有问“stackoverflow.com/questions/4274386/…”这个问题。它是由其他用户提出的。
    • @Pavel:那么,您是否从那个问题中复制了您的代码?
    • 不,我在一些当地社区看到了类似的代码。
    【解决方案4】:

    MSVC 需要朋友模板类的完整模板 decl,MSDN has an example here,特别是底部示例:

    template <class T>
    class X
    {
    private:
       T* data;
       void InitData(int seed) { data = new T(seed); }
    public:
       void print() { cout << *data << endl; }
       template <class U> friend class Factory;
    };
    
    template <class U>
    class Factory
    {
    public:
       U* GetNewObject(int seed)
       {
          U* pu = new U;
          pu->InitData(seed);
          return pu;
       }
    }
    

    所以你的应该声明:

    template <typename U > friend class b;
    

    【讨论】:

      猜你喜欢
      • 2018-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-14
      • 1970-01-01
      • 2016-10-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多