В C ++ 17 мы можем сделать это с немного меньшим количеством кода, используя выражения сгиба , особенно унарный левый сгиб:
template<class TupType, size_t... I>
void print(const TupType& _tup, std::index_sequence<I...>)
{
std::cout << "(";
(..., (std::cout << (I == 0? "" : ", ") << std::get<I>(_tup)));
std::cout << ")\n";
}
template<class... T>
void print (const std::tuple<T...>& _tup)
{
print(_tup, std::make_index_sequence<sizeof...(T)>());
}
Live Demo выходы:
(5, Привет, -0,1)
данный
auto a = std::make_tuple(5, "Hello", -0.1);
print(a);
Объяснение
Наша одинарная левая складка имеет форму
... op pack
, где op
в нашем сценарии - оператор запятой, а pack
- выражение, содержащее наш кортеж в нерасширенном контексте, например:
(..., (std::cout << std::get<I>(myTuple))
Итак, если у меня есть такой кортеж:
auto myTuple = std::make_tuple(5, "Hello", -0.1);
И std::integer_sequence
, значения которых указаны нетиповым шаблоном (см. Код выше)
size_t... I
Тогда выражение
(..., (std::cout << std::get<I>(myTuple))
Расширяется до
((std::cout << std::get<0>(myTuple)), (std::cout << std::get<1>(myTuple))), (std::cout << std::get<2>(myTuple));
Который напечатает
5Hello-0,1 * * одна тысяча сорок шесть
Это брутто, поэтому нам нужно сделать еще несколько хитростей, чтобы добавить разделитель запятых для печати первым, если это не первый элемент.
Для этого мы модифицируем часть pack
выражения сгиба, чтобы вывести " ,"
, если текущий индекс I
не первый, следовательно, часть (I == 0? "" : ", ")
*:
(..., (std::cout << (I == 0? "" : ", ") << std::get<I>(_tup)));
А теперь мы получим
5, Привет, -0,1
Что выглядит лучше (Примечание: я хотел получить такой же вывод, как этот ответ )
* Примечание. Вы можете разделять запятыми разными способами, чем я в конечном итоге. Я изначально добавил запятые условно после вместо до , протестировав против std::tuple_size<TupType>::value - 1
, но это было слишком долго, поэтому я проверил вместо sizeof...(I) - 1
, но в итоге я скопировал Xeo и мы получили то, что у меня есть.