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.

Reply via email to