嵌套类友元函数可在GCC/Clang编译,MSVC报错,谁符合C++标准?
C++类内友元函数的跨编译器兼容性问题
我编写了一段在类内定义友元函数的C++代码,该代码可通过GCC和Clang编译,但被MSVC拒绝。
代码示例:
#include <iostream> template<typename T> class Outer { struct Inner; friend void foo(); }; template<typename T> struct Outer<T>::Inner { friend void bar(Inner) { // GCC和Clang接受,但MSVC拒绝此代码 typename Outer<int>::Inner k; std::cout << "bar called"; } }; void foo() { std::cout << "foo called"; Outer<int>::Inner i; bar(i); } int main() { Outer<int> outer; foo(); }
MSVC给出的错误信息(翻译后):
(14): error C2248: “Outer ::Inner”: 无法访问在类“Outer ”中声明的私有结构 (5): note: 参见“Outer ::Inner”的声明 (14): note: 参见“Outer ”的声明 (14): note: 模板实例化上下文(最早的优先)是 (17): note: 正在编译类模板实例化“Outer ::Inner”的引用 (14): note: 正在编译类模板实例化“Outer ::Inner”的引用 (12): note: 正在编译类模板成员函数“void bar(Outer ::Inner)” (22): note: 参见“bar”在“foo”中的第一个引用 Compiler returned: 2
根据C++标准,MSVC的处理是正确的,原因如下:
Outer<T>::Inner是Outer<T>的私有嵌套类,按照C++访问控制规则,只有Outer<T>的成员或友元才能通过Outer<T>::Inner的方式直接引用这个类型。bar是Outer<T>::Inner的友元函数,但友元关系是单向的——Inner的友元不会自动成为外围类Outer<T>的友元,因此bar没有权限通过Outer<int>::Inner的形式访问Outer<int>的私有成员Inner。- 若要让代码符合标准且兼容所有编译器,只需将
typename Outer<int>::Inner k;改为Inner k;即可:在Outer<T>::Inner的作用域内,Inner是直接可见的,无需通过外围类限定。
内容的提问来源于stack exchange,提问作者Anoop Rana
相关产品推荐
相关产品推荐

