2013-07-22 9 views
6

私は現在、バリデーションテンプレートサポートでできることのいくつかを頭に入れようとしています。のは、私はこのような機能を持っているとしましょう -既知のタイプのC++バリアント関数テンプレート

template <typename ... Args> 
void foo(Args ... a) 
{ 
    int len = sizeof...(tail); 
    int vals[] = {a...}; 
    /* Rest of function */ 
} 

/* Elsewhere */ 
foo(1, 2, 3, 4); 

私は、引数は整数になりますが、明らかに私は何か他のものを提供する場合に失敗しますので、あらかじめ想定しているため、このコードは動作します。私はこれをやって試してみましたが、コンパイラがエラーを与えた

void foo(int ... a) 

- 私は、パラメータパックは、事前に特定のタイプが含まれていることを知っていれば、私はテンプレートなしで行うとのようなものを持つことができますいくつかの方法がありますfooについてはvoidフィールドです。私は再帰を介してパック内のパラメータにもアクセスできることを知っていますが、これが私の問題を解決するかどうかはわかりません。つまり、同じタイプの引数を可変数にすることができます。

+1

あなたはすべてのタイプが* * int型であることを確認するために 'enable_if'を使用することができます。 –

+2

コードはintを束ねて動作します。あなたが他の何かを与えるなら、それはうまくいかない。ミッションが達成されたように見えます。問題はどこだ? –

+0

私は問題は、コンパイル時にintであることを保証できるかどうかということです。 – znby

答えて

3

あなたが前のタイプがわかっている場合は、std:initializer_listで、関数のオーバーロードを使用することができます。

#include <initializer_list> 
#include <iostream> 

void foo(std::initializer_list<int> l) 
{ 
    for (auto el : l) 
     // do something 
} 

void foo(std::initializer_list<float> l) 
{ 
} 

void foo(std::initializer_list<std::string> l) 
{ 
} 

int main() 
{ 
    foo({1, 2, 3, 4 }); 
    foo({1.1f, 2.1f, 3.1f, 4.1f }); 
    foo({ "foo", "bar", "foo", "foo" }); 
    return 0; 
} 

あなたは、Visual Studio 2012を使用する場合は、あなたがVisual C++ Compiler November 2012 CTPが必要な場合があります。

EDIT:あなたはまだ可変長引数テンプレートを使用したい場合は、あなたが行うことができます:

template <int ... Args> 
void foo() 
{ 
    int len = sizeof...(Args); 
    int vals[] = {Args...}; 
    // ... 
} 

// And 

foo<1, 2, 3, 4>(); 

しかし、あなたは、それは例えばfloatstd::stringで作業していないことを覚えている:あなたは'float': illegal type for non-type template parameterで終了します。 floatは、non-type template parameterとして正当ではありません。これは精度と関係があるもので、浮動小数点数を正確に表現することはできません。また、同じ型を参照する確率は、数値の表現方法によって異なる場合があります。

+0

'initializer_list'が' constexpr size() 'メンバーを提供しないので、コンパイル時に引数の数を知る必要がある場合は、この回避策では十分ではありません。 AFAIK、 'is_same <>/is_convertible <>'のチェックでバリデーショナルテンプレートの周りに方法はありません。 – user2523017

+0

@ user2523017あなたが正しいです、このソリューションでは、コンパイル時に引数の数を持つことはできません。 –

1

私は現在、可変的なテンプレートサポートでできることのいくつかを頭に入れようとしています。

#include <iostream> 

template<int ...Values> 
void foo2() 
{ 
    int len = sizeof...(Values); 
    int vals[] = {Values...}; 

    for (int i = 0; i < len; ++i) 
    { 
     std::cout << vals[i] << std::endl; 
    } 
} 

int main() 
{ 
    foo2<1, 2, 3, 4>(); 

    return 0; 
} 

foo2とあなたの違い:その後、私は以下のコードを見てみお勧め、あなたの問題への解決策を見つけることができません、あなたは可変引数テンプレートを試してみたいと仮定すると、

fooは、実行時にパラメータをfooに渡し、コンパイル時にfoo2に渡すため、使用するすべてのパラメータセットに対して、コンパイラは別のfoo2関数本体を生成します。

10

これは動作するはずです:

void foo(int); 

template<typename ...Args> 
void foo(int first, Args... more) 
{ 
    foo(first); 
    foo(std::forward(more)...); 
} 
+0

この回答は、OPが求めていたものに適しています。このソリューションの唯一の欠点は、再帰部分です。しかし、今はもっと良い解決策を見出すことができます。たとえC++ 17や折り畳み式を使うことさえできません。 – mic

関連する問題