C++ 类模板的友元函数是否应该成为所有实例化的友元?
考虑以下代码段:C++ 类模板的友元函数是否应该成为所有实例化的友元?,c++,templates,language-lawyer,friend-function,C++,Templates,Language Lawyer,Friend Function,考虑以下代码段: template<typename T> struct Foo { friend void bar(Foo, Foo<char> f) { static_cast<void>(f.private_field); // Should only compile when friends with Foo<char>. } private: int private_field{}; }; in
template<typename T> struct Foo {
friend void bar(Foo, Foo<char> f) {
static_cast<void>(f.private_field); // Should only compile when friends with Foo<char>.
}
private:
int private_field{};
};
int main() {
bar(Foo<char>{}, Foo<char>{}); // Compiles.
bar(Foo<bool>{}, Foo<char>{}); // Compiles erroneously?
}
模板结构Foo{
好友无效栏(Foo,Foo-f){
static_cast(f.private_field);//应该只在friends with Foo时编译。
}
私人:
int私有_字段{};
};
int main(){
bar(Foo{},Foo{});//编译。
bar(Foo{},Foo{});//编译错误?
}
它使用trunk(截至2020年5月6日)GCC成功编译,但不使用Clang和MSVC:请参阅
谁在这里?
来自Clang和MSVC的错误消息如下所示:
<source>:3:29: error: 'private_field' is a private member of 'Foo<char>'
static_cast<void>(f.private_field); // Should only compile when friends with Foo<char>.
^
<source>:11:5: note: in instantiation of member function 'bar' requested here
bar(Foo<bool>{}, Foo<char>{}); // Compiles erroneously?
^
<source>:6:9: note: declared private here
int private_field{};
^
1 error generated.
Compiler returned: 1
:3:29:错误:“private_field”是“Foo”的私有成员
静态_cast(f.private_字段);//应该只在朋友使用Foo时编译。
^
:11:5:注意:在这里请求的成员函数'bar'的实例化中
bar(Foo{},Foo{});//编译错误?
^
:6:9:注意:此处声明为私有
int私有_字段{};
^
生成1个错误。
返回的编译器:1
及
example.cpp
(3) :错误C2248:“Foo::private_字段”:无法访问类“Foo”中声明的私有成员
(6) :注意:请参见“Foo::private_字段”的声明
(2) :注:见“Foo”的声明
(2) :注意:编译类模板成员函数“void bar(Foo,Foo)”时
(11) :注意:请参阅正在编译的函数模板实例化“void bar(Foo,Foo)”的参考
(11) :注意:请参阅对正在编译的类模板实例化“Foo”的引用
返回的编译器:2
GCC在这里显然是错误的:因为每个专门化定义了自己单独的友元函数(因为它必须避免重复的定义错误),bar(Foo,Foo)
是Foo
的友元,但bar(Foo,Foo)
不是。该标准包含了一个相关案例,其中提到了一个非常类似的案例
example.cpp
<source>(3): error C2248: 'Foo<char>::private_field': cannot access private member declared in class 'Foo<char>'
<source>(6): note: see declaration of 'Foo<char>::private_field'
<source>(2): note: see declaration of 'Foo<char>'
<source>(2): note: while compiling class template member function 'void bar(Foo<bool>,Foo<char>)'
<source>(11): note: see reference to function template instantiation 'void bar(Foo<bool>,Foo<char>)' being compiled
<source>(11): note: see reference to class template instantiation 'Foo<bool>' being compiled
Compiler returned: 2