c ++ 11 std :: thread和类友元函数之间的交互

mat*_*tth 3 c++ friend c++11 stdthread

我无法理解编译器错误我正在尝试使用声明为c ++ 11 std::thread对象中的类的朋友的函数.我创建了一个小例子来展示我遇到的问题.基本上,当编译器只看到friend函数原型时aa,它会在函数传递给线程对象时抛出一个未定义的符号错误.我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)

编译命令:

g++ -o test test.cpp -g -O0 -std=c++11 -lpthread
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误:

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));
Run Code Online (Sandbox Code Playgroud)

在上面,如果我更换线

std::thread t1(aa,std::ref(*this));
Run Code Online (Sandbox Code Playgroud)

aa(*this);
Run Code Online (Sandbox Code Playgroud)

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

void aa(A &p);
Run Code Online (Sandbox Code Playgroud)

它使用线程对象声明编译好.

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

我意识到在这个琐碎的例子中我可以移动aa上面的定义声明A::av,但是在实践中我想做一些更复杂的事情,我有一个派生类B包含B::av,并且定义在aa逻辑上放在实现文件中A,而类的定义A与原型的aa位于包含在类定义中的头文件中B.那么这是一个编译器错误,还是我声明某些东西的问题?

Mik*_*our 5

只有一个类内声明,友元函数只能通过参数依赖查找.要按名称指定它而不调用它,就像在定义中那样av,您需要事先在全局命名空间中声明它,或者将定义移动到更早的点.

  • ...或者将lambda传递给`std :: thread`以便ADL工作:`std :: thread t1 {[=] {aa(*this); }}`. (2认同)