2017-05-05 169 views
4

我試圖創建一個名爲Sink的類,它將創建一個指向您傳入的類的指針,這是在RAII中包裝api。從可變參數模板構造類

在此代碼的完整版本中,自定義類也從另一個類繼承,並且有靜態資產來檢查它。指針也傳遞給api。

但爲了保持簡單,我已將其刪除。

這是我從cpp.sh

In function 'int main()': 
43:30: error: no matching function for call to 'Sink<OneArg>::Sink(int)' 
43:30: note: candidate is: 
10:5: note: Sink<CustomSink, Args>::Sink(Args&& ...) [with CustomSink = OneArg; Args = {}] 
10:5: note: candidate expects 0 arguments, 1 provided 

代碼得到錯誤:

#include <string> 
#include <iostream> 
#include <memory> 
#include <utility> 

template<typename CustomSink, typename... Args> 
class Sink 
{ 
public: 
    Sink(Args&&... args) 
    {   
     _ptr = std::make_unique<CustomSink>(std::forward<Args>(args)...);   
    } 
    ~Sink() 
    { 
    } 
private: 
    std::unique_ptr<CustomSink> _ptr; 
}; 


////////////////////////////////////////////////////////////////////// 
class NoArg 
{ 
public: 
    NoArg() {}; 
    ~NoArg() {}; 
}; 

class OneArg 
{ 
public: 
    OneArg(int a) { 
     std::cout << a << '\n'; 
    }; 
    ~OneArg() {}; 
}; 
////////////////////////////////////////////////////////////////////// 


int main(){ 
    Sink<NoArg> noArgSink; 
    Sink<OneArg> oneArgSink(5); 

    return 0; 
} 

回答

5

這裏你的問題是與安置模板類型Args。現在你在班上tempalte有Args所以

Sink<OneArg> oneArgSink(5); 

Args是空的,所以Sink的構造函數沒有預期到的參數。你需要做的是將Args作爲模板移動到構造函數中。這就給了你

template<typename... Args> 
Sink(Args&&... args) 
{   
    _ptr = std::make_unique<CustomSink>(std::forward<Args>(args)...);   
} 

而現在的構造函數將演繹,而不必在聲明類指定它傳遞給它的參數。

5

模板的構造函數的參數應該從類移動到模板構造函數:

template<typename CustomSink> 
class Sink 
{ 
public: 
    template <typename... Args> 
    Sink(Args&&... args) 
    {   
     _ptr = std::make_unique<CustomSink>(std::forward<Args>(args)...);   
    } 
private: 
    std::unique_ptr<CustomSink> _ptr; 
}; 
3

Accordin克至你的設計,你必須寫:

Sink<OneArg, int> oneArgSink(5); 

demo

事實上,構造函數的參數數量和類型是由你的模板(typename ... Args)的可變參數部分決定。但是這部分是依附於類,而不是構造函數。所以你必須在實例化模板時指定它。

否則,如果你要尊重你的實例,讓編譯器確定模板參數,你必須將你的模板的構造函數的可變參數的一部分(見Jarod42 answer,或NathanOliver's one

1

您聲明類Sink的方式意味着您需要在模板實例化處指定Args...

這意味着如果您聲明Sink<OneArg>,您實際上使Args...爲空,並且構造函數不期望任何參數。這就是爲什麼編譯器會抱怨將參數傳遞給構造函數。

您只需要構造函數中的可變參數模板。這樣你甚至可以容納具有不同數量參數的多個構造函數的類。

template<typename CustomSink> 
class Sink 
{ 
public: 
    template<typename... Args> 
    Sink(Args&&... args) 
    { 
     _ptr = std::make_unique<CustomSink>(std::forward<Args>(args)...); 
    } 
    ~Sink() 
    { 
    } 
private: 
    std::unique_ptr<CustomSink> _ptr; 
};