2017-05-05 108 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; 
}; 
相关问题