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: [email protected]
ReportedBy: [email protected]
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.