2

Johannes Schaub-litbLuc Dantonからの回答を基にしたコードを使用して、タプルを出力する短いプログラムを次に示します。

#include <iostream>
#include <tuple>

template<int ...>
struct seq { };

template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };

template<int ...S>
struct gens<0, S...> {
  typedef seq<S...> type;
};

template <int ...S, typename ...T>
void print(const std::tuple<T...> & tup, seq<S...> s) {
  int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
  std::cout << std::endl;
}

int main() {
  std::tuple<double, int, char> tup(1.5, 100, 'c');
  print(tup, gens<std::tuple_size<decltype(tup)>::value >::type());
  return 0;
}

print の 2 番目の引数は常に になりますgens<N>::type()。ここNで、 はタプルのサイズです。デフォルトの引数を指定することで、print の 2 番目の引数を回避しようとしています。

template <int ...S, typename ...T>
void print(const std::tuple<T...> & tup, seq<S...> s = gens<std::tuple_size<decltype(tup)>::value >::type()) {
  int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
  std::cout << std::endl;
}

ただし、結果はコンパイラ エラーです。

tmp5.cpp: 関数 'void print(const std::tuple<_Elements ...>&, seq) [with int ...S = {}; T = {double, int, char}]':
tmp5.cpp:23:12: エラー: 不完全な型 'std::tuple_size&>' がネストされた名前指定子で使用されています

S...のような関数に2番目の引数なしで提供する方法を知っていますprintか?

4

3 に答える 3

3

いいえ、ありません。

実際のところ、この問題は可変個引数テンプレートに限定されたものではなく、すべてのテンプレート関数で発生します。引数のテンプレート型はデフォルト値から推定できません。

template <typename T>
void func(T = 0) {} // expected-note {candidate template ignored:\
                                      couldn't infer template argument 'T'}

int main() {
  func(); // expected-error {no matching function for call to 'func'}
}

ギアを切り替える必要があります。

これを行う最も簡単な方法は、2 番目の引数を渡すタスクを実行するオーバーロードを提供することです。結局のところ、デフォルトの引数は、転送関数の記述を避けるための単なる構文糖衣です。

于 2012-05-25T08:43:01.950 に答える
3

S...問題は、関数の 2 番目の引数を指定しないと、コンパイラがインデックス シーケンスを推測する方法がないことです。デフォルトの引数に到達するまでに、何が何でS...あるかを知る必要があるため、デフォルトの引数を使用して決定することはできません。

printこれは、インデックス リストを構築し、インデックス リストを受け入れるオーバーロードに転送する のオーバーロードを提供することで解決できます。

template <typename ...T>
void print(const std::tuple<T...> & tup) {
  print(tup,typename gens<sizeof...(T)>::type());
}
于 2012-05-25T07:30:06.480 に答える
1

より良い方法があるかもしれませんが、私が考えることができる最も簡単な方法は、余分なレベルの間接化を追加することでした:

#include <iostream>
#include <tuple>

template<int ...>
struct seq { };

template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };

template<int ...S>
struct gens<0, S...> {
  typedef seq<S...> type;
};

template <typename ...T, int ...S>
void print_impl(const std::tuple<T...> & tup, seq<S...>) {
  int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
  std::cout << std::endl;
}
// Pass args to real implementation here
template <typename ...T>
void print(const std::tuple<T...> & tup)
{
    print_impl(tup, typename gens<sizeof...(T)>::type());
}

int main() {
  std::tuple<double, int, char> tup(1.5, 100, 'c');
  print(tup);
  return 0;
}
于 2012-05-25T07:23:23.970 に答える