https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71332

            Bug ID: 71332
           Summary: Passing non-copyable type by reference to variadic
                    generic lambda after a copyable type by value results
                    in a compile-time error
           Product: gcc
           Version: 6.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vittorio.romeo at outlook dot com
  Target Milestone: ---

Created attachment 38592
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38592&action=edit
Minimal code example

* Example on gcc.godbolt.org:
https://godbolt.org/g/HxMq0K

* Related StackOverflow question:
http://stackoverflow.com/questions/37508217

---

I've encountered a situation where passing a non-copyable type (by reference)
to a variadic generic lambda after a copyable type (by copy) causes a
compilation error on `g++` (both on `5.3` and `6.1`) but not on `clang++`.

    int main()
    {
        auto f = [](auto&&...)
        {
        };

        non_copyable nc;

        f(nc); // ok on both compilers
        f(nc, int{}); // ok on both compilers
        f(int{}, nc); // error only on gcc 
    } 

`g++` gives the following error for the `f(int{}, nc)` call: 

    x.cpp: In function ‘void test()’:
    x.cpp:19:19: error: use of deleted function
‘non_copyable::non_copyable(const non_copyable&)’
         f(int{}, nc);
                    ^
    x.cpp:8:5: note: declared here
         non_copyable(const non_copyable&) = delete;
         ^~~~~~~~~~~~

It seems that if the first argument is passed by copy, all the other arguments
are passed by copy as well. This looks like a bug, because using an
hand-written callable object that should be equivalent to the lambda works on
both compilers:

    // should be equivalent to `[](auto&&...){ }`
    struct do_nothing
    {
        template <typename... Ts>
        constexpr auto operator()(Ts&&...) const noexcept
        {
        }
    };

    // ...

    do_nothing{}(nc); // ok on both compilers
    do_nothing{}(nc, int{}); // ok on both compilers
    do_nothing{}(int{}, nc); // ok on both compilers

There seems to be an inconsistency between callable objects and generic
variadic lambdas on `g++`.

Reply via email to