Topic: Q: is A a = 100; equivalent to A a (100); ?


Author: damian@molly.cs.monash.edu.au (Damian Conway)
Date: 1995/10/18
Raw View
kanze <kanze@lts.sel.alcatel.de> writes:

>In article <45sl3a$coc@engnews2.Eng.Sun.COM> clamage@Eng.sun.com
>(Steve Clamage) writes:

>|> damian@molly.cs.monash.edu.au (Damian Conway) writes:

>|> >Then is it possible to set up a class X wherein:

>|> > X x(1);
>|> >and
>|> > X x = 1;

>|> >behave differently?

>|> Yes.  Silly example: Write a message to the terminal from the copy
>|> constructor. If the copy is optimized away, you won't see the message.

>I don't think that is what he was looking for.  As far as I know,
>there is no way of *ensuring* that the above will both be legal, but
>have garanteed different run-time semantics.

Yes, that was what I was asking.

>It is trival to make the first legal, and the second illegal, which, I
>suppose is a way of making them behave differently at compile time.

:-)

BTW: What was the rationale for making something as fundamental as copy
     initialization non-portable (in the sense that it has no guaranteed
     semantics)?


damian

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~
  who: Damian Conway                 email: damian@bruce.cs.monash.edu.au
where: Dept. Computer Science        phone: +61-3-565-5184
       Monash University               fax: +61-3-565-5146
       Clayton 3168                  quote: "A pessimist is never disappointed.
"
       AUSTRALIA
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: b91926@fsgm01.fnal.gov (David Sachs)
Date: 1995/10/18
Raw View
damian@molly.cs.monash.edu.au (Damian Conway) writes:

>kanze <kanze@lts.sel.alcatel.de> writes:

>>In article <45sl3a$coc@engnews2.Eng.Sun.COM> clamage@Eng.sun.com
>>(Steve Clamage) writes:

>>|> damian@molly.cs.monash.edu.au (Damian Conway) writes:

>>|> >Then is it possible to set up a class X wherein:

>>|> > X x(1);
>>|> >and
>>|> > X x = 1;

>>|> >behave differently?

>>|> Yes.  Silly example: Write a message to the terminal from the copy
>>|> constructor. If the copy is optimized away, you won't see the message.

>>I don't think that is what he was looking for.  As far as I know,
>>there is no way of *ensuring* that the above will both be legal, but
>>have garanteed different run-time semantics.

>Yes, that was what I was asking.

>>It is trival to make the first legal, and the second illegal, which, I
>>suppose is a way of making them behave differently at compile time.

>:-)

>BTW: What was the rationale for making something as fundamental as copy
>     initialization non-portable (in the sense that it has no guaranteed
>     semantics)?


While it is not easy to write an example in which

X x(1); and X x = 1;  are guaranteed to behave differently, it is quite
easy to produce a case in which X x(a); and X x=a; behave differently,
where a is a class object, of a class that has a conversion operator to
X&, and another higher priority conversion to something accepted by a
constructor of class X. then:

X x(a) uses higher priority conversion by overloading rules

X x=a uses X(a.operator X&)

At least this is the way I think it works.
--
** The Klingons' favorite food was named by the first earthling to see it **
David Sachs - Fermilab, HPPC MS369 - P. O. Box 500 - Batavia, IL 60510
Voice: 1 708 840 3942      Deparment Fax: 1 708 840 3785


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: matt@godzilla.EECS.Berkeley.EDU (Matt Austern)
Date: 1995/10/18
Raw View
In article <4638jp$ef4@fsgm01.fnal.gov> b91926@fsgm01.fnal.gov (David Sachs) writes:

> X x(a) uses higher priority conversion by overloading rules
>
> X x=a uses X(a.operator X&)

Sort of.  If a is of class A, if the copy constructor X::X(const X&)
exists, and if the converting constructor X::X(const A&) exists and
isn't qualified as explicit, then "X x(a)" simply invokes the
converting constructor while "X x=a" invokes the converting
constructor and then the copy constructor.

Section 12.6 of the working paper explains this in detail.  The rest
of chapter 12 is somewhat relevant too.
--
  Matt Austern                             He showed his lower teeth.  "We
  matt@physics.berkeley.edu                all have flaws," he said, "and
  http://dogbert.lbl.gov/~matt             mine is being wicked."

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: b91926@fsgm01.fnal.gov (David Sachs)
Date: 1995/10/19
Raw View
matt@godzilla.EECS.Berkeley.EDU (Matt Austern) writes:

>In article <4638jp$ef4@fsgm01.fnal.gov> b91926@fsgm01.fnal.gov (David Sachs) w
rites:

>> X x(a) uses higher priority conversion by overloading rules
>>
>> X x=a uses X(a.operator X&)

>Sort of.  If a is of class A, if the copy constructor X::X(const X&)
>exists, and if the converting constructor X::X(const A&) exists and
>isn't qualified as explicit, then "X x(a)" simply invokes the
>converting constructor while "X x=a" invokes the converting
>constructor and then the copy constructor.

>Section 12.6 of the working paper explains this in detail.  The rest
>of chapter 12 is somewhat relevant too.

If X had a constructor X(A&), there might be some ambiguity, but
suppose X has a constructor X(B&), where B is a unique base class of
A.

Then X x(a); means X X(B&(a)); as trying X(a.operator X&()) would use
a lower priority user conversion.

X x = a; should use the direct conversion function.
--
** The Klingons' favorite food was named by the first earthling to see it **
David Sachs - Fermilab, HPPC MS369 - P. O. Box 500 - Batavia, IL 60510
Voice: 1 708 840 3942      Deparment Fax: 1 708 840 3785
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Michael Cook <mcook@cognex.com>
Date: 1995/10/19
Raw View
>>>>> "SC" == Steve Clamage <clamage@Eng.sun.com> writes:

 SC> Silly example: Write a message to the terminal from the copy
 SC> constructor. If the copy is optimized away, you won't see the message.

If the constructor writes a message to the terminal, then the contructor has
side effects.  Such a constructor could not be optimized away and still
conform to the (drafts) standard, right?

By adding "write" statements to your constructor, you affect the system you're
trying to observe, and then the laws of quantum mechanics kick in and cause
your progam to start emitting bogon particles. :-)

Michael.
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/10/19
Raw View
Matt Austern (matt@godzilla.EECS.Berkeley.EDU) wrote:

|> In article <4638jp$ef4@fsgm01.fnal.gov> b91926@fsgm01.fnal.gov (David Sachs) writes:

|> > X x(a) uses higher priority conversion by overloading rules
|> >
|> > X x=a uses X(a.operator X&)

|> Sort of.  If a is of class A, if the copy constructor X::X(const X&)
|> exists, and if the converting constructor X::X(const A&) exists and
|> isn't qualified as explicit, then "X x(a)" simply invokes the
|> converting constructor while "X x=a" invokes the converting
|> constructor and then the copy constructor.

Except that there is no guarantee that the copy constructor will
actually be invoked.  The compiler is allowed to optimize it away.

|> Section 12.6 of the working paper explains this in detail.  The rest
|> of chapter 12 is somewhat relevant too.

Concerning the original posting: I don't think it will work.  As I
understand what you are suggesting:

    class B {} ;
    class D : public B { operator B() ; } ;

    D               aD ;
    B               aB( aD ) ;
    B               anotherB = aD ;

What you are saying is that in the first case, D::operator B() will not
be considered, and in the second case, it will be used.

In fact, in both cases, it will be considered, but as a user defined
conversion, it is pretty far down on the scale; in both cases, the
derived->base conversion will have precedence.  (I believe.)
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: b91926@fsgm01.fnal.gov (David Sachs)
Date: 1995/10/19
Raw View
kanze@gabi-soft.fr (J. Kanze) writes:


>Matt Austern (matt@godzilla.EECS.Berkeley.EDU) wrote:

>|> In article <4638jp$ef4@fsgm01.fnal.gov> b91926@fsgm01.fnal.gov (David Sachs) writes:

>|> > X x(a) uses higher priority conversion by overloading rules
>|> >
>|> > X x=a uses X(a.operator X&)

>|> Sort of.  If a is of class A, if the copy constructor X::X(const X&)
>|> exists, and if the converting constructor X::X(const A&) exists and
>|> isn't qualified as explicit, then "X x(a)" simply invokes the
>|> converting constructor while "X x=a" invokes the converting
>|> constructor and then the copy constructor.

>Except that there is no guarantee that the copy constructor will
>actually be invoked.  The compiler is allowed to optimize it away.

>|> Section 12.6 of the working paper explains this in detail.  The rest
>|> of chapter 12 is somewhat relevant too.

>Concerning the original posting: I don't think it will work.  As I
>understand what you are suggesting:

>    class B {} ;
>    class D : public B { operator B() ; } ;

>    D               aD ;
>    B               aB( aD ) ;
>    B               anotherB = aD ;

>What you are saying is that in the first case, D::operator B() will not
>be considered, and in the second case, it will be used.

>In fact, in both cases, it will be considered, but as a user defined
>conversion, it is pretty far down on the scale; in both cases, the
>derived->base conversion will have precedence.  (I believe.)
>  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]

I am relying on paragraph 2 of scetion 12.3.2 of the proposed standard,
which appears to specify that a conversion function will be used in
certain cases. Possibly, the draft standard is ambiguous in this area.
--
** The Klingons' favorite food was named by the first earthling to see it **
David Sachs - Fermilab, HPPC MS369 - P. O. Box 500 - Batavia, IL 60510
Voice: 1 708 840 3942      Deparment Fax: 1 708 840 3785


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: damian@molly.cs.monash.edu.au (Damian Conway)
Date: 1995/10/19
Raw View
Various people explore various copy initialization scenarios and the rationale
for allowing optimization back to direct construction:

 [deleted]

I still haven't seen a convincing explanation (pace Steve) as to why the WP
differentiates so clearly between direct and copy initialization semantics
when the real situation is (or appears to be) that direct initialization
_may_ be used in all cases, at the discretion of the compiler.

Sure, leaving the compiler the freedom to optimize out unneeded temporaries
is probably a Good Thing, even at the expense of predictability, but why
not simply word the description to reflect the fact that, when using _either_
the "()" or the "=" form of initialization, temporaries of various types
_may_ be generated (with the constraint that the direct initialization form
will not generate temporaries of the type being initialized)?

damian
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~
  who: Damian Conway                 email: damian@bruce.cs.monash.edu.au
where: Dept. Computer Science        phone: +61-3-565-5184
       Monash University               fax: +61-3-565-5146
       Clayton 3168                  quote: "A pessimist is never disappointed.
"
       AUSTRALIA
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: martelli@cadlab.cadlab.it (Alex Martelli)
Date: 1995/10/20
Raw View
b91926@fsgm01.fnal.gov (David Sachs) writes:
 ...
>easy to produce a case in which X x(a); and X x=a; behave differently,
>where a is a class object, of a class that has a conversion operator to
>X&, and another higher priority conversion to something accepted by a
>constructor of class X. then:
>X x(a) uses higher priority conversion by overloading rules
>X x=a uses X(a.operator X&)

I think I'm confused here -- what would be a "higher priority conversion"
from a class object a to something accepted by a constructor of class X,
than an operatorX&() member of a's class (call that class A)...?

It seems to me that the highest priority conversion of them all would
be "no conversion at all", i.e. assume class X has a constructor that
accepts an A, as in...:

class X:
class A{ public: operatorX&() const; };
class X{ public: X(const A&); X(const X&); }

Even in this case, wouldn't the two usages...:

    A a;
    X x1(a);
    X x2=a;

just both be _ambiguous_...?  I do suspect I may be somewhat
confused here, so would appreciate clarification (ideally with
draft standard chapter&verse reference, thanks!).


Alex
--
DISCLAIMER: these are TOTALLY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it                            Phone: +39 (51) 597313
CAD.LAB s.p.a., v. Ronzani 7/29, Casalecchio, Italia   Fax: +39 (51) 597120

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: martelli@cadlab.cadlab.it (Alex Martelli)
Date: 1995/10/21
Raw View
matt@godzilla.EECS.Berkeley.EDU (Matt Austern) writes:
 ...
>Sort of.  If a is of class A, if the copy constructor X::X(const X&)
>exists, and if the converting constructor X::X(const A&) exists and
>isn't qualified as explicit, then "X x(a)" simply invokes the
>converting constructor while "X x=a" invokes the converting
>constructor and then the copy constructor.

So, to clarify my understanding -- the following program...:

--cut tc.cc
#include <iostream.h>

class A { };

class X {
public:
    X(const X&) {
        cout<<"X::copy ctor"<<endl;
    }
    X(const A&) {
        cout<<"X::ctor(A&)"<<endl;
    }
};

int
main()
{
    A a;
    X x1 = a;
    X x2(a);

    return 0;
}
--end cut

... should necessarily emit:

X::ctor(A&)
X::ctor(A&)
X::copy ctor

and an implementation optimizing out the copy ctor in this case
would be non-conforming...?  Oh boy, I _am_ confused -- I thought
such sentences in the draft as "Either direct-initialization semantics
or copy-initialization semantics apply" in  [class.expl.init] sub 1
were there to specifically allow such optimizing-out... perhaps it
would be beneficial to the standard's clarity if this was spelled
out in as many words (or IS it there, and I'm just being unable to
see it?  I still think some clarification would help...).


Alex
--
DISCLAIMER: these are TOTALLY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it                            Phone: +39 (51) 597313
CAD.LAB s.p.a., v. Ronzani 7/29, Casalecchio, Italia   Fax: +39 (51) 597120
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: jlm@two-oo-one.fr (Jean-Louis Moser)
Date: 1995/10/13
Raw View
| According to the standard, are the two lines of the main
| equivalent ? My Opinion is yes, but one of my compilers would
| like to access copy contructor to be happy with the
| second line as if it would like to build a2 from a temporary A
| which would be build from the int value 99. If we make copy
| constructor public, this one isn't called, but the compiler
| is happy. Thank you for answers.

#include <iostream.h>

class A {
public:
    A (int i) {cout << "A" << endl;}
private:
    A (const A&) {cout << "COPY" << endl;}
};

void main ()
{
    A a1 (100);
    A a2 = 99;
}
--
+----------------------------+------------------------------------+
|   Jean-Louis Moser         |    2001 SA                         |
|   tel: 33 (1)46.66.54.54   |    2, rue de la renaissance        |
|   Email: jlm@two-oo-one.fr |    F-92184 Antony Cedex            |
+----------------------------+------------------------------------+
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/10/13
Raw View
>>>>> Jean-Louis Moser <jlm@two-oo-one.fr> writes:

> | According to the standard, are the two lines of the main
> | equivalent ? My Opinion is yes

Nope.

  8.5  Initializers                                           [dcl.init]

10The  initialization  that occurs in argument passing, function return,
  throwing  an  exception  (_except.throw_),   handling   an   exception
  (_except.handle_),     and     brace-enclosed     initializer    lists
  (_dcl.init.aggr_) is called copy-initialization and is  equivalent  to
  the form
          T x = a;
  The  initialization  that  occurs  in  new  expressions  (_expr.new_),
  static_cast expressions (_expr.static.cast_), functional notation type
  conversions  (_expr.type.conv_),  and  base  and  member  initializers
  (_class.base.init_) is called direct-initialization and is  equivalent
  to the form
          T x(a);

...

    --Otherwise (i.e., for the remaining copy-initialization  cases),  a
      temporary  of  the destination type is created.  User-defined con-
      versions that can convert from the source type to the  destination
      type  are enumerated (_over.match.user_), and the best one is cho-
      sen through overload resolution (_over.match_).  The  user-defined
      conversion  so  selected  is  called  to  convert  the initializer
      expression into the temporary.  If the conversion cannot  be  done
      or  is  ambiguous,  the  initialization is ill-formed.  The object
      being initialized is then direct-initialized  from  the  temporary
      according  to  the rules above.7) In certain cases, an implementa-
      tion is permitted to eliminate the temporary by  initializing  the
      object directly; see _class.temporary_.

Jason

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: tony@ews360.nec.com.tw (Anthony S. H. Lee)
Date: 1995/10/14
Raw View
Jean-Louis Moser (jlm@two-oo-one.fr) wrote:
: | According to the standard, are the two lines of the main
: | equivalent ? My Opinion is yes, but one of my compilers would
: | like to access copy contructor to be happy with the
: | second line as if it would like to build a2 from a temporary A
: | which would be build from the int value 99. If we make copy
: | constructor public, this one isn't called, but the compiler
: | is happy. Thank you for answers.

: #include <iostream.h>

: class A {
: public:
:     A (int i) {cout << "A" << endl;}
: private:
:     A (const A&) {cout << "COPY" << endl;}
: };

: void main ()
: {
:     A a1 (100);
:     A a2 = 99;
: }

Have you tried to remove the copy constuctor?
You are right! S. Lippman described this characteristic in his
book, 'C++ Primer'

Your compiler may not following the C++ standard!
Can you tell us what brand it was? :)

--
! Anthony S. H. Lee [Lee, Shih Hao]         Internet: tony@ews360.nec.com.tw
! BIG5:'uh;( EUC:JWDIk0     MSN: Anthony_S_H_Lee     Anthony_S_H_Lee@MSN.com
! Lee-fruit, Shih-scholar, Hao-hero        WWW http://necta.nec.com.tw/~tony
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]