7

そのため、テンプレート引数に基づいて文字列を解析するC++11より前に記述されたコードがあります。引数の数ごとに1つの定義を設定する代わりに、可変個引数テンプレートを使用したいのですが、タプルを正しく初期化する方法に頭を悩ませることはできません。私が欲しいもののこの単純化されたコードを見てください、これは2つの引数の特別な場合のためです:

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);             
  }
};

可変個引数の場合、タプルに引数を入れることに問題があります。次のコマンドで戻り値ホルダーを作成できます。

tuple<Args...> retVal; 

しかし、引数を繰り返してタプルに入れる方法があるかどうかはわかりません。たとえばprintf関数を取得するための再帰的な魔法を見たことがありますが、それがこの場合に適用できるかどうかはわかりません。

4

1 に答える 1

25

ヘルパー クラスは必要ありません。代わりに関数を使用してください。

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);
}

編集:今日、拡張を使用して非常に簡単な方法でそれを行う方法を思いつきました:

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);
}
于 2012-04-04T16:07:05.777 に答える