类无法与不在其命名空间中的函数交朋友

时间:2014-10-31 15:23:03

标签: c++ namespaces argument-dependent-lookup

我很难理解以下MWE无法编译的原因:

#include <iostream>

namespace N
{
    class Foo
    {
        friend void bar( Foo& f );
        void print(){ std::cout << "..." << std::endl; }    // private by default
    };  
}

void bar( N::Foo& f )
{
    f.print();
}

int main()
{
}

g ++ 4.8.2错误

Test.cpp: In function ‘void bar(N::Foo&)’:
Test.cpp:8:8: error: ‘void N::Foo::print()’ is private
   void print(){ std::cout << "..." << std::endl; } // private by default
        ^
Test.cpp:14:10: error: within this context

我几乎肯定在这里遗漏了一些东西,但朋友函数bar()肯定可以访问班级N::Foo的任何私人成员。

请注意:

  1. bar()移动到命名空间N可以解决此错误。
  2. 如果::bar()未调用N::Foo::print()
  3. ,则代码会进行编译

    为什么代码不按原样编译?

    修改

    第二个想法,这个问题的标题并没有准确地描述问题。我会在适当的时候编辑它。

1 个答案:

答案 0 :(得分:5)

非限定友元声明是指包含该类的命名空间中的函数,如果尚未声明该函数,则将该函数引入该命名空间。

我将该功能移到命名空间中。它可以通过参数依赖查找找到,因此您可以使用不合格的bar(foo)来调用它,而无需N::

如果由于某种原因确实需要它在全局命名空间中,那么在将它声明为朋友之前,您需要在全局命名空间中声明它。这有点乱:

// Need the class definition to declare the function
namespace N {class Foo;}

// Need the function definition to declare it a friend
void bar( N::Foo& );

// Need the class definition to define the function
namespace N
{
    class Foo
    {
        friend void ::bar( Foo& f );
        void print(){ std::cout << "..." << std::endl; }    // private by default
    };  
}

// And finally the function
void bar( N::Foo& f )
{
    f.print();
}