f



What is a difference in 'T t = u' and in 'T t( u )'

Hi,

Does anyone can explain me why declarations marked as 1 compile
whereas declarations marked as 2 do not compile?
The most obvious example is the third one with shared_ptr. It is
because of explicite constructor. Am I right?
But what about first and second examples?

Please notice also that examples second and third are completely
different. Constructor calling syntax is right in third but not in
second. However assign syntax is right in second example but not in
third.

#include <boost/assign/list_of.hpp>
#include <boost/shared_ptr.hpp>

#include <iostream>
#include <vector>

struct S{
    S(){}
    S( int * ){
        std::cout<<"S::S(int *)"<<std::endl;
    }
};

struct U{
    template< typename T >
    operator T * (){
        std::cout<<"U::operator T*()"<<std::endl;
        return static_cast< T * >( 0 );
    }
};

int main(){
    {// 1
        U u;

        S s1( u );
        //S s2 = u;
    }

    {// 2
        std::vector< int > array1 = boost::assign::list_of( 2 );
        //std::vector< int > array2( boost::assign::list_of( 3 ) );
    }

    {// 3
        boost::shared_ptr< int > p1( new int( 3 ) );
        //boost::shared_ptr< int > p2 = new int( 3 );
    }
}


Regards,
Lukasz

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
wo3kie
7/14/2009 3:03:14 PM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8509) is leader. Post Follow

8 Replies
1564 Views

Similar Articles

[PageSpeed] 45

wo3kie wrote:
> Hi,
> 
> Does anyone can explain me why declarations marked as 1 compile
> whereas declarations marked as 2 do not compile?
> The most obvious example is the third one with shared_ptr. It is
> because of explicite constructor. Am I right?
> But what about first and second examples?
> 

The issue just came up recently on this group:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/e9b4e24825d19c15/9e48b88aadcaaebe

Bottom line for me was:
U u;
T t(u);  // Will call the constructor of T that takes an U.
T t = u; // Behaves *as if* a temporary of T(u) was constructed and then
assigned to t. The compiler is allowed to elide the copy constructor if
it decides the outcome is the same.

That's how my understanding of the issue is at the moment.

br,
Martin

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Martin
7/15/2009 5:42:45 AM
> struct S{
>     S(){}
>     S( int * ){
>         std::cout<<"S::S(int *)"<<std::endl;
>     }
>
> };
>
> struct U{
>     template< typename T >
>     operator T * (){
>         std::cout<<"U::operator T*()"<<std::endl;
>         return static_cast< T * >( 0 );
>     }
> };
>
>         U u;
>
>         S s1( u );
>         //S s2 = u;

Hi,
In the current standard (2003) there is the section 8.5:14 (8.5:16 in
the latest draft for C++0x) that I think handles your cases 1 and 2.
Basically different look-up rules apply for "S s1(u)" and "S s2 = u"
syntax. The former only considers converting constructors of S,
whereas the latter also includes conversion operators. That is, if I
read the standard correctly.

Regards,
&rzej


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
restor
7/15/2009 8:46:24 AM
Martin T. wrote:
> 
> Bottom line for me was:
> U u;
> T t(u);  // Will call the constructor of T that takes an U.
> T t = u; // Behaves *as if* a temporary of T(u) was constructed and then
> assigned to t. The compiler is allowed to elide the copy constructor if
> it decides the outcome is the same.

The temporary is not assigned, but copy constructed (from).
Those two are different things.

> 
> That's how my understanding of the issue is at the moment.

-- 
Seungbeom Kim

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Seungbeom
7/15/2009 8:48:46 AM
On Jul 15, 1:03 am, wo3kie <wo3...@gmail.com> wrote:
> Hi,
>
> Does anyone can explain me why declarations marked as 1 compile
> whereas declarations marked as 2 do not compile?
> The most obvious example is the third one with shared_ptr. It is
> because of explicite constructor. Am I right?
> But what about first and second examples?
>
> Please notice also that examples second and third are completely
> different. Constructor calling syntax is right in third but not in
> second. However assign syntax is right in second example but not in
> third.
>
> #include <boost/assign/list_of.hpp>
> #include <boost/shared_ptr.hpp>
>
> #include <iostream>
> #include <vector>
>
> struct S{
>     S(){}
>     S( int * ){
>         std::cout<<"S::S(int *)"<<std::endl;
>     }
>
> };
>
> struct U{
>     template< typename T >
>     operator T * (){
>         std::cout<<"U::operator T*()"<<std::endl;
>         return static_cast< T * >( 0 );
>     }
>
> };
>
> int main(){
>     {// 1
>         U u;
>
>         S s1( u );
>         //S s2 = u;
>     }
>
>     {// 2
>         std::vector< int > array1 = boost::assign::list_of( 2 );
>         //std::vector< int > array2( boost::assign::list_of( 3 ) );
>     }
>
>     {// 3
>         boost::shared_ptr< int > p1( new int( 3 ) );
>         //boost::shared_ptr< int > p2 = new int( 3 );
>     }
>
> }
>

try this:

class A{
    A(){};
    explicit A(const a&){};/*TAKE A CAREFULL LOOK AT THIS LINE*/
};

class B{
    B();
    B(const b&);
};


void main(){

    B b1;
    B b2=b1;//ok : implicit copy
    B b3(b2);//ok: explicit copy

    A a1;
    A a2(a1);//ok: explicit copy
    A a3=a2;//ERROR: implicit copy prevented.

};

regards,
FM.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
terminator
7/15/2009 1:50:37 PM
On Jul 15, 3:42 pm, "Martin T." <0xCDCDC...@gmx.at> wrote:
> wo3kie wrote:
> > Hi,
>
> > Does anyone can explain me why declarations marked as 1 compile
> > whereas declarations marked as 2 do not compile?
> > The most obvious example is the third one with shared_ptr. It is
> > because of explicite constructor. Am I right?
> > But what about first and second examples?
>
> The issue just came up recently on this group:http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thr...
>
> Bottom line for me was:
> U u;
> T t(u);  // Will call the constructor of T that takes an U.
> T t = u; // Behaves *as if* a temporary of T(u) was constructed and then
> assigned to t.

No.

Both call the copy-ctor.
***But,**** the latter is allowed only on none-explicit ctors.

regards,
FM.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
terminator
7/15/2009 1:51:20 PM
On Jul 15, 6:48 pm, Seungbeom Kim <musip...@bawi.org> wrote:
> Martin T. wrote:
>
> > Bottom line for me was:
> > U u;
> > T t(u);  // Will call the constructor of T that takes an U.
> > T t = u; // Behaves *as if* a temporary of T(u) was constructed and then
> > assigned to t. The compiler is allowed to elide the copy constructor if
> > it decides the outcome is the same.
>
> The temporary is not assigned, but copy constructed (from).
> Those two are different things.
>
>
>
> > That's how my understanding of the issue is at the moment.
>

That is another story.
what you wrote is about function call value parameters:

void f(A a);

g(){
    A aa
    f(aa);//compiler decides :1 or 2 copies.
};

constructors usually use reference arguments.For a copy ctor this is
not an option ; It is a *** must****:

A::A(B& b){};//usually
A::A(A& a){};//***always***


where no copy happens.

regards,
FM.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
terminator
7/15/2009 1:52:05 PM
> Basically different look-up rules apply for "S s1(u)" and "S s2 = u"
> syntax. The former only considers converting constructors of S,
> whereas the latter also includes conversion operators.

You're telling right.

S s1( u );

In this case only converting constructor of S will be called.

S s2 = u;

In this case converting constructor expect s2 must be initialized by S
type of object and hence compilation error.

To remove compilation error we need to used conversion operator:

S s2 = static_cast<S2>(u);

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Vicky
7/16/2009 12:54:26 AM
Seungbeom Kim wrote:
> Martin T. wrote:
>>
>> Bottom line for me was:
>> U u;
>> T t(u);  // Will call the constructor of T that takes an U.
>> T t = u; // Behaves *as if* a temporary of T(u) was constructed and then
>> assigned to t. The compiler is allowed to elide the copy constructor if
>> it decides the outcome is the same.
> 
> The temporary is not assigned, but copy constructed (from).
> Those two are different things.
> 

Ah yes of course. Let me rephrase:
T t = u; // Behaves *as if* a temporary of T(u) was constructed and then
the copy-ctor of T(const T&) called.
i.e.
U u;
T t = u; <===> T t( T(u) ); ... but the compiler is allowed to ellide
the copy-ctor *if* it is accessible.

cheers,
Martin

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Martin
7/16/2009 10:18:55 AM
Reply: