Возможно, вам не нужен C ++ 17 (который еще не выпущен) для достижения нерекурсивного (на самом деле рекурсивного, но более естественного) решения. То есть вам не нужны выражения свертывания, вам нужны только последовательности индексов (C ++ 14) и пакеты параметров шаблона (C ++ 11).
#include <iostream>
#include <sstream>
#include <utility>
#include <tuple>
#include <string>
template<class T>
std::ostringstream& concat_to_stream(std::ostringstream &oss, T &&arg) {
oss << arg;
return oss;
}
template<class First, class ...Rest>
std::ostringstream& concat_to_stream(std::ostringstream &oss, First &&firstArg, Rest &&... restArgs) {
oss << firstArg << ", ";
return concat_to_stream(oss, std::forward<Rest &&>(restArgs)...);
}
template<class ...Types>
std::string concat_to_string(Types &&... args) {
std::ostringstream oss;
oss << '[';
concat_to_stream(oss, std::forward<Types &&>(args)...);
oss << ']';
return oss.str();
}
template<class Tuple, size_t... Indices>
std::string help_concat(const Tuple &tuple, std::index_sequence<Indices...>) {
return concat_to_string(std::get<Indices>(tuple)...);
};
template<class ...Types>
std::string tuple_to_string(const std::tuple<Types...> &tuple) {
return help_concat(tuple, std::make_index_sequence<sizeof...(Types)>{});
};
template<class ...Types>
std::ostream &operator<<(std::ostream &os, const std::tuple<Types...> &tuple) {
return os << tuple_to_string(tuple);
}
int main() {
std::tuple<int, double, std::string> sample_tuple = std::make_tuple(3, 1.723, "Hi!");
std::cout << sample_tuple << '\n'; // [3, 1.723, Hi!]
return 0;
}
Рекурсивная часть - это часть concat_to_stream
, которая довольно естественна и распространена. Ключевая часть - help_concat
, которую я изучаю из Реализация std :: tuple с нуля: часть 6, tuple_cat Take 1 .
Метод заключается в использовании фиктивной переменной std::index_sequence
в списке параметров для вывода size_t... Indices
в списке параметров шаблона, что позволяет нам "сгладить" содержимое std::tuple
в списке переменных параметров, который может быть принят с помощью функции concat_to_string
.