2017-05-05 12 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; 
}; 
関連する問題