声明模板朋友的语法背后的基本原理是什么?

时间:2011-07-23 20:24:23

标签: c++ templates syntax friend

声明模板函数的朋友涉及一些非常不直观的语法,即使对于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;消除歧义而不是其他更直观的语法。

2 个答案:

答案 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语法对我来说并不清楚。