用于定义完整功能模板的语法如何专门化 class 的朋友?

How does that syntax for defining a full function template specialization a friend of a class?

我在 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) 中,编译器说 bar 的一个特定实例(即带有某某参数的 bar<T>)是 Foo<T> 的朋友,但我知道不明白 (2).

中发生了什么

(2) 中的 bar 编译器使用什么类型的参数?这通常是如何工作的?该语法是如何调用的,它是否在标准中的某处定义?

参见 C++17 [temp.friend]/1:

A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class. For a friend function declaration that is not a template declaration:

  • if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function template, otherwise,
  • if the name of the friend is a qualified-id and a matching non-template function is found in the specified class or namespace, the friend declaration refers to that function, otherwise,
  • if the name of the friend is a qualified-id and a matching function template is found in the specified class or namespace, the friend declaration refers to the deduced specialization of that function template (17.8.2.6), otherwise,
  • the name shall be an unqualified-id that declares (or redeclares) a non-template function.

名字bar<T>bar<>都是template-ids,所以如果你使用任何一个,那么它指的是函数模板 ::bar。如 [temp.arg.explicit] 中指定:

Template arguments can be specified when referring to a function template specialization by qualifying the function template name with the list of template-arguments ... A template argument list may be specified when referring to a specialization of a function template ... in a friend declaration. Trailing template arguments that can be deduced (17.8.2) or obtained from default template-arguments may be omitted from the list of explicit template-arguments. ... If all of the template arguments can be deduced, they may all be omitted; ...

因此,friend 声明中bar<> 的含义是,应进行模板参数推导以确定引用bar 的哪个特化。当然,推导的特化是采用 Foo<T> 类型参数的特化。所以带有 bar<>bar<T> 的两个声明具有相同的含义。