C++ c和x2B之间的相互作用+;11 std::线程和类友元函数

C++ c和x2B之间的相互作用+;11 std::线程和类友元函数,c++,c++11,friend,stdthread,C++,C++11,Friend,Stdthread,我在理解一个编译器错误时遇到了问题。我试图使用一个声明为c++11std::thread对象中某个类的友元的函数。我创建了一个小示例来说明我遇到的问题。基本上,当编译器只看到aa的friend函数原型时,它会在将该函数传递到线程对象时抛出一个未定义的符号错误。我使用的是g++4.9.2 //test.cpp #include <thread> class A { public: friend void aa(A &p); void av(void); }; voi

我在理解一个编译器错误时遇到了问题。我试图使用一个声明为c++11
std::thread
对象中某个类的友元的函数。我创建了一个小示例来说明我遇到的问题。基本上,当编译器只看到
aa
friend
函数原型时,它会在将该函数传递到线程对象时抛出一个未定义的符号错误。我使用的是g++4.9.2

//test.cpp
#include <thread>

class A {
public:
  friend void aa(A &p);
  void av(void);
};

void A::av() {
  std::thread t1(aa,std::ref(*this));
}

void aa(A &p) {
  p;
}

int main() {
  A ai;
  ai.av();
  return 0;
}
我发现编译器错误:

test.cpp: In member function ‘void A::av()’:
test.cpp:12:18: error: ‘aa’ was not declared in this scope
   std::thread t1(aa,std::ref(*this));
在上面,如果我更换该行

std::thread t1(aa,std::ref(*this));

这个编译得很好。或者,如果我在
A::av
的定义上方添加另一个函数的原型声明,如:

void aa(A &p);
它可以很好地编译线程对象声明

那么,当我试图仅用友元原型声明线程对象时,为什么编译器会反对呢


我意识到在这个简单的示例中,我可以将
aa
的声明移到
A::av
的定义之上,但是在实践中,我想做一些更复杂的事情,其中我有一个包含
B::av
的派生类
B
aa
的定义逻辑上放在
A
的实现文件中,而原型为
aa
的类
A
的定义位于类
B
定义中包含的头文件中。这是一个编译器错误,还是我声明某些东西的方式有问题?

只有类内声明,friend函数只能通过依赖于参数的查找来使用。要按名称指定它而不调用它,就像您在
av
的定义中所做的那样,您需要事先在全局命名空间中声明它,或者将定义移到较早的位置。

哇,太快了!在我最后描述的场景中,您能推荐一种避免两次定义函数的方法吗?基本上我有A.cpp,A.hpp,B.cpp B.hpp main.cpp,我在A.cpp中定义aa,在A.hpp中声明朋友原型,并想在B.cpp中使用它(B是A的派生类)。@matth:在命名空间中声明它,以及在
A.hpp
中声明类……或者将lambda传递给
std::thread
因此ADL工作:
std::thread t1{[=]{aa](*这个);}}
。谢谢。这很有帮助。
aa(*this);
void aa(A &p);