【问题标题】:friend operator << and private access of template class member友元运算符 << 和模板类成员的私有访问
【发布时间】:2016-09-06 23:03:09
【问题描述】:

阅读this answer后,我做了一些测试,我想出了以下代码:

#include <iostream>

template <typename T> 
class Test {
    int val{42};

    friend std::ostream & operator << (std::ostream & flux, Test const & instance) {
        return flux << Test<char>{}.val;
    }
};

int main() {
    std::cout << Test<int>{};
    return 0;
}

main() 中使用Test&lt;int&gt;,我认为operator&lt;&lt; 无法访问Test&lt;char&gt;{}.val。但令我惊讶的是,GCC 编译得很好。

然后,我使用 Clang 和 Visual Studio 进行了测试,两者都给了我一个私有成员错误,正如预期的那样(请参阅 GCC/Clang demo)。

哪个编译器是正确的?

另外,我想知道在哪种情况下需要链接中提到的 extrovert 版本?或者从Test&lt;T&gt;operator&lt;&lt; 内部对Test&lt;U&gt; 的私人访问(当T != U 时)?你有什么实际的例子吗?

【问题讨论】:

  • 您询问的是哪个版本的 C++?您使用了哪些编译器版本?
  • 我在标准 (C++11) 中没有看到任何证据表明该程序应该被认为是有效的,但 GCC 接受似乎如此明显的错误令人怀疑。
  • 也许有人误读了 14.5.4/5... 11.3/2 很清楚,没有什么与我发现的矛盾之处。我建议您将其发布在 GCC 的 Bugzilla 上,然后用一个答案向我们报告开发人员得出的任何结论。

标签: c++ templates operator-overloading friend ostream


【解决方案1】:

我相信 Clang/VS 正在使用正确的行为,因为如果您创建一个新实例(如在您的示例中)而不是使用参数中的友元实例,我相信它会将访问重置为就好像它来自外部一样。

至于额外的问题,我想不出一个外向的实际例子,但我想它存在的原因与 C++ 中的许多事情相同,如果你愿意,可以让你这样做。也许用它来从一种类型转换为另一种类型?不确定,对不起^^;

PS 对最初的混乱表示抱歉。

【讨论】:

  • “你链接的DEMO现在显示的错误和Clang或VS基本一样”不,仔细看!
  • "g++ -std=c++11 main.cpp && echo "GCC OK" && clang++ -std=c++11 main.cpp GCC OK main.cpp:8:37: 错误: 'val' 是 'Test' 的私有成员 return Flux {}.val; ^ main.cpp:13:15: 注意:在此处请求的成员函数 'operator{}; ^ main.cpp:5:9: 注意:这里隐式声明私有 int val{42}; ^ 1 错误生成。“这几乎正是我从 clang 中得到的。
  • 的clang输出。 GCC 不发出任何诊断信息。这就是echo "GCC OK" 存在的原因 - 表明第一个诊断来自对 clang 的调用。
  • 啊,对不起。在链接被简单地标记为 DEMO 之前和之前从未使用过该网站。
  • 不是很清楚。我一开始的解释和你一样。
猜你喜欢
  • 1970-01-01
  • 2011-10-20
  • 2019-08-08
  • 2019-05-29
  • 2021-05-29
  • 2016-08-27
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
相关资源
最近更新 更多