模板专业化的朋友声明失败

时间:2011-12-15 03:48:16

标签: c++ templates friend language-lawyer name-lookup

以下包含好友声明的代码失败并显示错误(请参阅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>();
}

如果朋友声明不包含模板专业化,则不会发生这种情况:非模板朋友可以,以及模板朋友。在模板专门化中使用限定名称也允许编译代码。 我的问题是为什么第一个例子失败了?似乎编译器在朋友声明点查找类范围中的名称,仅用于模板专业化?标准中的哪个行为被指定了?

1 个答案:

答案 0 :(得分:7)

要明确表示它是你想要的那个函数 - 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

     

类或类模板的朋友可以是函数模板或类模板,是a的特化   函数模板或类模板,或普通(非模板)   功能或类。对于不是的朋友函数声明   模板声明:

     

- 如果朋友的姓名是合格的或   unquali fi ed template-id,朋友声明指的是a   功能模板的特化,否则

     

- 如果是的话   friend是quali fi ed-id,找到匹配的非模板函数   在指定的类或命名空间中,友元声明引用   那个功能,否则,

     

- 如果朋友的名字是quali fi ed-id   并且在。中找到了函数模板的匹配特化   特定的类或命名空间,朋友声明指的是那个   功能模板专业化,否则,

     

- 名称应为   声明(或重新声明)普通(非模板)的unquali fi ed-id   功能