2012-04-04 14 views
4

テンプレート引数に基づいて文字列を解析するC++ 11より前に書かれたコードがいくつかあります。引数の数ごとに1つの定義を持たせるのではなく、バリデーショナルなテンプレートを使いたいのですが、タプルを正しく初期化する方法については頭を悩ますことはできません。私は可変長の場合にはタプルの引数を置くの問題を抱えている可変長テンプレートを使用してタプルを構築する

template <typename Arg1, typename Arg2> 
struct parser 
{ 
    static tuple<Arg1, Arg2> parse(const string& str) 
    { 
    Arg1 arg1; 
    Arg2 arg2; 
    // do the parsing with for example stringstream 
    return tuple<Arg1, Arg2>(arg1, arg2);    
    } 
}; 

:これは2つの引数の特殊な場合であるが、私が何をしたいのこの単純化されたコードを参照してください。私は、戻り値ホルダーを構築することができます。

tuple<Args...> retVal; 

が、引数を反復処理し、タプルでそれらを配置する方法があるかどうかはわかりません。私は、例えば、printf関数を得るための再帰的な魔法を見てきましたが、このケースに適用できるかどうかはわかりません。

+0

あなたはに基づいてタプルの種類を変更しようとしています文字列解析から何が出ましたか? – cababunga

+1

再帰を使わずにタプルのすべての要素を調べることは可能ですが、追加の関数呼び出しを犠牲にします。私は技術を何回か記述しました([ここ](http://stackoverflow.com/questions/9730593/how-can-i-call-a-set-of-variadic-base-class-constructors-based-on (ここでは( - )タグ付きargumen/9731981#9731981)、[ここで(http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates/7383493#7383493) http://stackoverflow.com/questions/7089284/dynamic-dispatching-of-template-functions/7089649#7089649))。 (重要なビットはそれぞれの場合に 'インデックス 'となります。) –

答えて

15

ヘルパークラスは不要です。代わりに関数でそれを行います。

template <typename T> std::tuple<T> parse(std::istream& is) 
{ 
    T t; is >> t; 
    return std::tuple<T>(std::move(t)); 
} 

template <typename T, typename Arg, typename... Args> 
std::tuple<T, Arg, Args...> parse(std::istream& is) 
{ 
    T t; is >> t; 
    return std::tuple_cat(std::tuple<T>(std::move(t)), 
         parse<Arg, Args...>(is)); 
} 

template <typename... Args> 
std::tuple<Args...> parse(const std::string& str) 
{ 
    std::istringstream is(str); 
    return parse<Args...>(is); 
} 

EDIT:今日、私は膨張を利用して、非常に簡単な方法でそれを行うにはどのようにアイデアを得た:

template <typename T> T read(std::istream& is) 
{ 
    T t; is >> t; return t; 
} 

template <typename... Args> 
std::tuple<Args...> parse(std::istream& is) 
{ 
    return std::make_tuple(read<Args>(is)...); 
} 

template <typename... Args> 
std::tuple<Args...> parse(const std::string& str) 
{ 
    std::istringstream is(str); 
    return parse<Args...>(is); 
} 
+0

thanx、tuple_catのような関数があったことは分かりませんでした。 – Rolle

+0

@ipc std :: make_tuple(read (is)...)を使用すると、ストリームが読み込まれる順序が未定義のようです。 @stackoverflow.com/questions/14056000/how-to-avoid-undefined-execution-order-for-the-constructors-when-using-stdmakeを参照してください。 –

+1

@ErikSjölund:AFAIRはよく定義されています(8.5節参照)。 4/4)。 – ipc

関連する問題