error on tuple copy ctor

View: New views
12 Messages — Rating Filter:   Alert me  

error on tuple copy ctor

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

As a heads up, while playing with the brand spanking new tuple
I ran into the error below. Looks like some of the ambiguities
we talked about are still there.

$     cat z.cpp \
   &&  make CPPOPTS=-D_RWSTD_EXT_CXX_0X CXXOPTS=-std=gnu++0x z
#include <tuple>

int main () {
     std::tuple<int> t;
     std::tuple<int> u (t);
}
gcc -c -I/home/sebor/stdcxx-4.3.x/include/ansi -D_RWSTDDEBUG   -pthread
-I/home/sebor/stdcxx-4.3.x/include
-I/build/sebor/stdcxx-4.3.x-gcc-4.3.0-15D/include
-I/home/sebor/stdcxx-4.3.x/examples/include -D_RWSTD_EXT_CXX_0X
-pedantic -nostdinc++ -g   -W -Wall -Wcast-qual -Winline -Wshadow
-Wwrite-strings -Wno-long-long -Wcast-align -std=gnu++0x  z.cpp
/home/sebor/stdcxx-4.3.x/include/rw/_tuple.h: In constructor
‘__rw::__rw_tuple<_HeadT, _TailT ...>::__rw_tuple(_HeadU&&, _TailU&&
...) [with _HeadU = std::tuple<int>&, _TailU = , _HeadT = int, _TailT = ]’:
/home/sebor/stdcxx-4.3.x/include/tuple:110:   instantiated from
‘std::tuple<_Types>::tuple(_TypesU&& ...) [with _TypesU =
std::tuple<int>&, _TypesT = int]’
z.cpp:5:   instantiated from here
/home/sebor/stdcxx-4.3.x/include/rw/_tuple.h:115: error: cannot convert
‘std::tuple<int>’ to ‘int’ in initialization
make: *** [z.o] Error 1


RE: error on tuple copy ctor

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 
Doh.  Hard to believe I missed something that common in the tests but
not unthinkable.  :P

Will add it to the list of changes to address previous comments.

Brad.

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Wednesday, July 02, 2008 12:32 PM
> To: dev@...
> Subject: error on tuple copy ctor
>
> As a heads up, while playing with the brand spanking new tuple
> I ran into the error below. Looks like some of the ambiguities
> we talked about are still there.
>
> $     cat z.cpp \
>    &&  make CPPOPTS=-D_RWSTD_EXT_CXX_0X CXXOPTS=-std=gnu++0x z
> #include <tuple>
>
> int main () {
>      std::tuple<int> t;
>      std::tuple<int> u (t);
> }
> gcc -c -I/home/sebor/stdcxx-4.3.x/include/ansi -D_RWSTDDEBUG  
>  -pthread
> -I/home/sebor/stdcxx-4.3.x/include
> -I/build/sebor/stdcxx-4.3.x-gcc-4.3.0-15D/include
> -I/home/sebor/stdcxx-4.3.x/examples/include -D_RWSTD_EXT_CXX_0X
> -pedantic -nostdinc++ -g   -W -Wall -Wcast-qual -Winline -Wshadow
> -Wwrite-strings -Wno-long-long -Wcast-align -std=gnu++0x  z.cpp
> /home/sebor/stdcxx-4.3.x/include/rw/_tuple.h: In constructor
> '__rw::__rw_tuple<_HeadT, _TailT ...>::__rw_tuple(_HeadU&&, _TailU&&
> ...) [with _HeadU = std::tuple<int>&, _TailU = , _HeadT =
> int, _TailT = ]':
> /home/sebor/stdcxx-4.3.x/include/tuple:110:   instantiated from
> 'std::tuple<_Types>::tuple(_TypesU&& ...) [with _TypesU =
> std::tuple<int>&, _TypesT = int]'
> z.cpp:5:   instantiated from here
> /home/sebor/stdcxx-4.3.x/include/rw/_tuple.h:115: error:
> cannot convert
> 'std::tuple<int>' to 'int' in initialization
> make: *** [z.o] Error 1
>
>

RE: error on tuple copy ctor

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 
Ohhh...now I remember.  That's the case that is not currently covered by
the standard.   The standard only specifies the following ctor:

        tuple (const tuple&);

It does not require this ctor:

        tuple (tuple&);

And because of the stricter type checking I mentioned earlier, a
`tuple<int>' value will not bind to a `const tuple<int>&' ctor (which I
really found surprising).

See the following thread from GNU libstdc++ for more info:

http://gcc.gnu.org/ml/libstdc++/2008-02/msg00047.html

Should we add the ctor even if the standard does not (currently) specify
it?

Brad.

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Wednesday, July 02, 2008 12:32 PM
> To: dev@...
> Subject: error on tuple copy ctor
>
> As a heads up, while playing with the brand spanking new tuple
> I ran into the error below. Looks like some of the ambiguities
> we talked about are still there.
>
> $     cat z.cpp \
>    &&  make CPPOPTS=-D_RWSTD_EXT_CXX_0X CXXOPTS=-std=gnu++0x z
> #include <tuple>
>
> int main () {
>      std::tuple<int> t;
>      std::tuple<int> u (t);
> }
> gcc -c -I/home/sebor/stdcxx-4.3.x/include/ansi -D_RWSTDDEBUG  
>  -pthread
> -I/home/sebor/stdcxx-4.3.x/include
> -I/build/sebor/stdcxx-4.3.x-gcc-4.3.0-15D/include
> -I/home/sebor/stdcxx-4.3.x/examples/include -D_RWSTD_EXT_CXX_0X
> -pedantic -nostdinc++ -g   -W -Wall -Wcast-qual -Winline -Wshadow
> -Wwrite-strings -Wno-long-long -Wcast-align -std=gnu++0x  z.cpp
> /home/sebor/stdcxx-4.3.x/include/rw/_tuple.h: In constructor
> '__rw::__rw_tuple<_HeadT, _TailT ...>::__rw_tuple(_HeadU&&, _TailU&&
> ...) [with _HeadU = std::tuple<int>&, _TailU = , _HeadT =
> int, _TailT = ]':
> /home/sebor/stdcxx-4.3.x/include/tuple:110:   instantiated from
> 'std::tuple<_Types>::tuple(_TypesU&& ...) [with _TypesU =
> std::tuple<int>&, _TypesT = int]'
> z.cpp:5:   instantiated from here
> /home/sebor/stdcxx-4.3.x/include/rw/_tuple.h:115: error:
> cannot convert
> 'std::tuple<int>' to 'int' in initialization
> make: *** [z.o] Error 1
>
>

Re: error on tuple copy ctor

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
> Ohhh...now I remember.  That's the case that is not currently covered by
> the standard.   The standard only specifies the following ctor:
>
> tuple (const tuple&);
>
> It does not require this ctor:
>
> tuple (tuple&);
>
> And because of the stricter type checking I mentioned earlier, a
> `tuple<int>' value will not bind to a `const tuple<int>&' ctor (which I
> really found surprising).

That would be a bug. One of const T& or T&& has to be a match
for all invocations of a copy ctor (for homogeneous types).

>
> See the following thread from GNU libstdc++ for more info:
>
> http://gcc.gnu.org/ml/libstdc++/2008-02/msg00047.html
>
> Should we add the ctor even if the standard does not (currently) specify
> it?

I don't think it's needed or desirable. In the test case I
posted, we want to call the const T& overload.

Martin

>
> Brad.
>
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
>> Sent: Wednesday, July 02, 2008 12:32 PM
>> To: dev@...
>> Subject: error on tuple copy ctor
>>
>> As a heads up, while playing with the brand spanking new tuple
>> I ran into the error below. Looks like some of the ambiguities
>> we talked about are still there.
>>
>> $     cat z.cpp \
>>    &&  make CPPOPTS=-D_RWSTD_EXT_CXX_0X CXXOPTS=-std=gnu++0x z
>> #include <tuple>
>>
>> int main () {
>>      std::tuple<int> t;
>>      std::tuple<int> u (t);
>> }
>> gcc -c -I/home/sebor/stdcxx-4.3.x/include/ansi -D_RWSTDDEBUG  
>>  -pthread
>> -I/home/sebor/stdcxx-4.3.x/include
>> -I/build/sebor/stdcxx-4.3.x-gcc-4.3.0-15D/include
>> -I/home/sebor/stdcxx-4.3.x/examples/include -D_RWSTD_EXT_CXX_0X
>> -pedantic -nostdinc++ -g   -W -Wall -Wcast-qual -Winline -Wshadow
>> -Wwrite-strings -Wno-long-long -Wcast-align -std=gnu++0x  z.cpp
>> /home/sebor/stdcxx-4.3.x/include/rw/_tuple.h: In constructor
>> '__rw::__rw_tuple<_HeadT, _TailT ...>::__rw_tuple(_HeadU&&, _TailU&&
>> ...) [with _HeadU = std::tuple<int>&, _TailU = , _HeadT =
>> int, _TailT = ]':
>> /home/sebor/stdcxx-4.3.x/include/tuple:110:   instantiated from
>> 'std::tuple<_Types>::tuple(_TypesU&& ...) [with _TypesU =
>> std::tuple<int>&, _TypesT = int]'
>> z.cpp:5:   instantiated from here
>> /home/sebor/stdcxx-4.3.x/include/rw/_tuple.h:115: error:
>> cannot convert
>> 'std::tuple<int>' to 'int' in initialization
>> make: *** [z.o] Error 1
>>
>>


RE: error on tuple copy ctor

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Wednesday, July 02, 2008 3:18 PM
> To: dev@...
> Subject: Re: error on tuple copy ctor
>
...
> >
> > Should we add the ctor even if the standard does not
> (currently) specify it?
>
> I don't think it's needed or desirable. In the test case I
> posted, we want to call the const T& overload.

That's the only workaround I can think of.  You have another one in
mind?

Brad.

Re: error on tuple copy ctor

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
>
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
>> Sent: Wednesday, July 02, 2008 3:18 PM
>> To: dev@...
>> Subject: Re: error on tuple copy ctor
>>
> ...
>>> Should we add the ctor even if the standard does not
>> (currently) specify it?
>>
>> I don't think it's needed or desirable. In the test case I
>> posted, we want to call the const T& overload.
>
> That's the only workaround I can think of.  You have another one in
> mind?

A workaround for what? This is a valid definition of
a CopyConstructible and MoveConstructible class (like tuple):

     struct S {
         S (const S&);
         S (S&&);
     };

I don't see why S would need another copy ctor with the signature
of S(S&). I realize tuple is quite a bit more complicated than S,
too complicated for me to understand why the ctor might be
necessary if, if fact, it really is. Could you show in a small
isolated example the problem that this ctor works around?

Martin

RE: error on tuple copy ctor

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Wednesday, July 02, 2008 3:55 PM
> To: dev@...
> Subject: Re: error on tuple copy ctor
>
> Eric Lemings wrote:
> >  
> >
> >> -----Original Message-----
> >> From: Martin Sebor [mailto:msebor@...] On Behalf Of
> Martin Sebor
> >> Sent: Wednesday, July 02, 2008 3:18 PM
> >> To: dev@...
> >> Subject: Re: error on tuple copy ctor
> >>
> > ...
> >>> Should we add the ctor even if the standard does not
> >> (currently) specify it?
> >>
> >> I don't think it's needed or desirable. In the test case I
> >> posted, we want to call the const T& overload.
> >
> > That's the only workaround I can think of.  You have another one in
> > mind?
>
> A workaround for what? This is a valid definition of
> a CopyConstructible and MoveConstructible class (like tuple):
>
>      struct S {
>          S (const S&);
>          S (S&&);
>      };
>
> I don't see why S would need another copy ctor with the signature
> of S(S&). I realize tuple is quite a bit more complicated than S,
> too complicated for me to understand why the ctor might be
> necessary if, if fact, it really is. Could you show in a small
> isolated example the problem that this ctor works around?

It would probably bind as expected if not for the template ctors in
tuple.  Apparently the compiler will prefer binding to a template ctor
any chance it gets because the constructed type and argument types are
"better", if not exact, matches in a template ctor.  Not so for trivial
copy ctors.

For binding to a `S (const S&)' ctor given an object value of S, there
is an implicit const conversion involved.

Here's a small test case to illustrate:

        #include <iostream>
        using namespace std;

        struct S {
            S () {}

            S (const S&) { cout << "trivial copy ctor called" << endl; }

            template <class T>
            S (T&&) { cout << "templated move ctor called" << endl; }
        };

        int main () {
            S s1;
            S s2 (s1); // trivial copy or templated move?
            return 0;
        }

Brad.

RE: error on tuple copy ctor

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Off list, the original tuple construction example, i.e.,

        #include <tuple>

        int main () {
             std::tuple<int> t;
             std::tuple<int> u (t);
        }

will not compile with the GNU libstdc++ tuple implementation either
without the additional `tuple (tuple&)' ctor.  That's the main reason I
suggested adding the additional ctor as a workaround.

        gcc-4.3.1/include/c++/4.3.1/tuple:
        ...
        227       tuple(const tuple& __in)
        228       : _Inherited(static_cast<const _Inherited&>(__in)) { }
        229
        230       tuple(tuple&& __in)
        231       : _Inherited(std::move<_Inherited>(__in)) { }
        ...
        242       // XXX
http://gcc.gnu.org/ml/libstdc++/2008-02/msg00047.html
        243       template<typename... _UElements>
        244         tuple(tuple<_UElements...>& __in)
        245         : _Inherited(static_cast<const _Tuple_impl<0,
_UElements...>&>(__in))
        246         { }

Brad.

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Wednesday, July 02, 2008 3:55 PM
> To: dev@...
> Subject: Re: error on tuple copy ctor
>
> Eric Lemings wrote:
> >  
> >
> >> -----Original Message-----
> >> From: Martin Sebor [mailto:msebor@...] On Behalf Of
> Martin Sebor
> >> Sent: Wednesday, July 02, 2008 3:18 PM
> >> To: dev@...
> >> Subject: Re: error on tuple copy ctor
> >>
> > ...
> >>> Should we add the ctor even if the standard does not
> >> (currently) specify it?
> >>
> >> I don't think it's needed or desirable. In the test case I
> >> posted, we want to call the const T& overload.
> >
> > That's the only workaround I can think of.  You have another one in
> > mind?
>
> A workaround for what? This is a valid definition of
> a CopyConstructible and MoveConstructible class (like tuple):
>
>      struct S {
>          S (const S&);
>          S (S&&);
>      };
>
> I don't see why S would need another copy ctor with the signature
> of S(S&). I realize tuple is quite a bit more complicated than S,
> too complicated for me to understand why the ctor might be
> necessary if, if fact, it really is. Could you show in a small
> isolated example the problem that this ctor works around?
>
> Martin
>

Re: error on tuple copy ctor

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
>
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
>> Sent: Wednesday, July 02, 2008 3:55 PM
>> To: dev@...
>> Subject: Re: error on tuple copy ctor
>>
>> Eric Lemings wrote:
>>>  
>>>
>>>> -----Original Message-----
>>>> From: Martin Sebor [mailto:msebor@...] On Behalf Of
>> Martin Sebor
>>>> Sent: Wednesday, July 02, 2008 3:18 PM
>>>> To: dev@...
>>>> Subject: Re: error on tuple copy ctor
>>>>
>>> ...
>>>>> Should we add the ctor even if the standard does not
>>>> (currently) specify it?
>>>>
>>>> I don't think it's needed or desirable. In the test case I
>>>> posted, we want to call the const T& overload.
>>> That's the only workaround I can think of.  You have another one in
>>> mind?
>> A workaround for what? This is a valid definition of
>> a CopyConstructible and MoveConstructible class (like tuple):
>>
>>      struct S {
>>          S (const S&);
>>          S (S&&);
>>      };
>>
>> I don't see why S would need another copy ctor with the signature
>> of S(S&). I realize tuple is quite a bit more complicated than S,
>> too complicated for me to understand why the ctor might be
>> necessary if, if fact, it really is. Could you show in a small
>> isolated example the problem that this ctor works around?
>
> It would probably bind as expected if not for the template ctors in
> tuple.  Apparently the compiler will prefer binding to a template ctor
> any chance it gets because the constructed type and argument types are
> "better", if not exact, matches in a template ctor.  Not so for trivial
> copy ctors.
>
> For binding to a `S (const S&)' ctor given an object value of S, there
> is an implicit const conversion involved.
>
> Here's a small test case to illustrate:

Thanks. I understand what's causing the error now. Unfortunately,
I'm not up enough on rvalue references to appreciate why or if
this is how they're supposed to work. Suppose we add a move ctor
to struct S. Which ctor would you expect to be called? gcc calls
the template with this signature:

     S::S(T&&) [with T = S&]

AFAICS, this is the same as S(S&&). Doesn't preferring a template
over an ordinary function with the same signature seem wrong? I
suppose it's time to dust off sections 13 and 14...

Martin

>
> #include <iostream>
> using namespace std;
>
> struct S {
>    S () {}
>
>    S (const S&) { cout << "trivial copy ctor called" << endl; }
>
>    template <class T>
>    S (T&&) { cout << "templated move ctor called" << endl; }
> };
>
> int main () {
>    S s1;
>    S s2 (s1); // trivial copy or templated move?
>    return 0;
> }
>
> Brad.


RE: error on tuple copy ctor

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Wednesday, July 02, 2008 5:17 PM
> To: dev@...
> Subject: Re: error on tuple copy ctor
>
> Eric Lemings wrote:
> >  
...
> AFAICS, this is the same as S(S&&). Doesn't preferring a template
> over an ordinary function with the same signature seem wrong?

Wrong, possibly.  Certainly not what one might expect.

Brad.

Re: error on tuple copy ctor

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
>
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
>> Sent: Wednesday, July 02, 2008 5:17 PM
>> To: dev@...
>> Subject: Re: error on tuple copy ctor
>>
>> Eric Lemings wrote:
>>>  
> ...
>> AFAICS, this is the same as S(S&&).

I was wrong. S::S(S&&&) is the same thing as S::S(S&). I.e., "an
rvalue reference to an lvalue reference" collapses into a plain
old (lvalue) reference.

> Doesn't preferring a template
>> over an ordinary function with the same signature seem wrong?
>
> Wrong, possibly.  Certainly not what one might expect.

I *think* I understand the rules now. Consider the example
in [temp.deduct.call], p3 of the latest WP (N2691):

    template <class T> void f (T&&);

    int i;
    int j = f (i);

Argument deduction instantiates "f<int&>(T&&&)" which after
collapsing the references is the same as f<int&>(T&). I.e.,
we end up calling a specialization of f for int&, which is
a better match than an overload (or specialization) of f for
int&&, since i is an lvalue and binding a (named) lvalue to
an rvalue (reference) involves an lvalue to rvalue conversion.
In fact, the generated specialization of f<int&> is an exact
match for i.

Martin

Re: error on tuple copy ctor

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
>
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
>> Sent: Wednesday, July 02, 2008 3:18 PM
>> To: dev@...
>> Subject: Re: error on tuple copy ctor
>>
> ...
>>> Should we add the ctor even if the standard does not
>> (currently) specify it?
>>
>> I don't think it's needed or desirable. In the test case I
>> posted, we want to call the const T& overload.
>
> That's the only workaround I can think of.  You have another one in
> mind?

Okay, now that we understand the rules and why a tuple lvalue
binds to the (variadic) template ctor instead of either the copy
or move ctor, I can't help but go back to one of first questions
I asked: if the non-const copy ctor is necessary, why doesn't
the spec mention it? Normally, when the spec leaves something
like this out it's either to allow different implementation
techniques, or it's an omission. In the first case, the
semantics tend to be described in terms of valid expressions.
In the second case it's up to us to fix it. I wonder which of
the two it is... Let me see if someone on c++std-lib can shed
some light on this.

Martin
LightInTheBox - Buy quality products at wholesale price