[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