The following code does not compile although I expect it to: /// BEGIN CODE /// #include <utility> struct S {}; struct C { S & mc2; S && mc3; C( S& b, S && c ) : mc2{b}, mc3{std::move(c)} {} }; int main() { return 0; } /// END CODE /// I compile it with command: g++ test.cpp -std=c++0x -o test.exe The output is: test.cpp: In constructor ‘C::C(S&, S&&)’: test.cpp:9:48: error: invalid initialization of non-const reference of type ‘S&’ from an rvalue of type ‘<brace-enclosed initializer list>’ test.cpp:9:48: error: invalid initialization of reference of type ‘S&&’ from expression of type ‘<brace-enclosed initializer list>’ Compiler version (g++ -v): Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-redhat-linux/4.6.0/lto-wrapper Target: i686-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux Thread model: posix gcc version 4.6.0 20110428 (Red Hat 4.6.0-6) (GCC)
G++ is actually correct according to wording in the C++11 FDIS (see 8.5.4 paragraphs 5 and 6), but we've reported it as an issue that needs to be fixed.
It's not just class members, it applies to list-initialization of any reference type: int i; int& ir{ i }; The FDIS requires a temporary to be created, and a non-const reference cannot bind to a temporary.
(In reply to comment #1) > G++ is actually correct according to wording in the C++11 FDIS (see 8.5.4 > paragraphs 5 and 6), but we've reported it as an issue that needs to be fixed. Are you sure about the paragraphs 5 and 6? (5 starts with "An object of type", 6 starts with "The lifetime of the array"?) They only say how std::initializer_list is created and how it behaves, but the 6th bullet of paragraph 3 (the one starting with "Otherwise, if the initializer list has a single element") does not require that std::initializer_list is created or used. It simply says that in code like: int i = 0; int & ri{i}; "ri" is initialized with "i". (And BTW, this example works on the same compiler.)
sorry, I meant bullets 5 and 6 in paragraph 3 the 5th bullet applies before the 6th one, and that says for a reference type a temporary is created. The 6th bullet is never reached for references. Your example with int& works because GCC doesn't implement the FDIS wording yet, according to the FDIS it should be rejected too, see http://gcc.gnu.org/ml/gcc-help/2011-07/msg00053.html this is a wording problem in the FDIS and will be core issue 1288 in the next issues list
Does anybody know the DR #? We could add it to the description and suspend.
The corresponding CWG issue is http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1288
Link changed now that it has been voted into the working paper: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1288 should it be un-suspended?
Yep, thanks, Marc.
Created attachment 28188 [details] Testcase for Bug "error: invalid initialization of non-const reference of type ‘std::istream&" Mysterious compiler error in line 35 of the attached testcase (test1.cpp); marked there as "BUG": test1.cpp:35:45: error: invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘void*’
Comment on attachment 28188 [details] Testcase for Bug "error: invalid initialization of non-const reference of type ‘std::istream&" (In reply to comment #9) > Created attachment 28188 [details] > Testcase for Bug "error: invalid initialization of non-const reference of type > ‘std::istream&" > > Mysterious compiler error in line 35 of the attached testcase (test1.cpp); > marked there as "BUG": > > test1.cpp:35:45: error: invalid initialization of non-const reference of type > ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘void*’ That's not mysterious, and is not related to this bug report. Your code can be reduced to: struct Base { operator void*() { return 0; } }; struct Derived1 : Base { }; struct Derived2 : Base { }; Derived1 d1; Derived2 d2; Base& b = true ? d1 : d2; The conditional expression cannot implicitly convert two objects of different types to a common base class, so instead the conversion operator is used to convert both types to void* To force the behaviour you expect use an explicit cast on one operand: istream& si = sfile.is_open() ? (std::istream&)sfile : sbuf;
*** Bug 56032 has been marked as a duplicate of this bug. ***
Jason, I'd like to try and fix this, but need some clues. A minimal example that fails to compile is: struct S { } s; S& r{s}; I find that in call.c:reference_binding we get compatible_p = false, which seems to be wrong. Even if compatible_p is true we don't take the branch that looks like it should be used: /* Directly bind reference when target expression's type is compatible with the reference and expression is an lvalue. In DR391, the wording in [8.5.3/5 dcl.init.ref] is changed to also require direct bindings for const and rvalue references to rvalues of compatible class type. We should also do direct bindings for non-class xvalues. */ if (compatible_p && (is_lvalue || (((CP_TYPE_CONST_NON_VOLATILE_P (to) && !(flags & LOOKUP_NO_RVAL_BIND)) || TYPE_REF_IS_RVALUE (rto)) && (gl_kind || (!(flags & LOOKUP_NO_TEMP_BIND) && (CLASS_TYPE_P (from) || TREE_CODE (from) == ARRAY_TYPE)))))) Naively I would expect compatible_p and is_lvalue to be true for the case above. Does the code earlier in the function need to be adjusted for the case where a braced-init-list has a single element of reference-compatible lvalue type?
*** Bug 58977 has been marked as a duplicate of this bug. ***
This bug seems to be fixed with the current trunk. Both the example in the original report and similar examples compile correctly, like std::string& f() {static std::string s; return s;} int main() { std::string& ri{f()}; } and int& f() {static int i = 42; return i;} int main() { int& ri{f()}; } Please close as resolved.
I agree. My examples are working. Unfortunately, my account seems to not have the permissions to close a bug. I am a maintainer. Any ideas how I can get such permissions set? Now if only I can remember what libstdc++ ctor I had to have one paren init amongst all the other brace inits that annoyed me enough to post this error! ;-)
Sorry for the noise. I reported a dupe not this bug. My question on permissions still stands though.
(In reply to Ed Smith-Rowland from comment #15) > Unfortunately, my account seems to not have the permissions to close a bug. > I am a maintainer. > > Any ideas how I can get such permissions set? You need to log in with an @gcc.gnu.org email address.
Created attachment 32240 [details] This is a test case for c++/50025. This just has simple classes with various reference member and verifies that using brace-initialization is accepted. I put it under g++.dg/cpp0x. Would anyone like more test cases? If this passes on x86_64-linux I think I'll close this with the test case patch. OK?
Sounds good.
Author: emsr Date: Sat Mar 1 22:51:25 2014 New Revision: 208251 URL: http://gcc.gnu.org/viewcvs?rev=208251&root=gcc&view=rev Log: 2014-03-01 Edward Smith-Rowland <3dw4rd@verizon.net> PR c++/50025 * g++.dg/cpp0x/pr50025.C: New. Added: trunk/gcc/testsuite/g++.dg/cpp0x/pr50025.C Modified: trunk/gcc/testsuite/ChangeLog
Fixed.
For the record, I think r207164 fixed this
Is it related bug? struct C { const std::string &st_ref; explicit C(const std::string &st) : st_ref{st} { std::cout << &st << ' ' << &st_ref << std::endl; assert(&st == &st_ref); } }; assert() fires! gcc 4.8.2 If we replace st_ref{st} with st_ref(st), assert() doesn't fire.
(In reply to __vic from comment #23) > Is it related bug? Yes, the original C++11 rules required a temporary to be created there and the reference member binds to that temporary (which then goes out of scope). Your code works correctly with GCC 4.9
*** Bug 60583 has been marked as a duplicate of this bug. ***