2013-02-21 87 views
2

我與你分享了一個問題,我用類使用可變參數函數得到了一個問題。它是以下代碼中顯示的類Thread。它是std :: thread的一個包裝,以便使用函數模式。C++多態性與可變參數函數

我想在繼承Thread類進入一個新的類,仿函數使用多態性與這個功能,但是GCC返回錯誤吼叫:

#include <thread> 
#include <iostream> 

using namespace std; 

template<class... Args> 
class Thread 
{ 
public: 
    virtual void operator()(Args...) = 0; 

    void run(Args... args) 
    { 
    std::thread t(std::forward< Thread<Args...> >(*this), std::forward<Args>(args)...); 
    t.join(); 
    } 
}; 

template<class... Args> 
class Functor : public Thread<Args...> 
{ 
public: 
    // generates the errors bellow 
    virtual void operator()(Args... /*args*/) 
    { 
    } 

    // doesnot work since the pure virtual function wants another prototype of function. 
    // void operator()(int) 
    // { 
    // } 
}; 

int main() 
{ 
    int a = 12; 
    Functor<int> f; 
    f.run(ref(a)); 

    return 0; 
} 
 
from t-Thread-args2.cpp:1: 
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple: In instantiation of ‘struct std::_Head_base, false>’: 
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:215:12: required from ‘struct std::_Tuple_impl, int>’ 
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:507:11: required from ‘class std::tuple, int>’ 
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:1601:39: required from ‘struct std::_Bind_simple(int)>’ 
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/thread:133:9: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Thread; _Args = {int}]’ 
t-Thread-args2.cpp:14:83: required from ‘void Thread::run(Args ...) [with Args = {int}]’ 
t-Thread-args2.cpp:42:17: required from here 
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:166:13: error: cannot declare field ‘std::_Head_base, false>::_M_head_impl’ to be of abstract type ‘Thread’ 
t-Thread-args2.cpp:7:7: note: because the following virtual functions are pure within ‘Thread’: 
t-Thread-args2.cpp:10:18: note:  void Thread::operator()(Args ...) [with Args = {int}] 

我真的不理解,因爲純錯誤虛擬函數在派生類中被很好地定義。但是,在將函數run()移入派生類(Functor)中時,它起作用。

由於提前, 蠶兒

+0

「std :: forward」的用法沒有意義。它對函數模板有意義,但是在你的代碼中,run()不是函數模板。 – Nawaz 2013-02-21 07:51:01

+0

更具體地說,'std :: forward'在這裏沒有意義,因爲它的參數總是'* this',即總是一個左值。 – jogojapan 2013-02-21 07:57:45

+0

@jogojapan:「std :: forward」的參數幾乎總是左值,因爲它通常有一個*名稱*。 – Nawaz 2013-02-21 08:03:28

回答

2

按照[thread.thread.constr]§3中,std::thread構造函數的第一參數的類型是F&&,與FMoveConstructible是要求。在你的情況下,FThread,這不是MoveConstructible

換句話說,std::thread需要按值存儲仿函數,並且將函數轉發爲Thread,這是抽象的。

+0

您的意思是我必須從MoveConstructible繼承我的F類嗎? – canercandan 2013-02-21 09:37:09

+0

@canercandan'MoveConstructible'是一個概念,而不是一個類。它意味着「可以使用移動構造函數構造類型的實例。」你的'Thread'是抽象的,所以它根本不能創建實例。你應該用實際的派生類類型來模擬'run()',或者(最好)使用'std :: ref',正如Mike在他的回答中所建議的那樣。 – Angew 2013-02-21 09:40:26

1

的問題是:

std::forward< Thread<Args...> >(*this) 

它試圖複製Thread子對象。幸運的是它是抽象的,所以你得到一個編譯錯誤而不是意外的運行時行爲。

你要參考包裝來代替:

std::ref(*this) 
+0

非常感謝它! – canercandan 2013-02-21 09:36:18

1

我認爲由參與者提供該主題包括使用std::ref的多個建議,願與大家分享工作代碼版本解決的問題,我用以前的代碼得到。

#include <thread> 
#include <iostream> 

using namespace std; 

template<class... Args> 
class Thread 
{ 
public: 
    virtual void operator()(Args...) = 0; 

    void run(Args... args) 
    { 
    std::thread t(std::ref(*this), args...); 
    t.join(); 
    } 
}; 

template<class... Args> 
class Functor : public Thread<Args...> 
{ 
public: 
    void operator()(int) 
    { 
     while (1) 
      { 
      cout << "42 "; cout.flush(); 
      } 
    } 
}; 

int main() 
{ 
    int a = 12; 
    Functor<int> f; 
    f.run(ref(a)); 

    return 0; 
} 

再次感謝。

+0

請嘗試充實你的答案多一點。只是在沒有任何解釋或上下文的情況下發布代碼塊並不好,對於未來尋找這個問題的答案的人可能沒有任何價值。 – 2014-05-02 18:22:16

+0

@XaverKapeller剛剛編輯了更多解釋的答案。 – canercandan 2014-10-11 15:34:04