模板特化的友元声明失败

发布于 2024-12-21 07:45:37 字数 813 浏览 2 评论 0原文

以下包含朋友声明的代码失败并显示错误(请参阅 http://ideone.com/Kq5dy):

template<class T> void foo() {}

template<typename T>
class A {
   void foo();
   friend void foo<T>(); // error: variable or field 'foo' declared void
};

int main()
{
   foo<int>();
}

如果把友元声明和成员函数声明的顺序颠倒一下,代码编译就没有问题了(参见http://ideone.com/y3hiK):

template<class T> void foo() {}

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

int main()
{
   foo<int>();
}

如果好友声明不包含模板专门化,则不会发生这种情况:非模板好友以及模板好友都可以。此外,在模板专业化中使用限定名称允许代码编译。 我的问题是为什么第一个例子失败了?编译器似乎在友元声明时在类作用域中查找名称,并且仅用于模板专业化?标准中的何处指定了这种行为?

The following code containing friend declaration fails with indicated error (see http://ideone.com/Kq5dy):

template<class T> void foo() {}

template<typename T>
class A {
   void foo();
   friend void foo<T>(); // error: variable or field 'foo' declared void
};

int main()
{
   foo<int>();
}

If the order of friend declaration and member function declaration reversed, then the code compiles without problems (see http://ideone.com/y3hiK):

template<class T> void foo() {}

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

int main()
{
   foo<int>();
}

This doesn't happen if the friend declaration doesn't contain template specialization: non-template friends are ok, as well as a template friends. Also using qualified name in template specialization allows code to compile.
My question is why does the first example fail? It seems compiler looking up names in class scope at the point of friend declaration and only for template specialization? Where in the Standard this behavior is specified?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

姜生凉生 2024-12-28 07:45:37

为了明确表明您想要成为该函数的friend,请在函数名称前添加 :: 来表示它位于全局命名空间中。

编译并执行您想要的操作的片段:

template<class T> void foo() {}

template<typename T>
class A {
   void foo();
   friend void ::foo<T>();
};

int main()
{
   foo<int>();
}

n1905。 pdf

3.4/9 名称查找

查找友元函数定义中使用的名称
(11.4) 在授予友谊的类中内联定义应如下进行
描述了在成员函数定义中的查找。如果朋友
函数未在授予友谊、名称查找的类中定义
在友元函数定义中应按照查找描述进行
在命名空间成员函数定义中

您的代码片段无法编译,原因与以下代码无法编译的原因相同。

template<class T> void foo () {}

template<typename T>
struct A { 

  void foo (); 

  void func () {
    foo<T> (); // when performing the name lookup A::foo is
               // found before ::foo<T>
  }
};

...

14.5.3 朋友 [temp.friend]
1

类或类模板的友元可以是函数模板或类模板,是
函数模板或类模板,或普通(非模板)
函数或类。对于不是友元函数声明
模板声明:

——如果朋友的名字是合格的或
不合格的 template-id,友元声明引用一个
函数模板的特化,否则

——如果名称
friend 是一个限定 ID,并且找到了匹配的非模板函数
在指定的类或命名空间中,友元声明引用
该函数,否则,

——如果好友的名字是限定 ID
并且函数模板的匹配专业化可以在
指定的类或命名空间,友元声明指的是
函数模板特化,否则,

—名称应为
unqualified-id 声明(或重新声明)普通(非模板)
功能。

To make it explicit that it's that function you want to be-friend prepend the function name with :: to say that it's in the global namespace.

Snippet that compiles and does what you want:

template<class T> void foo() {}

template<typename T>
class A {
   void foo();
   friend void ::foo<T>();
};

int main()
{
   foo<int>();
}

n1905.pdf

3.4/9 Name Lookup

Name lookup for a name used in the definition of a friend function
(11.4) defined inline in the class granting friendship shall proceed as
described for lookup in member function definitions. If the friend
function is not defined in the class granting friendship, name lookup
in the friend function definition shall proceed as described for lookup
in namespace member function definitions

Your snippet fails to compile because of the same reason as the code below fails to compile.

template<class T> void foo () {}

template<typename T>
struct A { 

  void foo (); 

  void func () {
    foo<T> (); // when performing the name lookup A::foo is
               // found before ::foo<T>
  }
};

...

14.5.3 Friends [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 an ordinary (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 specialization of a function template is found in the
specified class or namespace, the friend declaration refers to that
function template specialization, otherwise,

— the name shall be an
unqualified-id that declares (or redeclares) an ordinary (non-template)
function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文