Pretty-print std :: tuple

Это продолжение моего предыдущего вопроса о красиво печатающих контейнерах STL , для которых нам удалось разработать очень элегантный и полностью общее решение.


На этом следующем шаге я хотел бы включить красивую печать для std :: tuple , используя вариативные шаблоны (так что это строго C ++ 11) . Для std :: pair я просто говорю

std::ostream & operator<<(std::ostream & o, const std::pair & p)
{
  return o << "(" << p.first << ", " << p.second << ")";
}

Какова аналогичная конструкция для печати кортежа?

Я пробовал различные биты распаковки стека аргументов шаблона, передавая индексы вокруг и с помощью SFINAE, чтобы обнаружить, когда я нахожусь на последнем элементе, но безуспешно. Я не буду обременять вас своим сломанным кодом; Описание проблемы, надеюсь, достаточно прямолинейно. По сути, мне бы хотелось следующего поведения:

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

Бонусные баллы за включение такого же уровня универсальности (char / wchar_t, разделители пар), что и в предыдущем вопросе!

78
задан Community 23 May 2017 в 12:02
поделиться

1 ответ

Усиление на std::apply (C++ 17) мы можем отбросить std::index_sequence и определить единственную функцию:

#include <tuple>
#include <iostream>

template<class Ch, class Tr, class... Args>
auto& operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t) {
  std::apply([&os](auto&&... args) {((os << args << " "), ...);}, t);
  return os;
}

Или, немного украшенный с помощью stringstream:

#include <tuple>
#include <iostream>
#include <sstream>

template<class Ch, class Tr, class... Args>
auto& operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t) {
  std::basic_stringstream<Ch, Tr> ss;
  ss << "[ ";
  std::apply([&ss](auto&&... args) {((ss << args << ", "), ...);}, t);
  ss.seekp(-2, ss.cur);
  ss << " ]";
  return os << ss.str();
}
0
ответ дан 24 November 2019 в 10:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: