|
Boost : |
Subject: Re: [boost] Metaprogramming: parameter pack expansion/evaluation trick
From: Tim Song (t.canens.cpp_at_[hidden])
Date: 2015-07-03 03:35:22
C++1z will have fold expressions for this:
(std::cout << a << '\n', ...);
Add optional (void) cast for the paranoid.
Also, your implementation doesn't work if the type of the expression is
`void`, as far as I can see.
On Fri, Jul 3, 2015 at 2:16 AM, Antony Polukhin <antoshkka_at_[hidden]> wrote:
> Hi,
>
> Straight to the problem. Consider the situation, were a function accepts
> parameter pack and something need to be done with each argument (for
> example, we want to print each argument on a new line):
>
> template <typename... Args>
> void print(Args&&... a) {
> // print each a on a separate line
> }
>
> There's a known trick to do that:
>
> template <typename... Args>
> void print(Args&&... a) {
> (void) (int []){
> 0, (std::cout << a << std::endl, 0)...
> };
> }
>
> But the syntax is not very readable (and I always forget it and search for
> an example in Internet). I've tried to improve the syntax, and here's the
> result:
>
> template<typename... Args>
> void print(Args&&... a) {
> expand_if<Args...> {
> std::cout << a << '\n'...
> };
> }
>
>
> Compete source could be found here:
> http://coliru.stacked-crooked.com/view?id=c2c59f22574671e5
>
> Here's some more usage examples:
>
> template<typename... Args>
> void printer_int(Args&&... args) {
> expand {
> std::cout << std::abs(args) << std::endl...,
> std::cout << "Printing once again all the numbers: " << std::endl,
> std::cout << " Once again " << std::abs(args) << std::endl...,
> std::cout << "EOF Printing once again all the numbers." <<
> std::endl
> };
> }
>
> template<typename... Args>
> float sum(Args&&... args) {
> float res = 0;
> expand_if<Args...> {
> res += args...
> };
>
> return res;
> }
>
>
> I hope this would be helpful for someone or it could be used as an argument
> for a proposal to extend C++ and allow simpler syntax:
>
> template<typename... Args>
> void print(Args&&... a) {
> std::cout << a << '\n'...;
> }
>
>
>
> P.S.: There was a nicer solution that newer required "_if<Args..>" :
>
> namespace detail {
> struct expand_impl final {
> template <class... Arg>
> constexpr inline
> expand_impl(Arg&&...) noexcept
> {}
> };
> }
>
> template <class... Arg>
> using expand = detail::expand_impl;
>
> But unfortunately there's no way to force the compiler to evaluate
> expressions in constructor call from left to right. So it did not work on
> GCC (but work on Clang).
>
> --
> Best regards,
> Antony Polukhin
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk