Topic: ANSI C++ feature to be removed...


Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 10 May 2001 17:27:51 GMT
Raw View
heard@vvnet.com (C. M. Heard) wrote (abridged):
> However, if Foo's copy constructor and/or assignment operator modifies
> its argument, then why not write GenerateFoo to take a Foo as a
> reference argument rather than to return a Foo by value?  In other
> words, instead of something like
>
> Foo GenerateFoo() {... return <foo-expression>}
> Foo foo = GenerateFoo();
>
> write
>
> void GenerateFoo(Foo& generatedFoo) {... generatedFoo =
> <foo-expression>}
> Foo foo; GenerateFoo(foo);
>
> Then you would not need to make the copy constructor and/or assignment
> operator arguments const.
>
> What is wrong with that?

It is syntactically horrid if we want operators. Eg:

    Matrix a,b,c,d,e;

    d = a+b+c+e;

is easier to proof-read than:

    Matrix a,b,c,d,e;

    Matrix temp1, temp2;
    plus( temp1, a, b );
    plus( temp2, temp1, c );
    plus( e, temp2, d );

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Mirek Fidler" <cxl@iol.cz>
Date: Thu, 10 May 2001 17:27:57 GMT
Raw View
> However, if Foo's copy constructor and/or assignment operator modifies
> its argument, then why not write GenerateFoo to take a Foo as a
> reference argument rather than to return a Foo by value?  In other
> words, instead of something like
>
> Foo GenerateFoo() {... return <foo-expression>}
> Foo foo = GenerateFoo();
>
> write
>
> void GenerateFoo(Foo& generatedFoo) {... generatedFoo = <foo-expression>}
> Foo foo; GenerateFoo(foo);
>
> Then you would not need to make the copy constructor and/or assignment
> operator arguments const.
>
> What is wrong with that?
>

   This would sure work, but it disallows you to write code in
functional-like manner. Instead of e.g.

Vector<Foo> foo = Sort(GetData());

    you have to write

Vector<Foo> foo;
GetData(foo);
Sort(foo);

    Which could be less clear in some contexts. Think - if using reference
argument would be satisfactory, why auto_ptr does nt use it instead of that
dirty dance with mutable ?

    Further, proper using of "move" constructors would easily make possible
things like

vector< vector<Foo> >

    without any performance penalty, even when Foo

struct Foo {
    vector<Boo> boo;
    int number;
};

    itself contains a container.

Mirek


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: Thu, 10 May 2001 20:07:21 GMT
Raw View
In article <crfK6.7133$Up.210324@sea-read.news.verio.net>, "C. M. Heard"
<heard@vvnet.com> wrote:
>...if Foo's copy constructor and/or assignment operator modifies
>its argument, then why not write GenerateFoo to take a Foo as a
>reference argument rather than to return a Foo by value?  In other
>words, instead of something like
>
>Foo GenerateFoo() {... return <foo-expression>}
>Foo foo = GenerateFoo();
>
>write
>
>void GenerateFoo(Foo& generatedFoo) {... generatedFoo = <foo-expression>}
>Foo foo; GenerateFoo(foo);
>
>Then you would not need to make the copy constructor and/or assignment
>operator arguments const.
>
>What is wrong with that?

The reason one does not want to use that style is that one is implementing
something functional in style.

In those terms, your suggestion is that instead if writing
  integer x, y, z;
  z = x + y;
write
  add(z, x, y);

This is pretty un-intuitive.

But in fact this style is used, for example by the GNU http://www.gnu.org
multiprecision library GMP, which is written in C.

Then, if one would want to write something more like the algebraic version
in C++, it is hard to do it efficiently.

This is a pretty simply example. One could do something more complicated,
like an evaluator with the capacity of handling lambda expressions in a
functional style. Then your suggestion becomes very unintuitive at least:
You could use it at an implementation level, but then  you would probably
prefer to build another language on top of that.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "C. M. Heard" <heard@vvnet.com>
Date: Wed, 9 May 2001 20:48:31 GMT
Raw View
Mirek Fidler wrote:
> One feature, which we really hate in ANSI C++ and which could be easilly
> removed:
>
> ANSI C++ prohibits non-constant operation on temporary objects. That causes
> pretty much confusion in some of our library code, as we sometimes like to
> use "destroy-source-on-copy" style:
>
> class Foo {
>     char *ptr;
> .....
> public:
> .....
>     Foo(Foo& src)             { ptr = src.ptr; src.ptr = NULL; }
>     ~Foo()                          { if(ptr) delete ptr; }
> }
>
> So far so good. But
>
> Foo GenerateFoo() {......}
>
> .....
> Foo foo = GenerateFoo();
>
> is ill-formed, because GenerateFoo creates temporary and you cannot apply
> non-const Foo copy constructor.

Presumably you will have the same problem with Foo's assignment operator.

> So we have to use
>
> class Foo {
>     mutable char *ptr;
> ......
>     Foo(const Foo& src)
> ......
>
> which is completely misguiding, as in fact src in copy constructor is to be
> changed.

I agree that this is an abuse of mutable and that it is misleading to
make the copy constructor or assignment operator argument const when
the constructor modifies its argument in an essential way.

However, if Foo's copy constructor and/or assignment operator modifies
its argument, then why not write GenerateFoo to take a Foo as a
reference argument rather than to return a Foo by value?  In other
words, instead of something like

Foo GenerateFoo() {... return <foo-expression>}
Foo foo = GenerateFoo();

write

void GenerateFoo(Foo& generatedFoo) {... generatedFoo = <foo-expression>}
Foo foo; GenerateFoo(foo);

Then you would not need to make the copy constructor and/or assignment
operator arguments const.

What is wrong with that?

Mike

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Mirek Fidler" <cxl@iol.cz>
Date: Mon, 7 May 2001 11:25:13 GMT
Raw View
> Rather than removing the fence,
> which really does prevent errors, I think,
> perhaps we could make a way to get thru it
> when we really want to.
>
> Maybe this:
>
>   class Foo {
>     char *ptr;
>     // ...
>     Foo( mutable Foo& src); // used like a copy constructor
>                             // but actually changes src.
>   };
>

    I do not see actuall difference here. I think that without const, it is
obvious that the constructor is not normal.

    Perhaps it would be satisfactory to just change a terminology little
bit.

Foo(const Foo&) - the COPY constructor

Foo(Foo&) - the PICK constructor

Mirek


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: Mon, 7 May 2001 01:31:12 GMT
Raw View
In article <9d33k7$tl1$1@news.vol.cz>, "news.volny.cz" <cxl@iol.cz> wrote:

>One feature, which we really hate in ANSI C++ and which could be easilly
>removed:

>ANSI C++ prohibits non-constant operation on temporary objects.
...
>class Foo {
>    char *ptr;
>.....
>public:
>.....
>    Foo(Foo& src)             { ptr = src.ptr; src.ptr = NULL; }
>    ~Foo()                          { if(ptr) delete ptr; }
>}

>So far so good. But
>
>Foo GenerateFoo() {......}
...
>Foo foo = GenerateFoo();
>is ill-formed, because GenerateFoo creates temporary and you cannot apply
>non-const Foo copy constructor.
>
>So we have to use
>
>class Foo {
>    mutable char *ptr;

>    Foo(const Foo& src)
..
>which is completely misguiding, as in fact src in copy constructor is to be
>changed.

I think myself too that the C++ standard should be changed so that if the
copy constructor T::T(T&) has been explicitly written, then it will be
applied in the same way to temporaries as the copy constructor T::T(const
T&) is used to prolong the life of objects at need.

As you say, as it is now T::T(T&) isn't applied the way one would expect
from the point of view of dynamic programming, which screws up the use of
functions with reference arguments f(T&), as one ends up having to put in
explicit constructors f(T(t)).

And the only reasonable way around this seems to be to declare mutable
objects, and then use T::T(const T&) in lieu of T::T(T&).

Very strange indeed.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Dennis Yelle <dennis51@jps.net>
Date: Mon, 7 May 2001 01:32:09 GMT
Raw View
"news.volny.cz" wrote:
>
> One feature, which we really hate in ANSI C++ and which could be easilly
> removed:
>
> ANSI C++ prohibits non-constant operation on temporary objects. That causes
> pretty much confusion in some of our library code, as we sometimes like to
> use "destroy-source-on-copy" style:
>
> class Foo {
>     char *ptr;
> .....
> public:
> .....
>     Foo(Foo& src)             { ptr = src.ptr; src.ptr = NULL; }
>     ~Foo()                          { if(ptr) delete ptr; }
> }
>
> So far so good. But
>
> Foo GenerateFoo() {......}
>
> .....
> Foo foo = GenerateFoo();
>
> is ill-formed, because GenerateFoo creates temporary and you cannot apply
> non-const Foo copy constructor.
>
> So we have to use
>
> class Foo {
>     mutable char *ptr;
> ......
>     Foo(const Foo& src)
> ......
>
> which is completely misguiding,

Rather than removing the fence,
which really does prevent errors, I think,
perhaps we could make a way to get thru it
when we really want to.

Maybe this:

  class Foo {
    char *ptr;
    // ...
    Foo( mutable Foo& src); // used like a copy constructor
                            // but actually changes src.
  };

Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here:
http://table.jps.net/~vert/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "news.volny.cz" <cxl@iol.cz>
Date: Sun, 6 May 2001 11:15:10 GMT
Raw View
One feature, which we really hate in ANSI C++ and which could be easilly
removed:

ANSI C++ prohibits non-constant operation on temporary objects. That causes
pretty much confusion in some of our library code, as we sometimes like to
use "destroy-source-on-copy" style:

class Foo {
    char *ptr;
.....
public:
.....
    Foo(Foo& src)             { ptr = src.ptr; src.ptr = NULL; }
    ~Foo()                          { if(ptr) delete ptr; }
}

So far so good. But

Foo GenerateFoo() {......}

.....
Foo foo = GenerateFoo();

is ill-formed, because GenerateFoo creates temporary and you cannot apply
non-const Foo copy constructor.

So we have to use

class Foo {
    mutable char *ptr;
......
    Foo(const Foo& src)
......

which is completely misguiding, as in fact src in copy constructor is to be
changed. We try to make it more readable by

#define pick_   const

but that helps only a little.

Hope some competent would read this ;-)))

Mirek


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]