ホームページ >バックエンド開発 >C++ >可変引数テンプレートを使用して C 11 で `std::tuple` をきれいに印刷する方法

可変引数テンプレートを使用して C 11 で `std::tuple` をきれいに印刷する方法

Barbara Streisand
Barbara Streisandオリジナル
2024-11-07 17:44:03826ブラウズ

How to Pretty-Print `std::tuple` in C  11 Using Variadic Templates?

きれいに印刷する std::tuple

この記事は、きれいに印刷する STL コンテナに関する以前の議論の続きであり、そこでは、このタスク。

問題ステートメント

この拡張機能では、特に C 11 向けに調整された、可変個引数テンプレートを使用した std::tuple オブジェクトの整形機能を含めることを目的としています。前述の std::pair の例からインスピレーションを得て、タプルにも同様の構造を求めます。望ましい動作は次のとおりです。

auto a = std::make_tuple(5, "Hello", -0.1);
std::cout << a << std::endl; // prints: (5, "Hello", -0.1)

さらに、さまざまな文字タイプやカスタマイズ可能なペア区切り文字のサポートなど、前の質問と同じレベルの汎用性を組み込むことを目指しています。

ソリューション

インデックスベースのアプローチを活用すると、次のコード スニペットを使用してソリューションを構築できます。

namespace aux{
template<std::size_t... Is> struct seq{};

template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};

template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>{};

template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple(std::basic_ostream<Ch,Tr>& os, Tuple const& t, seq<Is...>)
{
  using swallow = int[];
  (void)swallow{0, (void(
    os << (Is == 0? "" : ", ") << std::get<Is>(t)
  ), 0)...};
}
}

template<class Ch, class Tr, class... Args>
auto operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t)
    -> std::basic_ostream<Ch, Tr>&
{
  os << "(";
  aux::print_tuple(os, t, aux::gen_seq<sizeof...(Args)>()
);
  return os << ")";
}

区切り文字のカスタマイズについては、次の部分的なコードを追加できます。特殊化:

// Delimiters for tuple
template<class... Args>
struct delimiters<std::tuple<Args...>, char> {
  static const delimiters_values<char> values;
};

template<class... Args>
const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values =
    { "(", ", ", ")" };

template<class... Args>
struct delimiters<std::tuple<Args...>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template<class... Args>
const delimiters_values<wchar_t> delimiters<
    std::tuple<Args...>, wchar_t
>::values = { L"(", L", ", L")" };

これらの変更により、演算子<< print_tuple 関数は、区切り文字のカスタマイズを組み込むように更新できます:

template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple(std::basic_ostream<Ch, Tr>& os, Tuple const& t, seq<Is...>)
{
  using swallow = int[];
  char const* delim = delimiters<Tuple, Ch>::values.delimiter;
  if(!delim) delim = "";
  (void)swallow{0, (void(
    os << (Is == 0? "" : delim) << std::get<Is>(t)
  ), 0)...};
}
template<class Ch, class Tr, class... Args>
auto operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t)
    -> std::basic_ostream<Ch, Tr>&
{
  typedef std::tuple<Args...> tuple_t;
  if(delimiters<tuple_t, Ch>::values.prefix != 0)
    os << delimiters<tuple_t,char>::values.prefix;

  print_tuple(os, t, aux::gen_seq<sizeof...(Args)>()
);

  if(delimiters<tuple_t, Ch>::values.postfix != 0)
    os << delimiters<tuple_t,char>::values.postfix;

  return os;
}

以上が可変引数テンプレートを使用して C 11 で `std::tuple` をきれいに印刷する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。