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

            Bug ID: 70942
           Summary: [c++14] Incorrect deduction of generic lambda `auto&&`
                    parameter
           Product: gcc
           Version: 6.1.0
            Status: UNCONFIRMED
          Severity: critical
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vittorio.romeo at outlook dot com
  Target Milestone: ---

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

g++ 6.1 was recently introduced into Arch Linux's testing repositories, and
some of my code that successfully compiled with g++ 5.3.0 does not compile
anymore. I've made a minimal example:

gcc.godbolt.org link: 
https://godbolt.org/g/73RTHf


    // This code compiles with g++ 5.3.0
    // This does not compile with g++ 6.1

    #include <type_traits>
    #include <utility>
    #include <tuple>

    #define FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)

    struct sinker
    {
        template <typename T>
        void sink(T&)
        {
        }
    };

    template <typename T, typename TF>
    void caller(T& v, TF&& f)
    {
        sinker s;
        f(s, v);
    }

    template <typename T>
    void interface(T& v)
    {
        return caller(v, [](auto& xs, auto&& xv) -> decltype(auto)
            {
                xs.sink(FWD(xv));
            });
    }

    int main()
    {
        int x = 0;
        interface(x);
    }

This is the reported error:

    : In instantiation of ‘get_impl(T&)::<lambda(auto:1&, auto:2&&)> [with
auto:1 = sinker; auto:2 = int; T = int]’:
    :25:58:   required by substitution of ‘template<class auto:1, class auto:2>
get_impl(T&)
          [with T = int]::<lambda(auto:1&, auto:2&&)>::operator 
          decltype (((get_impl(T&) [with T = int]::<lambda(auto:1&,
auto:2&&)>)0u).operator()(static_cast<auto:1&>(<anonymous>),
           static_cast<auto:2&&>(<anonymous>))) (*)(auto:1&, auto:2&&)() const
[with auto:1 = sinker; auto:2 = int]’
    :19:6:   required from ‘void chunk_fn_impl(T&, TF&&) [with T = int; TF =
get_impl(T&) [with T = int]::<lambda(auto:1&, auto:2&&)>]’
    :25:25:   required from ‘void get_impl(T&) [with T = int]’
    :36:15:   required from here
    :27:13: error: invalid initialization of non-const reference of type ‘int&’
from an rvalue of type ‘int’
                 xs.sink(FWD(md));
                 ^~
    :10:10: note:   initializing argument 1 of ‘void sinker::sink(T&) [with T =
int]’
         void sink(T&)
              ^~~~

---

Changing:

    return caller(v, [](auto& xs, auto&& xv) -> decltype(auto)

to:

    return caller(v, [](auto& xs, auto& xv) -> decltype(auto)

allows the code to successfully compile.

---

I do not understand why this error is happening, as `xv` is being
perfectly-forwarded and the `FWD(xv)` call should produce a lvalue reference.
Note that the code worked as intended in g++ 5.3.0 and clang++ 3.7.

gcc.godbolt.org link: 
https://godbolt.org/g/73RTHf

Try compiling with multiple g++ versions and changing `auto&&` to `auto&`.

Is this a g++ 6.1 bug? Or was the code incorrectly compiling with previous
versions of g++ and clang++?

---

More information:
http://stackoverflow.com/questions/37023265

Reply via email to