2017-01-06 3 views
4

はちょうどこの無効である理由を不思議:なぜこの可変的なテンプレートはエラーですか?

#include <iostream> 

template <std::size_t... Is> 
void foo(Is&&... args) { 
    std::cout << "foo called with " << sizeof...(Is) << "params\n"; 
} 

int main() { 
    foo(1, 2, 3, 4); 
} 

は、それは完全に合理的な例だ、まだ私は私の手を得ることができる任意のコンパイラでfails

classの代わりにsize_tを使用すると、この例は正常に動作します。私も新しいautoテンプレートパラメータを使用しようとしましたが、オンラインコンパイラはこれを受け入れないので、これが無効なユースケースか適合問題かどうかわかりません。

+4

は 'Is'がタイプではない専用の概念を定義します。 'size_t'の値です。 – NathanOliver

+1

あなたは 'void foo(1 a、2 b、3 c、...)'を書かないので、なぜ 'void foo(Is ...)'と書いていますか? ;)標的用量をだます – Holt

+3

@BaummitAugenはなぜ@NathanOliver – NathanOliver

答えて

10

これは有効なC++ではないためです。

あなたが署名取得テンプレートに引数を代入した後、テンプレート引数1, 2, 3, 4でその関数テンプレートをインスタンス化した場合:

void foo(1&&, 2&&, 3&&, 4&&); 

明確に有効な機能ではありません。

あなたが任意の数の引数を受け入れますが、彼らは右のタイプである場合にのみ、あなたはこのようにC++ 17のことをで行うことができます関数テンプレートを作成したい場合:

template<typename T> 
    using is_size_t = std::is_same<T, std::size_t>; 

template<typename... T> 
    std::enable_if_t<std::conjunction<is_size_t<T>...>::value>> 
    foo(T&&... args); 

または代わりに(また、C++ 17)を使用して:

template<typename... T> 
    std::enable_if_t<(std::is_same_v<std::size_t, T> && ...)> 
    foo(T&&... args); 

14 C++のために、あなたはstd::conjunctionに、例えば自分で実装する必要がありますand_テンプレートを使用p0032r1

+0

C++ 14にfold式があるとは思いませんか? – Barry

+1

@Barry、oops、プリミティブなC++ 14が忘れていた;) –

+1

@JonathanWakelyそれは原始的ではない、そうでなければ完成した。 – skypjack

2

最近私は別の言語を使っていて、Monikaを完全に引っ張ってきました。

template <class... Is> 
    requires (std::is_same<Is, int>::value && ...) 
void foo(Is&&... args) { /*...*/ } 

、あるいは(ミリアンペアのFAV):ただ、これはすべてのパラメータがusing conceptsを(私は実際にやろうとしたもの)size_tタイプであることを確認する方法であるジョナサンの答えは、(説明のための感謝とコメント)を補完しますによって

template <class T> concept bool Integer = std::is_same<T, int>::value; 

template <Integer... Is> void foo(Is&&... args) { /*...*/ } 
//  ^^^^^^^awesome 

Live

+0

概念はC++言語の一部ではありません。 – Sjoerd

+1

@Sjoerd私は彼らのことを言っているわけではありません、私ですか?それらの添加を遅らせる理由の1つは、C++コミュニティは、テストを実験し、それらの上に手の込んだだろうとそうでした –

関連する問題