2017-09-05 22 views
2

私は、次の構文を持っている:C++ 11:可変引数テンプレート控除ロジック

template <class... Args> 
class some_class 
{ 
public: 
    some_class() = default; 
    some_class(Args...) = delete; 
    ~some_class() = default; 
}; 

template<> 
class some_class<void> 
{ 
public: 
    some_class() = default; 
    ~some_class() = default; 
}; 

この理由は、私はちょうど、ユーザーは、デフォルトのコンストラクタを使用してオブジェクトを作成できるようにしたいということです例えばので:

some_class<int,float> b; 

は動作するはずですが、

some_class<int,float> c(1,3.4); 

は私にコンパイルエラーを与える必要があります。私もそれ故にvoidに基づいてテンプレートを作成するのに必要な時間の中でいくつかの点で

voidのための専門:

some_class<void> a; 

しかし、誤って私が入力した:

some_class<> d; 

そして突然、私のコードをコンパイルが停止し、エラーが表示されました。

some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be 
overloaded 
some_class(Args...) = delete; 

だからここに質問が来る:私はsome_class<>void専門に推理されるべきだと私は間違っていると感じる...私はちょうど理由を知らない。なぜsome_class<>(空の引数リスト)がsome_class<void>と異なるのか説明してください。 (正確には、不完全型)

https://ideone.com/o6u0D6

答えて

2

voidは、他のようなタイプである(標準から数行は:)行います)。これは、通常、型テンプレートパラメータのテンプレート引数として使用できることを意味します。あなたのクラステンプレートを取って、これらはすべて完全に有効であり、明確な、インスタンス:void:最初のケースで

some_class<void> 
some_class<void, void> 
some_class<void, void, void> 
some_class<void, char, void> 

、パラメータパックArgsは、一つの要素を持っています。 2番目のケースでは、2つの要素、voidvoidがあります。等々。

これはケースsome_class<>とはかなり異なります。この場合、パラメータパックの値はであり、値はです。あなたは簡単にsizeof...を使用してこれを実証することができます

template <class... Pack> 
struct Sizer 
{ 
    static constexpr size_t size = sizeof...(Pack); 
}; 

int main() 
{ 
    std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl; 
} 

この意志出力:

0 1 2

[Live example]

を私は実際に引用する標準の関連部分を考えることはできません。おそらくこれ(C++ 11 [temp.variadic] 14.5.3/1):

+0

ありがとうございます、あなたの答えは完全に状況を説明しています...クラスのいくつかの関数に引数型としてパラメータパックを使用するので(元々 'void'を引数をとらないものに変換したので)、私は元の問題はこのレベルを少し上回っています。議論パックからインスタンス化されたので、この拘束のために実際にそこに ' 'を置くことはなかったが、確かにこの答えは状況をはっきりと記述する。 – fritzone

関連する問題