http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48476
Summary: [C++0x] conversion between std::tuple which have reference member is rejected Product: gcc Version: 4.6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: gintensub...@gmail.com Created attachment 23893 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=23893 Proposed patch for libstdc++-v3/include/std/tuple.hpp gcc-4.6.0 rejects this code (bug.cc): --------------------- #include <tuple> int main() { int i = 0; std::tuple<int&, int> t = std::forward_as_tuple( i, 0 ); } --------------------- # g++ -std=c++0x bug.cc In file included from bug.cc:1:0: /usr/local/gcc46/lib/gcc/i686-pc-cygwin/4.6.0/../../../../include/c++/4.6.0/tuple: In constructor 'std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = int, unsigned int _Idx = 0u, _Head = int&]': /usr/local/gcc46/lib/gcc/i686-pc-cygwin/4.6.0/../../../../include/c++/4.6.0/tuple:183:35: instantiated from 'std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _UElements ...>&&) [with _UElements = {int&, int&&}, unsigned int _Idx = 0u, _Head = int&, _Tail = {int}]' /usr/local/gcc46/lib/gcc/i686-pc-cygwin/4.6.0/../../../../include/c++/4.6.0/tuple:343:60: instantiated from 'std::tuple<_T1, _T2>::tuple(std::tuple<_U1, _U2>&&) [with _U1 = int&, _U2 = int&&, _T1 = int&, _T2 = int]' bug.cc:6:57: instantiated from here /usr/local/gcc46/lib/gcc/i686-pc-cygwin/4.6.0/../../../../include/c++/4.6.0/tuple:101:42: error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int' --------------------- I found a conversion ctor of '_Tuple_impl<_Idx, _Head, _Tail...>', --------------------- // libstdc++-v3/include/std/tuple.hpp, line 180 template<typename... _UElements> _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in) : _Inherited(std::move(__in._M_tail())), _Base(std::move(__in._M_head())) { } --------------------- is wrong, when the first type of '_UElements...' is lvalue reference. It should be implemented with std::forward, not std::move, like this: --------------------- template<typename _UHead, typename... _UTails> _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) : _Inherited(std::move(__in._M_tail())), _Base(std::forward<_UHead>(__in._M_head())) { } --------------------- and it would be work better. And I found these kinds of bugs also appear in implementations of assignment-ops and std::tuple_cat, so I attach a brief patch to fix them ( it might have some problems, because I have not tested it enough ). I'm glad if it could be some help.