一个类模板的友元函数是否应该成为所有实例化的友元?

4

考虑以下代码片段:

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?
}

2020年5月6日的GCC主干编译成功,但Clang和MSVC无法编译通过,请参见Godbolt

谁是正确的?

来自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

并且

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
1个回答

2
GCC在这里显然是错误的:因为每个特化都定义了自己独立的友元函数(为了避免重复定义错误),bar(Foo<char>,Foo<char>)Foo<char> 的友元,但 bar(Foo<char>,Foo<char>) 不是。标准包含一个相关的例子,提到了一个非常相似的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接