1

I'm reading "C++17 - The Complete Guide" book and I came across the example on page 107 and 108 regarding fold expression in C++17:

template<typename First, typename... Args>
void print(First first, const Args&... args)
{
    std::cout << first;
    auto outWithSpace = [](const auto& arg)
    {
        std::cout << " " << arg;
    };
    (..., outWithSpace(args));
    std::cout << "\n";
}

Is there any reason that the author couldn't do this as follows (without separating the first argument from the rest and apart from an extra printed space!):

template<typename... Types>
void print(Types const&... args)
{
    ([](const auto& x){ std::cout << x << " "; }(args), ...);
    std::cout << "\n";
}
Barry
  • 286,269
  • 29
  • 621
  • 977
Ali
  • 288
  • 3
  • 10

4 Answers4

4

As you have already figured out, the author could not have done as you suggest because that would leave an additional space…

What the author could have done though, would be something like

template<typename First, typename... Args>
void print(First first, const Args&... args)
{
    ((std::cout << first), ..., (std::cout << ' ' << args)) << '\n';
}

or, rather

template <typename Arg, typename... Args>
std::ostream& print(Arg&& arg, Args&&... args)
{
    return ((std::cout << std::forward<Arg>(arg)), ..., (std::cout << ' ' << std::forward<Args>(args))) << '\n';
}

live example here

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
0

Plainly the readable way to write this is

template<typename... Types>
void print(Types const&... args)
{
    std::size_t n = 0;
    (std::cout << " " + !n++ << args), ...);
    std::cout << '\n';
}

(with std::forward to taste). The temptation to do this sort of nonsense (which could use bool first if C++17 hadn’t killed that wonderful feature) is the motivation for the template for feature planned for C++23.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • @Barry i think he means arithmetic on `bool` – Richard Hodges Dec 17 '19 at 17:37
  • @RichardHodges: With tongue in cheek (like the answer), yes: for weird cases like this (and code golfing), post-increment (“has this been set already?”) and decrement (toggle) on `bool` were useful shorthands but far too obscure. – Davis Herring Dec 18 '19 at 02:07
0

Since we're having fun times with friends

template<typename First, typename... Args>`
void print(First&& first, Args&&... args)
{
    auto emit = [](auto&&...x) { ((std::cout << x), ...); };

    (emit(first), ..., emit(' ', args)), emit('\n');
}

:)

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
-1

No, it's just a question of aesthetics. No more reason.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35