Как этот синтаксис для определения полной специализации шаблона функции является другом класса? - PullRequest
0 голосов
/ 06 мая 2020

Я видел следующий пример в cppreference (раздел «Шаблонные дружественные операторы»), упрощенный

template<typename> struct Foo;
template<typename T> void bar(Foo<T>) {}

template<typename T>
struct Foo {
    // friend void bar<T>(Foo f);  // (1)
    friend void bar<>(Foo f);  // (2)
};

int main() {
    bar(Foo<int>{});
}

Здесь либо (1), либо (2) работают одинаково хорошо. Я понимаю, что в (1) компилятор говорит, что один конкретный c экземпляр bar (а именно bar<T> с такими-то параметрами) является другом Foo<T>, но я не понимаю, что происходит в (2).

Параметры какого типа компилятор использует для bar в (2)? Как это вообще работает? Как называется этот синтаксис, определен ли он где-нибудь в Стандарте?

1 Ответ

2 голосов
/ 06 мая 2020

См. C ++ 17 [temp.friend] / 1:

Другом класса или шаблона класса может быть шаблон функции или шаблон класса, специализация шаблона функции или класса. шаблон или нешаблонная функция или класс. Для объявления функции друга, которая не является объявлением шаблона:

  • , если имя друга является квалифицированным или неквалифицированным template-id , объявление друга относится к специализации шаблон функции, в противном случае
  • , если имя друга - квалифицированный-идентификатор и соответствующая нешаблонная функция найдена в указанном классе или пространстве имен, объявление друга относится к эта функция, в противном случае
  • , если имя друга - это квалифицированный-идентификатор и соответствующий шаблон функции найден в указанном классе или пространстве имен, объявление друга относится к выведенной специализации этого шаблона функции (17.8.2.6), в противном случае
  • имя должно быть unqualified-id , которое объявляет (или повторно объявляет) нешаблонную функцию.

Имена bar<T> и bar<> - это идентификатор шаблона s, поэтому, если вы используете любой из них, это относится к специализации функции. n шаблон ::bar. Как указано в [temp.arg.explicit]:

Аргументы шаблона могут быть указаны при ссылке на специализацию шаблона функции путем уточнения имени шаблона функции списком аргументов шаблона ... Список аргументов шаблона может быть указан при ссылке на специализацию шаблона функции ... в объявлении друга. Завершающие аргументы шаблона, которые могут быть выведены (17.8.2) или получены из аргументов-шаблонов по умолчанию, могут быть исключены из списка явных аргументов-шаблонов . ... Если все аргументы шаблона можно вывести, все они могут быть опущены; ...

Таким образом, значение bar<> в объявлении друга состоит в том, что вывод аргументов шаблона должен выполняться, чтобы определить, на какую специализацию bar делается ссылка. Конечно, выведенная специализация - это та, которая принимает аргумент типа Foo<T>. Таким образом, два объявления с bar<> и bar<T> будут иметь одно и то же значение.

...