Должна ли дружественная функция шаблона класса стать другом для всех экземпляров? - PullRequest
4 голосов
/ 06 мая 2020

Рассмотрим следующий фрагмент:

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

Он успешно компилируется с транком (по состоянию на 6 мая 2020 г.) G CC, но не с Clang и MSV C: см. Godbolt .

Кто здесь?

Сообщения об ошибках от Clang и MSV C соответствуют ожидаемым:

<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 голосов
/ 06 мая 2020

G CC здесь явно ошибочен: поскольку каждая специализация определяет свою собственную отдельную функцию-друг (поскольку она должна избегать повторяющихся ошибок определения), bar(Foo<char>,Foo<char>) является другом Foo<char>, а bar(Foo<char>,Foo<char>) - нет. Стандарт содержит соответствующий пример , в котором упоминается очень похожий случай.

...