Явная специализация не может быть декларацией друга

Код

template <typename T>
void foo(const T& t)
{}

template <typename T>
class A
{
template <>
friend void foo<T>(const T& t)
{}
};

выдает ошибку компиляции

"defining explicit specialization ‘foo<T>’ in friend declaration friend void foo<T>(const T& t)"

при компиляции с gcc и

"error C3637: 'A<int>::foo' : a friend function definition cannot be a specialization of a unction template"

при компиляции в VS2013

Я понимаю, что стандарт говорит так, но почему? Я хочу понять причину (под капотом)
Во многих статьях написано «Явная специализация не может быть декларацией друга», но я не могу понять, почему. Есть идеи?

4

Решение

Объявление явной специализации внутри шаблона класса в первый (и, возможно, единственный) раз будет означать, что явная специализация будет «существующей» только после того, как будет создан экземпляр шаблона — независимо от того, зависит объявление от параметра шаблона или нет.
Это создает много проблем и может привести к нарушениям УСО в различных сценариях, многие из которых будут предположительно плохо сформированными НДР; Главным образом из-за абзаца, упомянутого @dyp в комментариях, [temp.expl.spec] / 6

Кроме того, функция друга определение внутри класса без внешнего объявления эта функция вызывается только через ADL. Ясно, что было бы абсолютно бессмысленно, если бы явная специализация была применима только тогда, когда вызов имеет ассоциированные типы аргументов — опять же, не говоря уже о нарушениях ODR.

Эти и другие причины делают такую ​​конструкцию слишком сложной, но и не очень выгодной: просто добавьте специализацию как friend, никоим образом не указывая, является ли эта специализация конкретизированной или явно специализированной.

friend void foo<T>(const T&);

Любая явная специализация может быть добавлена ​​в область имен пространства.

4

Другие решения


По вопросам рекламы [email protected]