声明模板函数的朋友涉及一些非常不直观的语法,即使对于C ++也是如此!为所需的额外<>
选择语法背后的理由是什么?使用template
关键字不是更有意义吗?
对于那些不了解这一点的人,以下是您可能尝试做的一个示例:
template <typename T>
class Foo
{
int x;
friend void bar(Foo<T>);
};
template <typename T>
void bar(Foo<T> f)
{
std::cout << f.x;
}
如果您尝试调用bar(Foo<T>())
,则会出现链接器错误。
要解决此问题,您必须转发声明bar
(因此Foo
),然后在朋友声明中粘贴一个奇怪的<>
。
template <typename T> class Foo;
template <typename T> void bar(Foo<T>);
template <typename T>
class Foo
{
int x;
friend void bar<>(Foo<T>); // note the <> (!?)
};
template <typename T>
void bar(Foo<T> f)
{
std::cout << f.x;
}
我的问题是,<>
语法背后的基本原理是什么?使用template
关键字或类似的东西不是更直观吗?
编辑:澄清一下,我已经知道为什么&lt;&gt;是必需的,我想知道他们为什么选择使用&lt;&gt;消除歧义而不是其他更直观的语法。
答案 0 :(得分:6)
等待。您没有声明朋友模板。您将模板的特化声明为朋友!因此,你为什么要在那里放一个template
条款?
命名函数模板特化的语法是teplateName<ArgumentList>
,这是你根据朋友声明中的标准使用的。
如果您希望与整个模板以及所有专业化生成并明确专业化,您仍然可以这样做,然后您可以使用模板子句
template<typename U>
friend void bar(Foo<U>);
答案 1 :(得分:2)
引用this page:
调用非模板函数是因为非模板函数优先于重载解析。
所以我猜friend void bar<>(Foo<T>);
很直观,因为你想确保它是你正在调用的模板函数,而不是Foo<T>
的重载。否则,编译器无法注意模板化或非模板化函数是否是类的朋友。
为什么使用<>
语法而不是template
语法对我来说并不清楚。