2016-09-18 10 views
0

我實現了將數據添加到二叉樹的一些基本功能。我想練習異步調用,因此我決定將Node添加爲async任務。但是,我在調用異步任務的行上發生構建錯誤。下面是示例代碼:使用異步添加二叉樹成員無法編譯

struct Node 
{ 
    static Node *root; 
    static mutex _mtx; 
    int _value; 
    Node *_left; 
    Node *_right; 

    Node() 
    { 
     _left = nullptr; 
     _right = nullptr; 
    } 

    Node(int value) 
    {  
     _left = nullptr; 
     _right = nullptr; 
     _value = value; 

     if (!root) root = this; 
     else 
     { 
      lock_guard<mutex> lck(_mtx); 
      auto func = bind(&Node::AddNodeAsync, root, ref(*this)); 
      auto ftr = async(launch::async, func); // Error!!!!!!  
     } 
    } 

    void AddNodeAsync(Node *parentNode, Node &nodeToAdd) 
    { 
     lock_guard<mutex> lck(_mtx); 
     AddNode(parentNode, nodeToAdd); 
    } 

    void AddNode(Node *parentNode, Node &nodeToAdd) 
    {   
     if (nodeToAdd._value < parentNode->_value) 
     { 
      if (parentNode->_left == nullptr) 
      { 
       parentNode->_left = &nodeToAdd; 
      } 
      else 
      { 
       AddNode(parentNode->_left, nodeToAdd); 
      } 
     } 
     else if (nodeToAdd._value > parentNode->_value) 
     { 
      if (parentNode->_right == nullptr) 
      { 
       parentNode->_right = &nodeToAdd; 
      } 
      else 
      { 
       AddNode(parentNode->_right, nodeToAdd); 
      } 
     } 
     else 
     { 
      assert(false); 
     } 
    } 
}; 

的錯誤,我得到:

Severity Code Description Project File Line Suppression State 
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' BinaryTree c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits 1468  

我在做什麼錯?

+2

取而代之的是'bind'呼叫和呼叫'AddNodeAsync'的,它可以全部使用單個[lambda表達式](http://en.cppreference.com/w/cpp/language/lambda)完成。 –

+0

用以下語句替換這兩個語句: auto ftr = async(launch :: async,[&](){AddNodeAsync(root,* this);}); 做到了!但爲什麼第一個版本不起作用? – omegasbk

回答

1

您想撥打哪個NodeAddNodeAsync*this?或root?這正是問題所在:你沒有一個實例可以調用AddNodeAsync

你想指定實例爲AddNodeAsync第一個參數(這是隱含的):

auto func = bind(&Node::AddNodeAsync, this, root, *this); 
             ^^^^ 
            instance to call AddNodeAsync on 

此外,it is better to use lambdas instead of std::bind

1

看看void AddNodeAsync(Node *parentNode, Node &nodeToAdd),它有兩個參數,它也是一個成員函數,它應該得到this綁定。現在看看你的bind

auto func = bind(&Node::AddNodeAsync, root, ref(*this)); 

所以,bind採取第一和第二個參數(第一個是一個成員函數,第二個是綁定在this),和他們緊緊聯繫在一起,它是作爲你在哪裏寫

root->AddNodeAsync(ref(*this)); 

正如你所看到的,你缺少一個參數。例如,該程序編譯好:

auto func = bind(&Node::AddNodeAsync, root, root, *this); 
1

你忘了參數:

auto func = bind(&Node::AddNodeAsync,this, root, ref(*this)); 
auto ftr = async(launch::async, func); 

無論如何,你可以使用lambda表達式在一行做:

auto ftr = async(launch::async, [this]{ this->AddNodeAsync(root,*this); });