Это продолжение моего предыдущего вопроса о красиво печатающих контейнерах 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, разделители пар), что и в предыдущем вопросе!
Усиление на 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();
}