如何让call_once()在构造函数中正常工作?

时间:2018-05-04 06:40:29

标签: c++ multithreading

我已经在多线程上下文中测试了 call_once ()与变量的使用,并且行为符合预期。

但是,在多线程上下文中,我很难让 call_once ()与构造函数一起正常工作。

为此编写了以下program。它是Stroustrup在“CPL”第4版中提供的示例的修改。

/** 
    initialize_once_class_ctor.cpp

    Demonstrate the use of the once_flag type and the call_once() function
    to implement lazy initialization of a class' constructor.

**/

#include <mutex>    // once_flag, call_once()
#include <thread>   // thread
#include <iostream> // cout

using namespace std;

class X
{
private:
   static int data;
   static once_flag initdata_flg;

   static void init();

public:
   X()
   {
      call_once(initdata_flg, init);

      cout << "** diagnostic: X::data initialized"
           << endl; 
   }

   int getdata() const
   {
      return data;
   }
};


/** class X static members ...
    (static members must be defined 
    outside the class **/
int X::data;
once_flag X::initdata_flg;

void X::init()
{
   data = 915;
}


/// declarations ...

/// implementation ...

int main()
{
   thread t1 {X::X};
   thread t2 {X::X};

   t1.join();
   t2.join();
}


该程序会出现编译错误:

main.cpp: In function 'int main()':
main.cpp:57:19: error: no matching function for call to 'std::thread::thread(<brace-enclosed initializer list>)'
    thread t1 {X::X};
                   ^

In file included from main.cpp:10:
/usr/local/include/c++/8.1.0/thread:118:7: note: candidate: 'template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...)'
       thread(_Callable&& __f, _Args&&... __args)
       ^~~~~~
/usr/local/include/c++/8.1.0/thread:118:7: note:   template argument deduction/substitution failed:
main.cpp:57:19: note:   couldn't deduce template parameter '_Callable'
    thread t1 {X::X};
                   ^

In file included from main.cpp:10:
/usr/local/include/c++/8.1.0/thread:113:5: note: candidate: 'std::thread::thread(std::thread&&)'
     thread(thread&& __t) noexcept
     ^~~~~~
/usr/local/include/c++/8.1.0/thread:113:5: note:   no known conversion for argument 1 from '<unresolved overloaded function type>' to 'std::thread&&'
/usr/local/include/c++/8.1.0/thread:106:5: note: candidate: 'std::thread::thread()'
     thread() noexcept = default;
     ^~~~~~
/usr/local/include/c++/8.1.0/thread:106:5: note:   candidate expects 0 arguments, 1 provided

main.cpp:58:19: error: no matching function for call to 'std::thread::thread(<brace-enclosed initializer list>)'
    thread t2 {X::X};
                   ^

In file included from main.cpp:10:
/usr/local/include/c++/8.1.0/thread:118:7: note: candidate: 'template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...)'
       thread(_Callable&& __f, _Args&&... __args)
       ^~~~~~

/usr/local/include/c++/8.1.0/thread:118:7: note:   template argument deduction/substitution failed:
main.cpp:58:19: note:   couldn't deduce template parameter '_Callable'
    thread t2 {X::X};
                   ^

In file included from main.cpp:10:
/usr/local/include/c++/8.1.0/thread:113:5: note: candidate: 'std::thread::thread(std::thread&&)'
     thread(thread&& __t) noexcept
     ^~~~~~
/usr/local/include/c++/8.1.0/thread:113:5: note:   no known conversion for argument 1 from '<unresolved overloaded function type>' to 'std::thread&&'
/usr/local/include/c++/8.1.0/thread:106:5: note: candidate: 'std::thread::thread()'
     thread() noexcept = default;
     ^~~~~~
/usr/local/include/c++/8.1.0/thread:106:5: note:   candidate expects 0 arguments, 1 provided

如何修复这些编译错误?

1 个答案:

答案 0 :(得分:2)

永远不能直接调用构造函数(作为函数)。打字,例如X{}X()是用于创建X类型的(临时)对象,而不是以调用X的构造函数的语法。构造函数作为创建对象的一部分被调用,但那是内部的。

std::thread需要一个可调用的,而构造函数永远不能是一个。你可以提供一个lambda:

auto f = []{ X{}; };

thread t1 {f};
thread t2 {f};