C++17 кратное выражение в cout
Я изучаю новое C++17-кратное выражение и увидел этот код из C++17-кратного выражения. Я хотел бы знать, почему этот код работает:
template<typename ...Args>
void printer(Args&&... args) {
(std::cout << ... << args) << '\n';
}
но не этот
template<typename ...Args>
void printer(Args&&... args) {
(std::cout << args << ...) << '\n';
}
что может показаться логичным, и, на мой взгляд, поменять порядок печати.
2 ответа
Решение
Как видно на cppreference, двоичные сгибы могут иметь следующие две формы:
куда E
это выражение пакета и I
это выражение инициализации.
Там нет бинарной складки, которая соответствует вашему (std::cout << args << ...)
, который имеет форму (I op E op ...)
,
Двоичная складка прекрасно работает с<<
оператор. Попробуйте это:
#include <iostream>
#include <string>
#include <sstream>
#include <tuple>
#include <utility>
// g++ -c -std=c++17 fold_cout.cpp
// g++ -std=c++17 fold_cout.cpp -o fldcout.exe
template<typename ...Ts,
std::size_t... I>
void print(std::tuple<Ts...> const &tpl, std::index_sequence<I...>) // tag dispatching
{
auto formatter = [](auto const& elem) {
std::stringstream ss;
ss << elem << ',';
return ss.str();
};
std::cout<<'(';
///((std::cout<<std::get<I>(tpl)<<','), ...); // fold on comma op; okay
///(std::cout<<...<<(std::get<I>(tpl))); // fold on `<<` op;
// okay, but separator is problematic
// (needs special formatter lambda)
(std::cout<<...<<formatter(std::get<I>(tpl)));
std::cout<<")\n";
}
template<typename ...Ts>
void print(std::tuple<Ts...> const& tpl)
{
print(tpl, std::make_index_sequence< sizeof...(Ts) >{});
}
int main(void)
{
std::tuple t{ 13, 17, 3.14, std::string{"Hello"} };
print(t);
std::cout << "Done!\n";
return 0;
}
Вы также можете получить желаемый эффект, сложив оператор запятую,
:
template<typename ...Args>
void foo(Args&&...ts)
{
std::cout<<"T list: ";
((std::cout<<std::forward<Args>(ts)<<','),...);
std::cout<<'\n';
}