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, двоичные сгибы могут иметь следующие две формы:

Скриншот из cppreference / fold

куда 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';
}
Другие вопросы по тегам