[Bug c++/63506] New: GCC deduces wrong return type of operator*() inside template functions

steffen.muething at iwr dot uni-heidelberg.de gcc-bugzilla@gcc.gnu.org
Fri Oct 10 14:02:00 GMT 2014


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

            Bug ID: 63506
           Summary: GCC deduces wrong return type of operator*() inside
                    template functions
           Product: gcc
           Version: 4.9.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: steffen.muething at iwr dot uni-heidelberg.de

Created attachment 33681
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33681&action=edit
Minimal working example based on std::vector<bool>

When trying to convert some iterators in our numerics library DUNE
(dune-project.org) to return temporaries instead of const refs, I stumbled over
the following bug in GCC 4.8.3 and 4.9.1:

Given a class with an operator*() that returns a temporary:

struct iterator
{
  ...

  proxy operator*() const
  {
    return ...;
  }

  proxy get() const
  {
    return ...;
  }

};

the expression 'decltype(*it())' should yield 'proxy', and a variable declared
with 'auto&& x = *it;' should be of type 'proxy&&'. The above is true inside
normal functions:

void bar(iterator it)
{
  typedef decltype(*it()) P; // P == proxy
  auto&& x = *it; // decltype(x) == proxy&&
}

But inside a function template, 'decltype(*it())' becomes 'proxy&', and 'auto&&
x = *it' fails with a compiler error:

template<typename T>
void foo(T t, iterator it)
{
  typedef decltype(*it()) P; // P == proxy&
  auto&& x = *it; // compiler error, see below
}

error: invalid initialization of non-const reference of type 'proxy&' from an
rvalue of type 'proxy'

For some reason, the compiler deduces the wrong type early on and then fails
when it later realizes the correct return type...

This problem can easily be observed with a std::vector<bool>, which returns a
proxy from its iterator. I have attached a minimal working example: The
contained code (which creates a vector and iterates over its contents with a
range-based for loop using auto&&) works in main() and in a normal function
bar(), but it fails to compile in foo(), which is a function template.

GCC 4.6 and 4.7 compile foo() correctly.



More information about the Gcc-bugs mailing list