[foreach] gcc 4.5 & 4.6 compiler error with BOOST_FOREACH(auto&& ...) loop

Hello, The following code fails to compile with gcc 4.5 or 4.6: #include <boost/foreach.hpp> template <typename> void f() { int A[6]; BOOST_FOREACH(auto&& x, A) ; } void g() { f<int>(); } The error is: test.cpp: In function 'void f() [with <template-parameter-1-1> = int]': test.cpp:14:12: instantiated from here test.cpp:6:5: error: invalid initialization of reference of type 'int&&' from expression of type 'int' Interestingly, the error goes away if I make f() a non-template function. It also compiles fine with gcc 4.4. The native range-based for version, however, compiles fine with gcc 4.6 (which is the only version to support it): #include <boost/foreach.hpp> template <typename> void f() { int A[6]; for(auto&& x : A) ; } void g() { f<int>(); } What is going on here? Is this a Boost issue or a gcc issue? Thanks, Nate.

On 05/03/2011 03:13, Nathan Ridge wrote:
The error is:
test.cpp: In function 'void f() [with<template-parameter-1-1> = int]': test.cpp:14:12: instantiated from here test.cpp:6:5: error: invalid initialization of reference of type 'int&&' from expression of type 'int'
Simply put, the value it is initialized with is an lvalue.
Interestingly, the error goes away if I make f() a non-template function. It also compiles fine with gcc 4.4.
GCC 4.4 allowed lvalues to bind to rvalue references, which is why.
The native range-based for version, however, compiles fine with gcc 4.6 (which is the only version to support it):
#include<boost/foreach.hpp>
template<typename> void f() { int A[6]; for(auto&& x : A) ; }
Why does this compile? I don't see how any rvalue can be available in that context.

On 05.03.2011, at 14:11, Mathias Gaunard wrote:
On 05/03/2011 03:13, Nathan Ridge wrote:
The native range-based for version, however, compiles fine with gcc 4.6 (which is the only version to support it):
#include<boost/foreach.hpp>
template<typename> void f() { int A[6]; for(auto&& x : A) ; }
Why does this compile? I don't see how any rvalue can be available in that context.
Wouldn't auto deduction make x an lvalue reference here? Sebastian

Sebastian Redl wrote:
template<typename> void f() { int A[6]; for(auto&& x : A) ; }
Why does this compile? I don't see how any rvalue can be available in that context.
Wouldn't auto deduction make x an lvalue reference here?
Yes, x should be an lvalue reference here. The code should compile fine. I think this is a gcc bug. In a function template, auto deduction fails to deduce an lvalue reference when auto&& is initiliazed by a function return value of an lvalue reference. Minimal test case: (This code fails to be compiled.) int& identity(int& i) { return i; } template <typename = void> // Commenting this out makes compilation succeed void f() { int i = 0; auto&& x = identity(i); // In a function template, auto deduction fails } int main (int argc, char* argv[]) { f(); return 0; } Regards, Michel

Michel MORIN wrote:
I think this is a gcc bug. In a function template, auto deduction fails to deduce an lvalue reference when auto&& is initiliazed by a function return value of an lvalue reference.
Minimal test case: (This code fails to be compiled.)
int& identity(int& i) { return i; }
template <typename = void> // Commenting this out makes compilation succeed void f() { int i = 0; auto&& x = identity(i); // In a function template, auto deduction fails }
int main (int argc, char* argv[]) { f(); return 0; }
This seems an unknown bug of gcc, so I reported this to GCC Bugzilla: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47999 Good thing you found this problem, Nate! Regards, Michel
participants (4)
-
Mathias Gaunard
-
Michel MORIN
-
Nathan Ridge
-
Sebastian Redl