Topic: Fancy pointers that behave like Java-style reference?


Author: thp@cs.ucr.edu
Date: Wed, 12 Nov 2003 03:01:59 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bolisj$q39$1@glue.ucr.edu>...
+> Francis Glassborow <francis@robinton.demon.co.uk> wrote:
+> + In article <c87c1cfb.0311071749.787a0737@posting.google.com>, Bob Bell
+> + <belvis@pacbell.net> writes
+> +>It seems pretty obvious to me that the phrase "largest part of the
+> +>program in which that name is valid" must mean that the declarative
+> +>region must end at the point at which the destructor executes; after
+> +>the destructor of w executes, w.r is no longer valid.
+> +
+> + I think you are confusing names with objects. A name may be valid (i.e.
+> + the compiler must not reject it) even though the object it referred to
+> + has ended its lifetime.
+>
+> I've always understood that (per the definition of scope), within the
+> scope of a given name, all occurrences of that name refer to the same
+> entity.  So, after an object's destruction, its name refers to the
+> ghost of the destructed object, and any use of that name invokes nasal
+> demons.  But, after a subsequent placement-new (of appropriate type)
+> at the old location, the name refers to the resurrected object, and
+> demons go away.  Right?
+
+ struct Widget {
+   int x;
+ };
+
+ void F()
+ {
+   Widget w;
+
+   w.~Widget();
+
+ // summon the nasal demons
+   w.x = 10;
+ }
+
+ The nasal demons come because this code treats raw memory like an
+ object. After executing w.~Widget(), the memory region at &w does not
+ contain an object; using it as if it were an object is as undefined as
+ this:
[...]

I completely agree.

I would expect you to object to the use of the verb "resurrected" in
the last sentence of that posting, also to the use of "reconstructed",
"renewed", or "re-incarnated" in that same position.

Note that in ordinary parlance, if someone's house gets destroyed,
some people would say that they rebuilt their house, while others
would say that they built a new house on the old lot.  ("six" vs.
"half a dozen")

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Wed, 12 Nov 2003 04:32:02 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<boigc0$1ub$1@glue.ucr.edu>...
...
> AFAIK, the results of sizeof are implementation defined and are only
> as honest and reasonable as the implementor chooses to make them.

For POD types, sizeof() has to be the right size to use for operations
such as memcpy() and memcmp(), as well as for calculation memory
locations in arrays. This severely limits just how dishonest an
implmentation can be, at least with POD types. Reasonability, on the
other hand, is entirely up to the implementation.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 12 Nov 2003 04:32:16 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bomti5$7lt$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + thp@cs.ucr.edu wrote in message news:<bokd1p$h22$1@glue.ucr.edu>...
+> +> So, there are three supposedly distnct notions:
+> +>
+> +>   - references, which supposedly get initialized with reference values
+> +>     at certain points.
+> +>
+> +>   - reference values, which supposedly are returned by functions
+> +>     having reference return types.
+> +>
+> +>   - referents, which supposedly are the things referred to by
+> +>     reference values.
+> +>
+> +> Which of the three possible distinctions are accepted and which are
+> +> under question?
+> +
+> + All are objectionable, since they all use the term "reference value".
+> +
+> + I would use say something more like this:
+> +
+> + -- references, which get initialized with objects
+> + -- referents, the objects referred to by references
+> +
+> + As far as I know, these concepts are completely consistent with the
+> + way references are defined and used in C++. No "reference value"
+> + concept is implied or needed.
+>
+> There's still the problem of what it is that a reference-valued
+> function returns.
+
+ A reference; I feel like I've answered this question a dozen times.

That wasn't a question.

+ Why is this so hard?

What's hard?

+ I just don't get the problem here.

The problem is that C++ functions return values:

  The value of a function call is the value returned by the called
  function ...                                           [5.2.2#4]

and it appears that not all references are values.

+ Maybe you should just spell out what problem the term "reference
+ value" solves.

It allows us to distinguish between the references that are and aren't
values.  Just as we distinguish between floatss that are and aren't
values.  float-valued functions return float values but that kind of
float can't be named.

+> +> + No one has shown how to change the value of a reference. There have
+> +> + been examples of destroying references and recreating new ones in the
+> +> + same memory.
+> +> +
+> +> + void G(Widget* w, int& r)
+> +> + {
+> +> +   w->~Widget();
+> +> +
+> +> +   new (w) Widget(r);
+> +> + }
+> +> +
+> +> + void F()
+> +> + {
+> +> +   int x, y;
+> +> +   Widget*  w = new Widget(x);
+> +> +
+> +> +   G(w, y);
+> +> + }
+> +>
+> +> + Do you think this changes w->r? I don't. Even if G() is really called
+> +> + operator=().
+> +>
+> +> Per the definitions of "declarative region", w denotes the same Widget
+> +> (having the same reference member) both before and after the execution
+> +> of G.
+> +
+> + I don't think so. My newfound understanding of declarative region
+> + tells me that w denotes the same _pointer object_; what it points to
+> + is a dynamic issue and is not affected by static concepts like
+> + declarative region.
+>
+> Huh?  Are you claiming that names of C++ variables refer don't refer
+> to the object in their definitions but rather to hidden pointers that
+> point to that object.  AFAIK, unlike say Java, C/C++ uses value
+> semantics, i.e., there's no indirection between the name and what it
+> refers to.
+
+ Read the code again. W is a pointer to a Widget, not a Widget. In G(),
+ w points to a _new_ Widget, even though the value of w never changes.

Oops.  My oversight.

+ It doesn't even matter if w is really called "this":
+
+ Widget& Widget::operator=(const Widget& iOther)
+ {
+   if (this != &iOther) {
+      this->~Widget();
+      new (this) Widget(iOther);
+   }
+   return *this;
+ }
+
+ Here, even though the pointer value of "this" never changed, it
+ obviously refers to one Widget at the beginning of the function and
+ another Widget at the end. Just as in the G() example above.
+
+> + In this case, one Widget's lifetime ends and a new one begins. Both
+> + Widget happen to use the same storage, so w continues to point to a
+> + Widget. This is not really any different from:
+>
+> The name "w" refers to a Widget, the same Widget throughout the scope
+> of its declaration.
+
+ Read again; w is a pointer.

Right.

[...]
+> I'm simply going by the common notions of "scope", which is that all
+> occurrences of a name within a given scope refer to the same entity.
+
+ Are you claiming that an object's lifetime doesn't end when its
+ destructor executes?

I'm claiming that the Standard says that for a given declaration of a
name, all unqualified instances of that name in that declaration's
scope refer to the same entity.  AFAIK, it does't mention names of
destructed objects as an exception.

The view that an object constructed via placement-new at the site of a
destructed object is different from the destructed object appears to
conflict with the above-mentioned view that it's name (if any) still
refers to the same object.

[...]
+ No. sizeof(x) gives the size of x. So sizeof(int) gives the size of an
+ int. sizeof(Widget) gives the size of a Widget. But sizeof(Widget)
+ doesn't tell me anything about the size of a reference.

AFAIK, there are relatively few real constraints on a conforming
implementation of sizeof, and truthfulness isn't among them.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Thu, 13 Nov 2003 03:35:45 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bopta9$2nk$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + thp@cs.ucr.edu wrote in message news:<bomti5$7lt$1@glue.ucr.edu>...
> +> There's still the problem of what it is that a reference-valued
> +> function returns.
> +
> + A reference; I feel like I've answered this question a dozen times.
>
> That wasn't a question.
>
> + Why is this so hard?
>
> What's hard?

Either one of these:

-- understanding why "reference value" is a necessary concept
-- getting across the idea that "reference value" is an unnecessary
concept

So far, neither one of these seems to be happening.

> + I just don't get the problem here.
>
> The problem is that C++ functions return values:
>
>   The value of a function call is the value returned by the called
>   function ...                                           [5.2.2#4]
>
> and it appears that not all references are values.

_No_ references are values; at least, in my 10 or so years of using
C++ I haven't seen a single example of a reference that is a value.

> + Maybe you should just spell out what problem the term "reference
> + value" solves.
>
> It allows us to distinguish between the references that are and aren't
> values.  Just as we distinguish between floatss that are and aren't
> values.  float-valued functions return float values but that kind of
> float can't be named.

I understand what it _allows_ you to do; what I don't understand is
why you _need_ to make that distinction. As I said once before, I've
never made that distinction, and it's never caused a problem for me of
which that I'm aware.

> [...]
> +> I'm simply going by the common notions of "scope", which is that all
> +> occurrences of a name within a given scope refer to the same entity.
> +
> + Are you claiming that an object's lifetime doesn't end when its
> + destructor executes?
>
> I'm claiming that the Standard says that for a given declaration of a
> name, all unqualified instances of that name in that declaration's
> scope refer to the same entity.  AFAIK, it does't mention names of
> destructed objects as an exception.
>
> The view that an object constructed via placement-new at the site of a
> destructed object is different from the destructed object appears to
> conflict with the above-mentioned view that it's name (if any) still
> refers to the same object.

I see where you are coming from. But this view conflicts with the
notion that once a destructor executes, the object is gone. In the
oft-cited example:

void F()
{
   Widget w;

   w.~Widget();

   w.x = 10;
}

According to the scoping rules, the last use of "w" names the same
object that the other uses of "w" do. However, in a very real sense it
does not, because the object no longer exists. I can't quote chapter
and verse, but I believe that there is a section that discusses
lifetime issues and the relationship between object lifetime and
construction/destruction. There are no provisions for "bringing an
object back to life," so even though the sections you quote seem to
imply resurrection, I think that's a misinterpretation, because it led
you to invent terms like "resurrected" and "object in a deconstructed
state", both of which are not really C++ concepts.

Consider this as another example of the problem of scoping vs.
lifetime:

void F()
{
   Widget w;

   new (&w) Widget();

   w.x = 10;  // which Widget?
}

Because every call of a constructor makes an object, there must be two
Widgets, one of which is just overwritten by the other. However,
according to the scoping rules you quote, there is only one object.
How do we reconcile this?

Part of the reason the standard doesn't spell out the
"destroy/recreate" exception to the scoping rule is that, as this
example shows, it's not the only exception. Often the standard doesn't
spell out everything in great detail, precisely because doing so would
be a lot of work and we wouldn't have a standard today because the
committee'd still be arguing over it.

I understand the scoping rules, but since the object model demands
that constructors yield new objects, the scoping rules can't be the
whole story. I don't have a problem reconciling these two views the
way I do, but that's me. If you think the story's not as simple as I
make it out to be, perhaps you've found a defect.

> [...]
> + No. sizeof(x) gives the size of x. So sizeof(int) gives the size of an
> + int. sizeof(Widget) gives the size of a Widget. But sizeof(Widget)
> + doesn't tell me anything about the size of a reference.
>
> AFAIK, there are relatively few real constraints on a conforming
> implementation of sizeof, and truthfulness isn't among them.

Sure, but I'm talking within the context of C++. In C++, sizeof(int)
yields the size of an int; no matter how "truthful" that is, there
isn't any C++ code I can write to prove it false. Also in C++,
sizeof(Widget) is the size of a Widget, not the size of a reference.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Thu, 13 Nov 2003 03:55:43 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:boqi53$7r4$1@glue.ucr.edu...

> Note that in ordinary parlance, if someone's house gets destroyed,
> some people would say that they rebuilt their house, while others
> would say that they built a new house on the old lot.  ("six" vs.
> "half a dozen")

Hm, that pretty well fits the view of reference reseating or "value change".

If you have a house built, it is said you can't move the main walls.
Then someone comes around with a scheme: you call a dozer on the house, and
rebuild it, with some walls in different places.  Voils, the walls
impossible to move magically moved.

Well, for some reason I'm locked in my view -- so that just can't impress
me.
And I always thought we have terms to lead and not to mislead. Even if in
some context we use some phrases not fitting the meaning -- I know when we
"just say it that way" but it shall not be taken literally.    I see it no
problem to talk about a house rebuilt -- until everyone is aware the fact
that it is a new house, and has no relation to the old besides some of our
emotions -- and the acre of land under it.

Paul


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 13 Nov 2003 19:52:16 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bopta9$2nk$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + thp@cs.ucr.edu wrote in message news:<bomti5$7lt$1@glue.ucr.edu>...
+> +> There's still the problem of what it is that a reference-valued
+> +> function returns.
+> +
+> + A reference; I feel like I've answered this question a dozen times.
+>
+> That wasn't a question.
+>
+> + Why is this so hard?
+>
+> What's hard?
+
+ Either one of these:
+
+ -- understanding why "reference value" is a necessary concept
+ -- getting across the idea that "reference value" is an unnecessary
+ concept
+
+ So far, neither one of these seems to be happening.
+
+> + I just don't get the problem here.
+>
+> The problem is that C++ functions return values:
+>
+>   The value of a function call is the value returned by the called
+>   function ...                                           [5.2.2#4]
+>
+> and it appears that not all references are values.
+
+ _No_ references are values; at least, in my 10 or so years of using
+ C++ I haven't seen a single example of a reference that is a value.

Consider "f()" where f is defined "int& f(){return *new int;}".  If I
read the 5.2.2#4 correctly, f returns a value, which given the return
type of f would have to be a reference value.

+> + Maybe you should just spell out what problem the term "reference
+> + value" solves.
+>
+> It allows us to distinguish between the references that are and aren't
+> values.  Just as we distinguish between floatss that are and aren't
+> values.  float-valued functions return float values but that kind of
+> float can't be named.
+
+ I understand what it _allows_ you to do; what I don't understand is
+ why you _need_ to make that distinction. As I said once before, I've
+ never made that distinction, and it's never caused a problem for me of
+ which that I'm aware.

I know programmers who refuse to distinguish between int values and
int objects.  They claim that all values are in temp objects, so the
distinction is unnecessary.  Such distinctions may be necessary to
conform to the nomenclature of the Standard, but the Standard may not
have needed to make them in order to specify the behavior as it has.

+> [...]
+> +> I'm simply going by the common notions of "scope", which is that all
+> +> occurrences of a name within a given scope refer to the same entity.
+> +
+> + Are you claiming that an object's lifetime doesn't end when its
+> + destructor executes?
+>
+> I'm claiming that the Standard says that for a given declaration of a
+> name, all unqualified instances of that name in that declaration's
+> scope refer to the same entity.  AFAIK, it does't mention names of
+> destructed objects as an exception.
+>
+> The view that an object constructed via placement-new at the site of a
+> destructed object is different from the destructed object appears to
+> conflict with the above-mentioned view that it's name (if any) still
+> refers to the same object.
+
+ I see where you are coming from. But this view conflicts with the
+ notion that once a destructor executes, the object is gone. In the
+ oft-cited example:
+
+ void F()
+ {
+   Widget w;
+
+   w.~Widget();
+
+   w.x = 10;
+ }
+
+ According to the scoping rules, the last use of "w" names the same
+ object that the other uses of "w" do. However, in a very real sense it
+ does not, because the object no longer exists. I can't quote chapter
+ and verse, but I believe that there is a section that discusses
+ lifetime issues and the relationship between object lifetime and
+ construction/destruction. There are no provisions for "bringing an
+ object back to life," so even though the sections you quote seem to
+ imply resurrection, I think that's a misinterpretation, because it led
+ you to invent terms like "resurrected" and "object in a deconstructed
+ state", both of which are not really C++ concepts.

There's an obvious conflict between:
  - static scoping
  - prohibiting multi-segment lifetimes.
But I've seen nothing that explicitly says that once an object goes
away, it can't come back, i.e, nothing that says that an object's
lifetime can't have more than one segment.  Moreover, my reading of
3.3#1 indicates that in the example we discussed, the execution of
placement-new starded a new segment of the original object's lifetime.

+ Consider this as another example of the problem of scoping vs.
+ lifetime:
+
+ void F()
+ {
+   Widget w;
+
+   new (&w) Widget();
+
+   w.x = 10;  // which Widget?
+ }
+
+ Because every call of a constructor makes an object, there must be two
+ Widgets, one of which is just overwritten by the other. However,
+ according to the scoping rules you quote, there is only one object.
+ How do we reconcile this?

I'd simply say that placement-new reconstructed (or re-new'd) w.
Again, I've seen nothing that requires lifetimes to be monosegmented.

+ Part of the reason the standard doesn't spell out the
+ "destroy/recreate" exception to the scoping rule is that, as this
+ example shows, it's not the only exception.

If static scoping isn't intended, failing to mention that must be an
oversight.

+ Often the standard doesn't
+ spell out everything in great detail, precisely because doing so would
+ be a lot of work and we wouldn't have a standard today because the
+ committee'd still be arguing over it.

It's not so all that important that their metaphors be consistent, so
long as they precisely define the behavior of each program.

+ I understand the scoping rules, but since the object model demands
+ that constructors yield new objects, the scoping rules can't be the
+ whole story. I don't have a problem reconciling these two views the
+ way I do, but that's me. If you think the story's not as simple as I
+ make it out to be, perhaps you've found a defect.

I think it's as simple but different.  I'd preserve static scoping and
by accepting multi-segmented lifetimes.  That's probably simply a
matter of metaphysical taste.  My preference is based mostly on
pedagogical efficiency.  Consider:

  Widget w;

  void presto() {
    if ( getInput() ) {
      w.~Widget();
      new(&w) Widget();
    }
  }

  int main() {
    for ( int i = 0; i != whatever; ++i ) {
      presto();
      cout << w;
    }
  }

We can tell students either that

  The single occurrence of w in main refers to the Widget most recently
  created at &w if its still alive, because that's the way it is.

or that

  The call to w's destructor destroy w and the call to placement-new
  reconstructs it again.  (Imagine reincarnation.)

IMHO, they'll understand the latter a lot easier.

I don't consider it a defect that there is a conflict in the
Standard's metaphysical metaphors, a conflict that has no impact on
the specific behavior of programs.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Fri, 14 Nov 2003 01:25:21 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bovi63$ivf$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + void F()
> + {
> +   Widget w;
> +
> +   w.~Widget();
> +
> +   w.x = 10;
> + }
> +
> + According to the scoping rules, the last use of "w" names the same
> + object that the other uses of "w" do. However, in a very real sense it
> + does not, because the object no longer exists. I can't quote chapter
> + and verse, but I believe that there is a section that discusses
> + lifetime issues and the relationship between object lifetime and
> + construction/destruction. There are no provisions for "bringing an
> + object back to life," so even though the sections you quote seem to
> + imply resurrection, I think that's a misinterpretation, because it led
> + you to invent terms like "resurrected" and "object in a deconstructed
> + state", both of which are not really C++ concepts.
>
> There's an obvious conflict between:
>   - static scoping
>   - prohibiting multi-segment lifetimes.
> But I've seen nothing that explicitly says that once an object goes
> away, it can't come back, i.e, nothing that says that an object's
> lifetime can't have more than one segment.  Moreover, my reading of
> 3.3#1 indicates that in the example we discussed, the execution of
> placement-new starded a new segment of the original object's lifetime.

I'm saying that in the example I gave above, in the line "w.x = 10;" w
clearly isn't naming the Widget that is constructed in the first line
of the function. Therefore, static scoping can't be the only factor
determining object identity.

Further, "bringing an object back to life", "object in a deconstructed
state", and "multi-segment lifetimes" are concepts that don't appear
anywhere in the standard; you invented these concepts. If the authors
of the standard intended these ideas to be part of C++, don't you
think they would have said something about them, rather than having
them be something about which you must read between the lines?

> + Consider this as another example of the problem of scoping vs.
> + lifetime:
> +
> + void F()
> + {
> +   Widget w;
> +
> +   new (&w) Widget();
> +
> +   w.x = 10;  // which Widget?
> + }
> +
> + Because every call of a constructor makes an object, there must be two
> + Widgets, one of which is just overwritten by the other. However,
> + according to the scoping rules you quote, there is only one object.
> + How do we reconcile this?
>
> I'd simply say that placement-new reconstructed (or re-new'd) w.
> Again, I've seen nothing that requires lifetimes to be monosegmented.

I've seen nothing that allows lifetimes to be multi-segmented.

In any case, could you tell me what is going on in this example?

class Foo { };

class Bar { int x; Foo y; };

void F()
{
   Bar a;

   new (&a) Foo();
}

There is no way that "a" names a Bar object after the placement new.

What do you think is happening here?

void F()
{
   Widget* p = new Widget();

   p->~Widget();
   new (p) Widget();
}

If I'm understanding your viewpoint, it's the fact that in previous
examples "w" had to refer to the same entity throughout its scope that
implied resurrection. Here, scoping is not an issue, since the Widget
is not statically scoped. So it seems that this is not an example of
resurrection. If it's not resurrection, what is it?

[snip]

> + I understand the scoping rules, but since the object model demands
> + that constructors yield new objects, the scoping rules can't be the
> + whole story. I don't have a problem reconciling these two views the
> + way I do, but that's me. If you think the story's not as simple as I
> + make it out to be, perhaps you've found a defect.
>
> I think it's as simple but different.  I'd preserve static scoping and
> by accepting multi-segmented lifetimes.  That's probably simply a
> matter of metaphysical taste.  My preference is based mostly on
> pedagogical efficiency.  Consider:
>
>   Widget w;
>
>   void presto() {
>     if ( getInput() ) {
>       w.~Widget();
>       new(&w) Widget();
>     }
>   }
>
>   int main() {
>     for ( int i = 0; i != whatever; ++i ) {
>       presto();
>       cout << w;
>     }
>   }
>
> We can tell students either that
>
>   The single occurrence of w in main refers to the Widget most recently
>   created at &w if its still alive, because that's the way it is.
>
> or that
>
>   The call to w's destructor destroy w and the call to placement-new
>   reconstructs it again.  (Imagine reincarnation.)
>
> IMHO, they'll understand the latter a lot easier.

IMHO, the former is a lot easier to understand, especially when you
factor in consequent reasoning. Consider that the students who would
be confronted by this kind of lesson would have to be fairly advanced,
and probaly already familiar with most of the concepts in C++.

Also, this example is really only useful academically, for purposes of
discussions such as the one we're having. The dangers of actually
using such code far outweigh its usefulness -- there isn't anything
you can do with the

   w.~Widget();
   new (&w) Widget();

that can't be done with safer alternatives. So the only point of
showing this code to students is to warn them of its dangers and to
stimulate philosophical discussions about object lifetime.

Finally, "which is easier to understand" is ultimately a red herring,
since it doesn't matter which is easier -- it matters which is more
correct. The second view leads to a lot of notions that simply aren't
part of C++, like reference reseating, resurrection, and objects in a
deconstructed state.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 14 Nov 2003 21:24:43 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bovi63$ivf$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + void F()
+> + {
+> +   Widget w;
+> +
+> +   w.~Widget();
+> +
+> +   w.x = 10;
+> + }
+> +
+> + According to the scoping rules, the last use of "w" names the same
+> + object that the other uses of "w" do. However, in a very real sense it
+> + does not, because the object no longer exists. I can't quote chapter
+> + and verse, but I believe that there is a section that discusses
+> + lifetime issues and the relationship between object lifetime and
+> + construction/destruction. There are no provisions for "bringing an
+> + object back to life," so even though the sections you quote seem to
+> + imply resurrection, I think that's a misinterpretation, because it led
+> + you to invent terms like "resurrected" and "object in a deconstructed
+> + state", both of which are not really C++ concepts.
+>
+> There's an obvious conflict between:
+>   - static scoping
+>   - prohibiting multi-segment lifetimes.
+> But I've seen nothing that explicitly says that once an object goes
+> away, it can't come back, i.e, nothing that says that an object's
+> lifetime can't have more than one segment.  Moreover, my reading of
+> 3.3#1 indicates that in the example we discussed, the execution of
+> placement-new starded a new segment of the original object's lifetime.
+
+ I'm saying that in the example I gave above, in the line "w.x = 10;" w
+ clearly isn't naming the Widget that is constructed in the first line
+ of the function. Therefore, static scoping can't be the only factor
+ determining object identity.

The name "w" refers to the "same" now-destructed object, and that line
invokes undefined behavior.

+ Further, "bringing an object back to life", "object in a deconstructed
+ state", and "multi-segment lifetimes" are concepts that don't appear
+ anywhere in the standard;

But they seem to be implied by a strict interpretation of the scoping
rules.

+ you invented these concepts.

I simply described the consequences of "w" always naming the same
entity within a given declarative region.

+ If the authors
+ of the standard intended these ideas to be part of C++, don't you
+ think they would have said something about them, rather than having
+ them be something about which you must read between the lines?

There was no conflict between mono-segmented lifetimes and the
scoping rules until they added placement-new, at which point
the conflict probably went unnoticed.

+> + Consider this as another example of the problem of scoping vs.
+> + lifetime:
+> +
+> + void F()
+> + {
+> +   Widget w;
+> +
+> +   new (&w) Widget();
+> +
+> +   w.x = 10;  // which Widget?
+> + }
+> +
+> + Because every call of a constructor makes an object, there must be two
+> + Widgets, one of which is just overwritten by the other. However,
+> + according to the scoping rules you quote, there is only one object.
+> + How do we reconcile this?
+>
+> I'd simply say that placement-new reconstructed (or re-new'd) w.
+> Again, I've seen nothing that requires lifetimes to be monosegmented.
+
+ I've seen nothing that allows lifetimes to be multi-segmented.
+
+ In any case, could you tell me what is going on in this example?
+
+ class Foo { };
+
+ class Bar { int x; Foo y; };
+
+ void F()
+ {
+   Bar a;
+
+   new (&a) Foo();
+ }
+
+ There is no way that "a" names a Bar object after the placement new.
+
+ What do you think is happening here?

The name "a" refers to the clobbered Bar, the same way that the name
"JFK" refers to a murdered president.

+ void F()
+ {
+   Widget* p = new Widget();
+
+   p->~Widget();
+   new (p) Widget();
+ }
+
+ If I'm understanding your viewpoint, it's the fact that in previous
+ examples "w" had to refer to the same entity throughout its scope that
+ implied resurrection. Here, scoping is not an issue, since the Widget
+ is not statically scoped. So it seems that this is not an example of
+ resurrection. If it's not resurrection, what is it?

Of course the name "p" must refer to the same pointer object, but I
find nothing in the Standard that implies that this pointer must point
to the same object at the end of the function.

+ [snip]
+
+> + I understand the scoping rules, but since the object model demands
+> + that constructors yield new objects, the scoping rules can't be the
+> + whole story. I don't have a problem reconciling these two views the
+> + way I do, but that's me. If you think the story's not as simple as I
+> + make it out to be, perhaps you've found a defect.
+>
+> I think it's as simple but different.  I'd preserve static scoping and
+> by accepting multi-segmented lifetimes.  That's probably simply a
+> matter of metaphysical taste.  My preference is based mostly on
+> pedagogical efficiency.  Consider:
+>
+>   Widget w;
+>
+>   void presto() {
+>     if ( getInput() ) {
+>       w.~Widget();
+>       new(&w) Widget();
+>     }
+>   }
+>
+>   int main() {
+>     for ( int i = 0; i != whatever; ++i ) {
+>       presto();
+>       cout << w;
+>     }
+>   }
+>
+> We can tell students either that
+>
+>   The single occurrence of w in main refers to the Widget most recently
+>   created at &w if its still alive, because that's the way it is.
+>
+> or that
+>
+>   The call to w's destructor destroy w and the call to placement-new
+>   reconstructs it again.  (Imagine reincarnation.)
+>
+> IMHO, they'll understand the latter a lot easier.
+
+ IMHO, the former is a lot easier to understand,

So, it's pretty much a matter of taste.

[...]
+ Finally, "which is easier to understand" is ultimately a red herring,
+ since it doesn't matter which is easier -- it matters which is more
+ correct. The second view leads to a lot of notions that simply aren't
+ part of C++, like reference reseating, resurrection, and objects in a
+ deconstructed state.

Presumably correct mean in accord with the words of the standard.
And, there are words in the Standard that seem to require the
existence of multisegmented lifetimes, and none that prohibit them.

In choosing among metaphors to communicate/specify the semantics of
C++, I recommend that the authors choose the metaphor that is easiest
to explain, retain, and understand.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 15 Nov 2003 15:02:24 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:boqi53$7r4$1@glue.ucr.edu...
+
+> Note that in ordinary parlance, if someone's house gets destroyed,
+> some people would say that they rebuilt their house, while others
+> would say that they built a new house on the old lot.  ("six" vs.
+> "half a dozen")
+
+ Hm, that pretty well fits the view of reference reseating or "value change".
+
+ If you have a house built, it is said you can't move the main walls.
+ Then someone comes around with a scheme: you call a dozer on the house, and
+ rebuild it, with some walls in different places.  Voils, the walls
+ impossible to move magically moved.
+
+ Well, for some reason I'm locked in my view -- so that just can't impress
+ me.
+ And I always thought we have terms to lead and not to mislead. Even if in
+ some context we use some phrases not fitting the meaning -- I know when we
+ "just say it that way" but it shall not be taken literally.    I see it no
+ problem to talk about a house rebuilt -- until everyone is aware the fact
+ that it is a new house, and has no relation to the old besides some of our
+ emotions -- and the acre of land under it.

For those who implemenations of C++, we have something called the
"as-if rule":

  This provision is sometimes called the "as-if" rule, because
  an implementation is free to disregard any reqirement of this
  International standard as long as the result is *as if* the
  requirement had been obeyed, as far as can be determined from
  the obserable behaior of the program.  [footnote 5 on page 5]

It seems to me that this same privilege should be extended to
discussions of the language as well.

Tom Payne


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 17 Nov 2003 22:34:24 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bp2v69$gvc$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + I'm saying that in the example I gave above, in the line "w.x = 10;" w
> + clearly isn't naming the Widget that is constructed in the first line
> + of the function. Therefore, static scoping can't be the only factor
> + determining object identity.
>
> The name "w" refers to the "same" now-destructed object, and that line
> invokes undefined behavior.

I'm not sure, but it sounds like you agree; because the object has
been destroyed, and it's lifetime has ended, static scope is not the
only factor determining object identity.

> + Further, "bringing an object back to life", "object in a deconstructed
> + state", and "multi-segment lifetimes" are concepts that don't appear
> + anywhere in the standard;
>
> But they seem to be implied by a strict interpretation of the scoping
> rules.

Then perhaps the interpretation shouldn't be so strict. I find it hard
to believe that these concepts were intended in the standard. Nowhere
in the standard or anything I've ever read about the history of C++
suggests that resurrection was ever intended to be a part of the
language.

> + If the authors
> + of the standard intended these ideas to be part of C++, don't you
> + think they would have said something about them, rather than having
> + them be something about which you must read between the lines?
>
> There was no conflict between mono-segmented lifetimes and the
> scoping rules until they added placement-new, at which point
> the conflict probably went unnoticed.

In other words, "bringing an object back to life", "object in a
deconstructed state", and "multi-segment lifetimes" aren't part of
C++.

> + void F()
> + {
> +   Widget* p = new Widget();
> +
> +   p->~Widget();
> +   new (p) Widget();
> + }
> +
> + If I'm understanding your viewpoint, it's the fact that in previous
> + examples "w" had to refer to the same entity throughout its scope that
> + implied resurrection. Here, scoping is not an issue, since the Widget
> + is not statically scoped. So it seems that this is not an example of
> + resurrection. If it's not resurrection, what is it?
>
> Of course the name "p" must refer to the same pointer object, but I
> find nothing in the Standard that implies that this pointer must point
> to the same object at the end of the function.

Then what do you think of this:

void F(Widget* p)
{
   p->~Widget();
   new (p) Widget();
}

void G()
{
   Widget w;

   F(&w);
}

void H()
{
   Widget* w = new Widget();

   F(w);
}

So is F() resurrecting a Widget or not? If I'm understanding your
interpretation correctly, then when called from G(), yes, but when
called from H(), no. This troubles me because we can't really say what
F() does without knowing what its callers are doing. Whether the
object pointed at by p is resurrected or not cannot be determined by
looking at F() alone.

> +> We can tell students either that
> +>
> +>   The single occurrence of w in main refers to the Widget most recently
> +>   created at &w if its still alive, because that's the way it is.
> +>
> +> or that
> +>
> +>   The call to w's destructor destroy w and the call to placement-new
> +>   reconstructs it again.  (Imagine reincarnation.)
> +>
> +> IMHO, they'll understand the latter a lot easier.
> +
> + IMHO, the former is a lot easier to understand,
>
> So, it's pretty much a matter of taste.

You skipped the part about consequent reasoning. For example, the
concept of identity is defined at least two ways according to your
view: one way, using the static scoping rules, and another way for
dynamically allocated objects.

I would not say this:

> The single occurrence of w in main refers to the Widget most recently
> created at &w if its still alive, because that's the way it is.

because it seems to contain the phrase "because that's the way it is"
for no reason other than to stimulate a bias against this statement in
the reader. Instead I would say something like

> The name w refers to the Widget that was most recently created at &w,
> because constructors and destructors control object identity.

Note that this way, there is only one definition of identity: it
begins with constructor execution and ends with destructor execution,
regardless of whether the object is a local variable, a static object,
or allocated dynamically.

Maybe it is a matter of taste, but I'd rather avoid special cases.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 18 Nov 2003 05:20:07 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bp2v69$gvc$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + I'm saying that in the example I gave above, in the line "w.x = 10;" w
+> + clearly isn't naming the Widget that is constructed in the first line
+> + of the function. Therefore, static scoping can't be the only factor
+> + determining object identity.
+>
+> The name "w" refers to the "same" now-destructed object, and that line
+> invokes undefined behavior.
+
+ I'm not sure, but it sounds like you agree; because the object has
+ been destroyed, and it's lifetime has ended, static scope is not the
+ only factor determining object identity.

I'm going by the fact that the Standard states very explicit that:
"... before the lifetime of an object starts and after its lifetime
ends there are significant restrictions on the use of the object ..."
[3.8#3]

+> + Further, "bringing an object back to life", "object in a deconstructed
+> + state", and "multi-segment lifetimes" are concepts that don't appear
+> + anywhere in the standard;
+>
+> But they seem to be implied by a strict interpretation of the scoping
+> rules.
+
+ Then perhaps the interpretation shouldn't be so strict. I find it hard
+ to believe that these concepts were intended in the standard. Nowhere
+ in the standard or anything I've ever read about the history of C++
+ suggests that resurrection was ever intended to be a part of the
+ language.

Can you believe that it was intended that all occurrences of a name
within the scope of its declaration refer to the same entity?

+> + If the authors
+> + of the standard intended these ideas to be part of C++, don't you
+> + think they would have said something about them, rather than having
+> + them be something about which you must read between the lines?
+>
+> There was no conflict between mono-segmented lifetimes and the
+> scoping rules until they added placement-new, at which point
+> the conflict probably went unnoticed.
+
+ In other words, "bringing an object back to life", "object in a
+ deconstructed state", and "multi-segment lifetimes" aren't part of
+ C++.

That doesn't follow.

+> + void F()
+> + {
+> +   Widget* p = new Widget();
+> +
+> +   p->~Widget();
+> +   new (p) Widget();
+> + }
+> +
+> + If I'm understanding your viewpoint, it's the fact that in previous
+> + examples "w" had to refer to the same entity throughout its scope that
+> + implied resurrection. Here, scoping is not an issue, since the Widget
+> + is not statically scoped. So it seems that this is not an example of
+> + resurrection. If it's not resurrection, what is it?
+>
+> Of course the name "p" must refer to the same pointer object, but I
+> find nothing in the Standard that implies that this pointer must point
+> to the same object at the end of the function.
+
+ Then what do you think of this:
+
+ void F(Widget* p)
+ {
+   p->~Widget();
+   new (p) Widget();
+ }
+
+ void G()
+ {
+   Widget w;
+
+   F(&w);
+ }
+
+ void H()
+ {
+   Widget* w = new Widget();
+
+   F(w);
+ }
+
+ So is F() resurrecting a Widget or not? If I'm understanding your
+ interpretation correctly, then when called from G(), yes, but when
+ called from H(), no.

The the wording of the Standard entails "yes" in the first case.
AFAIK, there is nothing that entails "yes" or that entails "no" in the
second case.

+ This troubles me because we can't really say what
+ F() does without knowing what its callers are doing. Whether the
+ object pointed at by p is resurrected or not cannot be determined by
+ looking at F() alone.

So far as I can tell, it would be consistent to say "yes" in both
cases.

+> +> We can tell students either that
+> +>
+> +>   The single occurrence of w in main refers to the Widget most recently
+> +>   created at &w if its still alive, because that's the way it is.
+> +>
+> +> or that
+> +>
+> +>   The call to w's destructor destroy w and the call to placement-new
+> +>   reconstructs it again.  (Imagine reincarnation.)
+> +>
+> +> IMHO, they'll understand the latter a lot easier.
+> +
+> + IMHO, the former is a lot easier to understand,
+>
+> So, it's pretty much a matter of taste.
+
+ You skipped the part about consequent reasoning. For example, the
+ concept of identity is defined at least two ways according to your
+ view: one way, using the static scoping rules, and another way for
+ dynamically allocated objects.
+
+ I would not say this:
+
+> The single occurrence of w in main refers to the Widget most recently
+> created at &w if its still alive, because that's the way it is.
+
+ because it seems to contain the phrase "because that's the way it is"
+ for no reason other than to stimulate a bias against this statement in
+ the reader. Instead I would say something like
+
+> The name w refers to the Widget that was most recently created at &w,
+> because constructors and destructors control object identity.

AFAIK, "identity" is not a concept that the Standard uses, except
implicitly when it uses the word "same".  The above quote from 3.8#3
and other clauses make it clear that in some cases the Standard
defines lifetimes in terms of allocation and deallocation rather than
construction and destruction, e.g.:

  ... the lifetime of an array object or of an object of type (3.9)
  starts as soon as storage with proper size and alignment is
  obtained, and its lifetime ends when the storage whic the array or
  object occupied is reused or released.                     [3.8#2]

+ Note that this way, there is only one definition of identity: it
+ begins with constructor execution and ends with destructor execution,
+ regardless of whether the object is a local variable, a static object,
+ or allocated dynamically.

Given that the concept of object has always been that:

  An object is a region of storage.  [1.8#1]

it might be better to stick to the allocation/deallocation notion
of identity.

+ Maybe it is a matter of taste, but I'd rather avoid special cases.

We already have an as-if rule for conforming implementations.  Let's
devise an as-if rule for conforming metaphors: if conforming programs
must behave per that metaphor, then the metaphor conforms.  That way
we can both be right.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Fri, 7 Nov 2003 06:42:42 +0000 (UTC)
Raw View
repost

thp@cs.ucr.edu wrote in message news:<bnvgjn$783$2@glue.ucr.edu>...
> johnchx <johnchx2@yahoo.com> wrote:
> + usenet@nmhq.net (Niklas Matthies) wrote
> +> The point is that when you have
> +>
> +>    int i;
> +>    int & r1 = i;
> +>    int & r2 = i;
> +>
> +> you want to distinguish between (a) the thingies called 'r1' and 'r2'
> +> and (b) the identity of the object they reference. In the example
> +> above, 'r1' and 'r2' are two distinct thingies which happen to
> +> reference the same object.
> +
> + r1 and r2 are names.  They name exactly the same object that i names.
> + They do *not* name some mysterious thingie(s).  Honest!
>
> Consider:
>
>   class Widget {
>     int& r;
>     Widget(int& i) r(i) {}
>   };
>
> Whatever r names at compile time isn't an int.  Whatever r names at
> load time isn't an int.  At some point, the entity that r names, which
> is commonly called a "reference", gets bound to an int object, but it
> can later get bound to a different int object.  Honest.

No it can't. Honest. (It's nice that we're all being honest with each
other. ;-)

Perhaps you're referring to the discussion going on in the "No subject
given" thread.

class Widget {
   public:
      // other constructors ommitted for brevity
      Widget(const Widget&);
      Widget& operator=(const Widget&);
   private:
      int x;
      int& r;
};

Widget::Widget(const Widget& src) :
   x(src.x),
   r(src.r)
{
}

Widget& Widget::operator=(const Widget rhs)
{
   if (this != &rhs) {
      this->~Widget();
      new (this) Widget(rhs);
   }
   return *this;
}

This operator= no more reseats r than it reassigns x. One Widget is
destroyed and a different one is created in its place. It may look
like reseating, but no reseating takes place. If you think it does,
could you indicate the line where it happens?

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 7 Nov 2003 20:18:30 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bnvg7m$783$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> [....]
+> + Note that this distinction exists for objects. For example, there are
+> + operations that apply to an int (like taking its address) and
+> + operations that apply to its value (like addition).
+>
+> The function  int f(){return 3;}  returns an int.  You can't take the
+> return-value's address, and it is its own value.
+
+ That's interesting, and true, but I don't see the relevance. We were
+ discussing whether or not it makes sense to distinguish references
+ from "reference values". The point I made above is that I can make a
+ distinction between ints and int values based on the things I can do
+ with one or the other. Your example shows that the line is not as
+ neatly drawn as I made it seem, but your example doesn't disprove my
+ point. I can still take the address of an int object, but not the
+ address of an int value; thus it makes sense to talk about ints and
+ int values. Do you disagree with this?

It seems that "int" is an ambiguous term that gets applied both to int
objects and to int values.  IMHO, it's unfortunate that C/C++ doesn't
treat these as distinct type.

+ I'm unaware of any distinction between a reference and its "value";
+ there are no operations that apply to one but not the other.

Initialization is an operation on the reference itself rather than its
referent.

+ This is
+ the question I posed in the previous post, and the one that would
+ decide the issue for me.

After initialization, by definition, the reference refers all
operations to its referent.  Nevertheless

  - Others showed how (in a very special case) to change the value,
    i.e., referent, of a reference.

  - We can indirectly determine the size of a reference:

      class Widget {
        int& r;
      };
      ...
      sizeof(Widget);

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 7 Nov 2003 21:03:11 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<boarh4$s6j$1@glue.ucr.edu>...
+> Consider:
+>
+>     #include<new>
+>     #include<iostream>
+>     class Widget {
+>     public:
+>       int& r;
+>       Widget( int& i ) : r( i ) {}
+>       void reseat( int& i ) {
+>         this->~Widget() ;
+>         new( this ) Widget( i ) ;
+>       }
+>       Widget& operator=( Widget const& other ) {
+>         if ( this != &other ) {
+>           this->~Widget() ;
+>           new ( this ) Widget( other ) ;
+>         }
+>         return *this ;
+>       }
+>     } ;
+>
+>     int main() {
+>       int i, j;
+>       Widget w1(i);
+>       Widget w2(j);
+>       assert( &w1.r == &i );
+>       w1 = w2;                 // change of state or new lifetime?
+>       assert( &w1.r == &j );
+>     }
+>
+> One can take the view that w1's reference member has two lifetimes and
+> gets re-initialized by the copy constructor at the beginning of its
+> second lifetime
+
+ This view is correct.

Not quite.  The view that "r" names the referent and not the reference
conflicts with the first line of 3.3:

   Every name is introduced in some portion of program text called a
   declarative region, which is the largest part of the program in
   which that name is valid, that is, in which that name may be used
   as an unqualified name to refer to the same entity.

Specifically, the body of the definition of operator= is within the
declarative region of the declaration of r, so the name r may not
refer to two different entities within that region.  But that
reference has a different referents at beginning and end of the body
of the if statement.

AFAIK, names are supposed to acquire their denotation at compile time,
but referents aren't generally known until run time.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Sat, 8 Nov 2003 02:57:52 +0000 (UTC)
Raw View
>   - We can indirectly determine the size of a reference:
>
>       class Widget {
>         int& r;
>       };
>       ...
>       sizeof(Widget);

This doesn't necessarily work, as Widget might have padding.  Would you
be surprised when this assertion fired:

class Widget2 {int &r, &s; };
assert(sizeof Widget!=sizeof Widget2);

Adam Peterson

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sat, 8 Nov 2003 02:59:44 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bog70o$ctr$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + thp@cs.ucr.edu wrote in message news:<boarh4$s6j$1@glue.ucr.edu>...
> +> Consider:
> +>
> +>     #include<new>
> +>     #include<iostream>
> +>     class Widget {
> +>     public:
> +>       int& r;
> +>       Widget( int& i ) : r( i ) {}
> +>       void reseat( int& i ) {
> +>         this->~Widget() ;
> +>         new( this ) Widget( i ) ;
> +>       }
> +>       Widget& operator=( Widget const& other ) {
> +>         if ( this != &other ) {
> +>           this->~Widget() ;
> +>           new ( this ) Widget( other ) ;
> +>         }
> +>         return *this ;
> +>       }
> +>     } ;
> +>
> +>     int main() {
> +>       int i, j;
> +>       Widget w1(i);
> +>       Widget w2(j);
> +>       assert( &w1.r == &i );
> +>       w1 = w2;                 // change of state or new lifetime?
> +>       assert( &w1.r == &j );
> +>     }
> +>
> +> One can take the view that w1's reference member has two lifetimes and
> +> gets re-initialized by the copy constructor at the beginning of its
> +> second lifetime
> +
> + This view is correct.
>
> Not quite.  The view that "r" names the referent and not the reference
> conflicts with the first line of 3.3:
>
>    Every name is introduced in some portion of program text called a
>    declarative region, which is the largest part of the program in
>    which that name is valid, that is, in which that name may be used
>    as an unqualified name to refer to the same entity.
>
> Specifically, the body of the definition of operator= is within the
> declarative region of the declaration of r, so the name r may not
> refer to two different entities within that region.  But that
> reference has a different referents at beginning and end of the body
> of the if statement.

It seems pretty obvious to me that the phrase "largest part of the
program in which that name is valid" must mean that the declarative
region must end at the point at which the destructor executes; after
the destructor of w executes, w.r is no longer valid.

class Widget {
   int& r;
   int x;
   Bar y;
};

void F()
{
   Widget w;

   w.~Widget();

   // at this point, w, w.r, w.x, and w.y are all invalid.

}

Either the declarative region ended with the destructor call above, or
"declarative region" has no meaning in discussing liftime issues.

It's inescapable: once a destructor of an object executes, that
object's lifetime (and the lifetimes of all of its parts) ends. To
claim otherwise is to go against one of the foundations of C++.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sat, 8 Nov 2003 18:52:20 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bogb49$du1$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + I'm unaware of any distinction between a reference and its "value";
> + there are no operations that apply to one but not the other.
>
> Initialization is an operation on the reference itself rather than its
> referent.

The claim was that "reference value" was something other than the
reference, and something other than the referent (by which I mean the
object that the reference refers to).

Actually I need to qualify my claim; there are many operations that
apply to a reference that don't apply to a reference value, since
reference values don't exist. So can you suggest an operation that
applies to a "reference value" but not to a reference?

> + This is
> + the question I posed in the previous post, and the one that would
> + decide the issue for me.
>
> After initialization, by definition, the reference refers all
> operations to its referent.  Nevertheless
>
>   - Others showed how (in a very special case) to change the value,
>     i.e., referent, of a reference.

No one has shown how to change the value of a reference. There have
been examples of destroying references and recreating new ones in the
same memory.

void G(Widget* w, int& r)
{
   w->~Widget();

   new (w) Widget(r);
}

void F()
{
   int x, y;
   Widget*  w = new Widget(x);

   G(w, y);
}

Do you think this changes w->r? I don't. Even if G() is really called
operator=().

>   - We can indirectly determine the size of a reference:
>
>       class Widget {
>         int& r;
>       };
>       ...
>       sizeof(Widget);

There is nothing in the standard I'm aware of that supports the idea
that this somehow determines the size of a reference.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 8 Nov 2003 19:08:18 +0000 (UTC)
Raw View
"Adam H. Peterson" <ahp6@email.byu.edu> wrote:
+>   - We can indirectly determine the size of a reference:
+>
+>       class Widget {
+>         int& r;
+>       };
+>       ...
+>       sizeof(Widget);
+
+ This doesn't necessarily work, as Widget might have padding.  Would you
+ be surprised when this assertion fired:
+
+ class Widget2 {int &r, &s; };
+ assert(sizeof Widget!=sizeof Widget2);

AFAIK, the results of sizeof are implementation defined and are only
as honest and reasonable as the implementor chooses to make them.
Especially in the case of non-POD classes the implementor has great
leeway.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sat, 8 Nov 2003 19:09:22 +0000 (UTC)
Raw View
In article <c87c1cfb.0311071749.787a0737@posting.google.com>, Bob Bell
<belvis@pacbell.net> writes
>It seems pretty obvious to me that the phrase "largest part of the
>program in which that name is valid" must mean that the declarative
>region must end at the point at which the destructor executes; after
>the destructor of w executes, w.r is no longer valid.

I think you are confusing names with objects. A name may be valid (i.e.
the compiler must not reject it) even though the object it referred to
has ended its lifetime.

--
Francis Glassborow      ACCU
If you are not using up-to-date virus protection you should not be reading
this. Viruses do not just hurt the infected but the whole community.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 05:45:55 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bogb49$du1$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + I'm unaware of any distinction between a reference and its "value";
+> + there are no operations that apply to one but not the other.
+>
+> Initialization is an operation on the reference itself rather than its
+> referent.
+
+ The claim was that "reference value" was something other than the
+ reference, and something other than the referent (by which I mean the
+ object that the reference refers to).
+
+ Actually I need to qualify my claim; there are many operations that
+ apply to a reference that don't apply to a reference value, since
+ reference values don't exist. So can you suggest an operation that
+ applies to a "reference value" but not to a reference?

So, there are three supposedly distnct notions:

  - references, which supposedly get initialized with reference values
    at certain points.

  - reference values, which supposedly are returned by functions
    having reference return types.

  - referents, which supposedly are the things referred to by
    reference values.

Which of the three possible distinctions are accepted and which are
under question?

AFAIK, in Algol68, "reference" means exactly what C/C++ calls an
"object".  What C++ calls a "reference" would be called an
"object-valued object", i.e., a "reference to a reference".  Thus, f
would not be said to "return a reference to x" but rather to "return
x".  In other words, there is no distinction between "reference value"
and "referent".  (Reference-to-referent conversion is then a special
case of lvalue-to-rvalue converson.)

The general C++ paradigm seems to be that the return value of a
T-returning function is a "T-value".  And, an expression involving a
call to a T&-returning function has its type immediately "adjusted to
'T'":

  If an expression initially has the type "reference to T" (8.3.2,
  8.5.3), the type is adjusted to "T" prior to any further analysis,
  the expression designates the object or function denoted by the
  reference, and the expression is an lvalue.         [5#5, p. 63]

That adjustment wouldn't be needed if we adopted the proposal that, by
convention, T-valued objects have type T&.

+> + This is
+> + the question I posed in the previous post, and the one that would
+> + decide the issue for me.
+>
+> After initialization, by definition, the reference refers all
+> operations to its referent.  Nevertheless
+>
+>   - Others showed how (in a very special case) to change the value,
+>     i.e., referent, of a reference.
+
+ No one has shown how to change the value of a reference. There have
+ been examples of destroying references and recreating new ones in the
+ same memory.
+
+ void G(Widget* w, int& r)
+ {
+   w->~Widget();
+
+   new (w) Widget(r);
+ }
+
+ void F()
+ {
+   int x, y;
+   Widget*  w = new Widget(x);
+
+   G(w, y);
+ }

+ Do you think this changes w->r? I don't. Even if G() is really called
+ operator=().

Per the definitions of "declarative region", w denotes the same Widget
(having the same reference member) both before and after the execution
of G.

+>   - We can indirectly determine the size of a reference:
+>
+>       class Widget {
+>         int& r;
+>       };
+>       ...
+>       sizeof(Widget);
+
+ There is nothing in the standard I'm aware of that supports the idea
+ that this somehow determines the size of a reference.

That's why I said "indirectly".  This the size of a struct whose only
part is a refernece.

In any case, per the as-if rule,sizeof can return whatever the
implementor chooses to say about the sizes of things.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 06:04:43 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bog70o$ctr$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + thp@cs.ucr.edu wrote in message news:<boarh4$s6j$1@glue.ucr.edu>...
+> +> Consider:
+> +>
+> +>     #include<new>
+> +>     #include<iostream>
+> +>     class Widget {
+> +>     public:
+> +>       int& r;
+> +>       Widget( int& i ) : r( i ) {}
+> +>       void reseat( int& i ) {
+> +>         this->~Widget() ;
+> +>         new( this ) Widget( i ) ;
+> +>       }
+> +>       Widget& operator=( Widget const& other ) {
+> +>         if ( this != &other ) {
+> +>           this->~Widget() ;
+> +>           new ( this ) Widget( other ) ;
+> +>         }
+> +>         return *this ;
+> +>       }
+> +>     } ;
+> +>
+> +>     int main() {
+> +>       int i, j;
+> +>       Widget w1(i);
+> +>       Widget w2(j);
+> +>       assert( &w1.r == &i );
+> +>       w1 = w2;                 // change of state or new lifetime?
+> +>       assert( &w1.r == &j );
+> +>     }
+> +>
+> +> One can take the view that w1's reference member has two lifetimes and
+> +> gets re-initialized by the copy constructor at the beginning of its
+> +> second lifetime
+> +
+> + This view is correct.
+>
+> Not quite.  The view that "r" names the referent and not the reference
+> conflicts with the first line of 3.3:
+>
+>    Every name is introduced in some portion of program text called a
+>    declarative region, which is the largest part of the program in
+>    which that name is valid, that is, in which that name may be used
+>    as an unqualified name to refer to the same entity.
+>
+> Specifically, the body of the definition of operator= is within the
+> declarative region of the declaration of r, so the name r may not
+> refer to two different entities within that region.  But that
+> reference has a different referents at beginning and end of the body
+> of the if statement.
+
+ It seems pretty obvious to me that the phrase "largest part of the
+ program in which that name is valid" must mean that the declarative
+ region must end at the point at which the destructor executes; after
+ the destructor of w executes, w.r is no longer valid.
+
+ class Widget {
+   int& r;
+   int x;
+   Bar y;
+ };
+
+ void F()
+ {
+   Widget w;
+
+   w.~Widget();
+
+   // at this point, w, w.r, w.x, and w.y are all invalid.
+
+ }

I'm not sure what you mean by "invalid".  Any attempt to access those
objects at that point would invoke undefined behavior, but not a
compile-time diagnostic.  Consder:

    void F() {
      Widget w;
      if ( whatever() ) w.~Widget();
      // Now are w, w.r, w.x, and w.y "invalid" at this point.?
    }

+ Either the declarative region ended with the destructor call above, or
+ "declarative region" has no meaning in discussing liftime issues.

AFAIK, declarative region is a region of code ("part of the program"),
a static (compile-time) notion.  Lifetime is an interval of run time,
a dynamic (run-time) notion.  The two notions are orthogonal, except
for the fact that the lifetime of some objects ends when execution
leaves a certain region.  (There are dynamically scoped langauges, but
C++ is not one of them.)

+ It's inescapable: once a destructor of an object executes, that
+ object's lifetime (and the lifetimes of all of its parts) ends. To
+ claim otherwise is to go against one of the foundations of C++.

AFAIK, the destructor of a static or automatic object does not end the
object's lifetime but rather puts it into an "unconstructed" state
where accessing any part of the object invokes undefined behavior.
Placement-new can bring the object and its parts back from that state
with new "values" --- that includes parts having reference types.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 06:05:25 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bogb49$du1$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + I'm unaware of any distinction between a reference and its "value";
+> + there are no operations that apply to one but not the other.
+>
+> Initialization is an operation on the reference itself rather than its
+> referent.
+
+ The claim was that "reference value" was something other than the
+ reference, and something other than the referent (by which I mean the
+ object that the reference refers to).
+
+ Actually I need to qualify my claim; there are many operations that
+ apply to a reference that don't apply to a reference value, since
+ reference values don't exist. So can you suggest an operation that
+ applies to a "reference value" but not to a reference?

The general paradigm in C++ is that a T-returning function returns
T-values:

   The type of the function call expression is the return type of the
   statically chosen function ... The type shall be a complete object
   type, reference type or the type void.                   [5.2.5#3]

So, if f is declared "int& f(){return *new int;}", then
"f()" is a int&-valued expression, which gets adjusted to an
int-valued expression:

   If an expression initially has the type "reference to T" (8.3.2,
   8.4.3), the type is adjusted to "T" prior to any further analysis,
   the expression designates the object or function denoted by the
   reference, and the expression is an lvalue.                  [5#6]

But its pre-adjustment value is an int& value.

+> + This is
+> + the question I posed in the previous post, and the one that would
+> + decide the issue for me.
+>
+> After initialization, by definition, the reference refers all
+> operations to its referent.  Nevertheless
+>
+>   - Others showed how (in a very special case) to change the value,
+>     i.e., referent, of a reference.
+
+ No one has shown how to change the value of a reference. There have
+ been examples of destroying references and recreating new ones in the
+ same memory.
+
+ void G(Widget* w, int& r)
+ {
+   w->~Widget();
+
+   new (w) Widget(r);
+ }
+
+ void F()
+ {
+   int x, y;
+   Widget*  w = new Widget(x);
+
+   G(w, y);
+ }
+
+ Do you think this changes w->r? I don't. Even if G() is really called
+ operator=().
+
+>   - We can indirectly determine the size of a reference:
+>
+>       class Widget {
+>         int& r;
+>       };
+>       ...
+>       sizeof(Widget);

Per the definitions of "scope" and "declarative region", the name "w"
refers to the same object both before and after the evaluation of
"G(w,y)".

+ There is nothing in the standard I'm aware of that supports the idea
+ that this somehow determines the size of a reference.

The accuracy of sizeof is a quality-of-implementation matter.  Per the
Standard (via the as-if rule), sizeof can return pretty much whatever
the implementor(s) choose.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 17:01:11 +0000 (UTC)
Raw View
My apologies for the double follow up.  My news client said that the
first had not gotten "appended" because no lock was available in the
mail system (whatever that means).  Moreover, my system administrator
could find no trace of it being sent.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 17:01:11 +0000 (UTC)
Raw View
Niklas Matthies <usenet@nmhq.net> wrote:
+ On 2003-11-01 00:28, johnchx wrote:
+> usenet@nmhq.net (Niklas Matthies) wrote
+>> The point is that when you have
+>>
+>>    int i;
+>>    int & r1 = i;
+>>    int & r2 = i;
+>>
+>> you want to distinguish between (a) the thingies called 'r1' and 'r2'
+>> and (b) the identity of the object they reference. In the example
+>> above, 'r1' and 'r2' are two distinct thingies which happen to
+>> reference the same object.
+>
+> r1 and r2 are names.  They name exactly the same object that i names.
+> They do *not* name some mysterious thingie(s).  Honest!
+
+ Seeing it this way would make sense if references were always named.
+ But as function returns, we have unnamed references, which means that
+ references are things in their own right, neither names nor objects.
+ So if you want to treat named and unnamed references uniformly, then
+ r1 and r2 have to be considered as naming references-to-objects, not
+ as naming objects.

Agreed.  To underline that consider:

  Widget w;
  Widget& r;
  Widget* p;
  w.~Widget();
  new(p) Widget();

Now r refers to the "same" Widget as at its declaration. which now is
the new Widget that overlayed w.  Go figger!

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 9 Nov 2003 18:37:08 +0000 (UTC)
Raw View
In article <boilsk$3dd$1@glue.ucr.edu>, thp@cs.ucr.edu writes
>AFAIK, the destructor of a static or automatic object does not end the
>object's lifetime but rather puts it into an "unconstructed" state
>where accessing any part of the object invokes undefined behavior.
>Placement-new can bring the object and its parts back from that state
>with new "values" --- that includes parts having reference types.

Did you mean an explicitly called dtor rather than the normal dtor that
the compiler codes for the end of and automatic or static objects
lifetime?


--
Francis Glassborow      ACCU
If you are not using up-to-date virus protection you should not be reading
this. Viruses do not just hurt the infected but the whole community.


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 18:37:46 +0000 (UTC)
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
+ In article <c87c1cfb.0311071749.787a0737@posting.google.com>, Bob Bell
+ <belvis@pacbell.net> writes
+>It seems pretty obvious to me that the phrase "largest part of the
+>program in which that name is valid" must mean that the declarative
+>region must end at the point at which the destructor executes; after
+>the destructor of w executes, w.r is no longer valid.
+
+ I think you are confusing names with objects. A name may be valid (i.e.
+ the compiler must not reject it) even though the object it referred to
+ has ended its lifetime.

I've always understood that (per the definition of scope), within the
scope of a given name, all occurrences of that name refer to the same
entity.  So, after an object's destruction, its name refers to the
ghost of the destructed object, and any use of that name invokes nasal
demons.  But, after a subsequent placement-new (of appropriate type)
at the old location, the name refers to the resurrected object, and
demons go away.  Right?

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 9 Nov 2003 18:38:45 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<boilsk$3dd$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + Either the declarative region ended with the destructor call above, or
> + "declarative region" has no meaning in discussing liftime issues.
>
> AFAIK, declarative region is a region of code ("part of the program"),
> a static (compile-time) notion.  Lifetime is an interval of run time,
> a dynamic (run-time) notion.  The two notions are orthogonal, except
> for the fact that the lifetime of some objects ends when execution
> leaves a certain region.  (There are dynamically scoped langauges, but
> C++ is not one of them.)

We were discussing lifetimes. Since declarative region is orthogonal
to lifetime issues, it was a red herring. My mistaken impressions of
declarative region aside, it seems that declarative region doesn't
have anything to say one way or the other about this statement:

> +> +> One can take the view that w1's reference member has two lifetimes and
> +> +> gets re-initialized by the copy constructor at the beginning of its
> +> +> second lifetime

So when I said

> +> + This view is correct.

I was correct.

> + It's inescapable: once a destructor of an object executes, that
> + object's lifetime (and the lifetimes of all of its parts) ends. To
> + claim otherwise is to go against one of the foundations of C++.
>
> AFAIK, the destructor of a static or automatic object does not end the
> object's lifetime but rather puts it into an "unconstructed" state
> where accessing any part of the object invokes undefined behavior.
> Placement-new can bring the object and its parts back from that state
> with new "values" --- that includes parts having reference types.

Untrue. Once a destructor executes, you have a region of memory,
nothing more; there is no object at all. When the constructor
executes, you turn a region of memory into a brand new object, not the
old object "brought back to life." Consider:

class Foo {
   public:
      void* operator new(size_t);
      operator delete(void*);
};

void* Foo::operator new(size_t size)
{
   static char sData[sizeof(Foo)];

   return &sData[0];
}

void Foo::operator delete(void*)
{
}

void F()
{
   Foo* f = new Foo();

   delete f;

   f = new Foo();
}

This isn't a particularly useful operator new and delete, but it
suffices for this example. I know that the two calls to operator new
will return the same region of memory.

Just because the same region of memory is used for both new calls
doesn't mean the first Foo was brought back to life, or that the first
object somehow continued to exist in an unconstructed state.

This particular example may not be strictly conforming, but that's
besides the point in this case; even with the default operators new
and delete, it's possible that the two new calls in F() could return
the same region of memory.

This was a point I made early on in the discussion: identity (and
consequently lifetime) has nothing to do with address. Identity in C++
is established by the execution of a constructor, and is taken away by
execution of the destructor.

Once an object's destructor executes, that object's lifetime ends.
There is no such thing as an "object in an unconstructed state"; there
are objects, and there are regions of memory.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 9 Nov 2003 18:39:56 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bokd1p$h22$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + thp@cs.ucr.edu wrote in message news:<bogb49$du1$1@glue.ucr.edu>...
> +> Bob Bell <belvis@pacbell.net> wrote:
> +> + I'm unaware of any distinction between a reference and its "value";
> +> + there are no operations that apply to one but not the other.
> +>
> +> Initialization is an operation on the reference itself rather than its
> +> referent.
> +
> + The claim was that "reference value" was something other than the
> + reference, and something other than the referent (by which I mean the
> + object that the reference refers to).
> +
> + Actually I need to qualify my claim; there are many operations that
> + apply to a reference that don't apply to a reference value, since
> + reference values don't exist. So can you suggest an operation that
> + applies to a "reference value" but not to a reference?
>
> So, there are three supposedly distnct notions:
>
>   - references, which supposedly get initialized with reference values
>     at certain points.
>
>   - reference values, which supposedly are returned by functions
>     having reference return types.
>
>   - referents, which supposedly are the things referred to by
>     reference values.
>
> Which of the three possible distinctions are accepted and which are
> under question?

All are objectionable, since they all use the term "reference value".

I would use say something more like this:

-- references, which get initialized with objects
-- referents, the objects referred to by references

As far as I know, these concepts are completely consistent with the
way references are defined and used in C++. No "reference value"
concept is implied or needed.

> AFAIK, in Algol68, "reference" means exactly what C/C++ calls an
> "object".  What C++ calls a "reference" would be called an
> "object-valued object", i.e., a "reference to a reference".  Thus, f
> would not be said to "return a reference to x" but rather to "return
> x".  In other words, there is no distinction between "reference value"
> and "referent".  (Reference-to-referent conversion is then a special
> case of lvalue-to-rvalue converson.)
>
> The general C++ paradigm seems to be that the return value of a
> T-returning function is a "T-value".  And, an expression involving a
> call to a T&-returning function has its type immediately "adjusted to
> 'T'":
>
>   If an expression initially has the type "reference to T" (8.3.2,
>   8.5.3), the type is adjusted to "T" prior to any further analysis,
>   the expression designates the object or function denoted by the
>   reference, and the expression is an lvalue.         [5#5, p. 63]
>
> That adjustment wouldn't be needed if we adopted the proposal that, by
> convention, T-valued objects have type T&.

But we haven't adopted that proposal, the adjustment is needed, and
what does this have to do with reference values anyway?

> +> + This is
> +> + the question I posed in the previous post, and the one that would
> +> + decide the issue for me.
> +>
> +> After initialization, by definition, the reference refers all
> +> operations to its referent.  Nevertheless
> +>
> +>   - Others showed how (in a very special case) to change the value,
> +>     i.e., referent, of a reference.
> +
> + No one has shown how to change the value of a reference. There have
> + been examples of destroying references and recreating new ones in the
> + same memory.
> +
> + void G(Widget* w, int& r)
> + {
> +   w->~Widget();
> +
> +   new (w) Widget(r);
> + }
> +
> + void F()
> + {
> +   int x, y;
> +   Widget*  w = new Widget(x);
> +
> +   G(w, y);
> + }
>
> + Do you think this changes w->r? I don't. Even if G() is really called
> + operator=().
>
> Per the definitions of "declarative region", w denotes the same Widget
> (having the same reference member) both before and after the execution
> of G.

I don't think so. My newfound understanding of declarative region
tells me that w denotes the same _pointer object_; what it points to
is a dynamic issue and is not affected by static concepts like
declarative region.

In this case, one Widget's lifetime ends and a new one begins. Both
Widget happen to use the same storage, so w continues to point to a
Widget. This is not really any different from:

void F()
{
   Widget*  w = new Widget();

   delete w;

   w = new Widget();
}

It's entirely possible that the same address is returned, so that w's
value doesn't change. So what? It's still two Widgets.

It sounds like you're confusing address with identity; identity is not
defined by address.

> +>   - We can indirectly determine the size of a reference:
> +>
> +>       class Widget {
> +>         int& r;
> +>       };
> +>       ...
> +>       sizeof(Widget);
> +
> + There is nothing in the standard I'm aware of that supports the idea
> + that this somehow determines the size of a reference.
>
> That's why I said "indirectly".  This the size of a struct whose only
> part is a refernece.

It may not be the only part. The implementation is allowed to put in
any padding or hidden members it wants.

> In any case, per the as-if rule,sizeof can return whatever the
> implementor chooses to say about the sizes of things.

In other words, after evaluating sizeof(Widget) above you still don't
know how big a reference is.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 9 Nov 2003 19:01:13 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ repost
+
+ thp@cs.ucr.edu wrote in message news:<bnvgjn$783$2@glue.ucr.edu>...
+> johnchx <johnchx2@yahoo.com> wrote:
+> + usenet@nmhq.net (Niklas Matthies) wrote
+> +> The point is that when you have
+> +>
+> +>    int i;
+> +>    int & r1 = i;
+> +>    int & r2 = i;
+> +>
+> +> you want to distinguish between (a) the thingies called 'r1' and 'r2'
+> +> and (b) the identity of the object they reference. In the example
+> +> above, 'r1' and 'r2' are two distinct thingies which happen to
+> +> reference the same object.
+> +
+> + r1 and r2 are names.  They name exactly the same object that i names.
+> + They do *not* name some mysterious thingie(s).  Honest!
+>
+> Consider:
+>
+>   class Widget {
+>     int& r;
+>     Widget(int& i) r(i) {}
+>   };
+>
+> Whatever r names at compile time isn't an int.  Whatever r names at
+> load time isn't an int.  At some point, the entity that r names, which
+> is commonly called a "reference", gets bound to an int object, but it
+> can later get bound to a different int object.  Honest.
+
+ No it can't. Honest. (It's nice that we're all being honest with each
+ other. ;-)
+
+ Perhaps you're referring to the discussion going on in the "No subject
+ given" thread.
+
+ class Widget {
+   public:
+      // other constructors ommitted for brevity
+      Widget(const Widget&);
+      Widget& operator=(const Widget&);
+   private:
+      int x;
+      int& r;
+ };
+
+ Widget::Widget(const Widget& src) :
+   x(src.x),
+   r(src.r)
+ {
+ }
+
+ Widget& Widget::operator=(const Widget rhs)
+ {
+   if (this != &rhs) {
+      this->~Widget();
+      new (this) Widget(rhs);
+   }
+   return *this;
+ }
+
+ This operator= no more reseats r than it reassigns x. One Widget is
+ destroyed and a different one is created in its place. It may look
+ like reseating, but no reseating takes place. If you think it does,
+ could you indicate the line where it happens?

Let's make x and y public and add the constructor:

  Widget(int xx, int& rr) : x(xx), r(rr) {}

Then consider:

   int i, j;
   Widget w1(1,i);
   Widget w2(2,j);
   assert( w1.x == 1 && &w1.r == &i );
   w1 = w2;
   assert( w1.x == 2 && &w1.r == &j );

Within its scope the name "w1" always refers to the same entity
(3.3#1) having the same members.  More specifically, after

   Widget::Widget(const Widget& src) :
     x(src.x),
     r(src.r)
   {
   }

executes, the names "x" and "r" still "refer" to the same reference
and int members of the same Widget.  But, that reference now "denotes"
the int object j.  So, the expression "w1.r" now "designates" j:

   If an expression initially has the type "reference to T" (8.3.2,
   8.4.3), the type is adjusted to "T" prior to any further analysis,
   the expression designates the object or function denoted by the
   reference, and the expression is an lvalue.                  [5#6]

Presumably by the phrase "the reference", 5#6 means the reference
value of the unadjusted expression.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 10 Nov 2003 00:37:09 CST
Raw View
thp@cs.ucr.edu wrote in message news:<bolgf3$pub$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + class Widget {
> +   public:
> +      // other constructors ommitted for brevity
> +      Widget(const Widget&);
> +      Widget& operator=(const Widget&);
> +   private:
> +      int x;
> +      int& r;
> + };
> +
> + Widget::Widget(const Widget& src) :
> +   x(src.x),
> +   r(src.r)
> + {
> + }
> +
> + Widget& Widget::operator=(const Widget rhs)
> + {
> +   if (this != &rhs) {
> +      this->~Widget();
> +      new (this) Widget(rhs);
> +   }
> +   return *this;
> + }
> +
> + This operator= no more reseats r than it reassigns x. One Widget is
> + destroyed and a different one is created in its place. It may look
> + like reseating, but no reseating takes place. If you think it does,
> + could you indicate the line where it happens?
>
> Let's make x and y public and add the constructor:
>
>   Widget(int xx, int& rr) : x(xx), r(rr) {}
>
> Then consider:
>
>    int i, j;
>    Widget w1(1,i);
>    Widget w2(2,j);
>    assert( w1.x == 1 && &w1.r == &i );
>    w1 = w2;
>    assert( w1.x == 2 && &w1.r == &j );
>
> Within its scope the name "w1" always refers to the same entity
> (3.3#1) having the same members.

void F()
{
   Widget w;

   w.~Widget();

   w.x = 10;
}

In the line "w.x = 10;", w is in scope. Does it still name the same
entity it named before the explicit destructor call? No. Scope isn't
everything.

When control enters a scope, it causes constructors to be called which
create the objects defined in that scope. When control leaves a scope,
it causes destructors to be called to destroy the objects in that
scope. But it's not the scope that controls the lifetimes of objects;
the lifetimes of objects are controlled by the calls to the
constructors and destructors. You can end an object's lifetime
prematurely by calling the destructor early, as above. Likewise, you
can use placement new to turn a range of memory into an object. For an
example of these things in action, study your implementation's
std::vector.

If you call the destructor of an object, in any context, either
explicitly or implicitly, that object is gone. Kaput. Bye bye.

> More specifically, after
>
>    Widget::Widget(const Widget& src) :
>      x(src.x),
>      r(src.r)
>    {
>    }
>
> executes, the names "x" and "r" still "refer" to the same reference
> and int members of the same Widget.

I don't understand the use of the word "still" here. Do you mean that
x and r were referring to something, and after the copy constructor
executes they still refer to something? That can't be right because
before the copy constructor, there was no object, so x and r didn't
exist.

> But, that reference now "denotes"
> the int object j.  So, the expression "w1.r" now "designates" j:
>
>    If an expression initially has the type "reference to T" (8.3.2,
>    8.4.3), the type is adjusted to "T" prior to any further analysis,
>    the expression designates the object or function denoted by the
>    reference, and the expression is an lvalue.                  [5#6]
>
> Presumably by the phrase "the reference", 5#6 means the reference
> value of the unadjusted expression.

That's a big presumption; the phrase "reference value" doesn't appear
anywhere in the standard as far as I know. I find it more likely that
the phrase "the reference" means "the reference". I still don't
understand the need to introduce this "reference value" concept when
standard C++ works just fine without it.

In any case, I'm not sure I understood if you answered my question. On
what line did the reseating take place?

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Mon, 10 Nov 2003 10:38:05 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bolisj$q39$1@glue.ucr.edu...

> I've always understood that (per the definition of scope), within the
> scope of a given name, all occurrences of that name refer to the same
> entity.

The name [used for an object] is an lvalue. That refers to a region of
storage where the object is set up by the compiler.  [As I said earlier a
reference works exactly the same way in this regard.]

In C++ normally the object and its name has the same lifetime.  As for local
objects where the name goes out of csope, the object too gets destructed.
For globals the object lives all the way. (settinf aside the well known
problems of trying to use it before construction during startup or after
destruction at exit.)

However you have that ability to call dtor explicitly to kill the object.
Then its lifetime ends, though the name is still usable.

> So, after an object's destruction, its name refers to the
> ghost of the destructed object, and any use of that name invokes nasal
> demons.

Unless I'm mistaken you can use the name as an lvalue. But if you enforce an
lvalue->rvalue conversion with a killed object you get UB.

There may be more restrictions, but you can use the name -- as it is used in
the placement-new expression.

I dunno what you mean by ghst here, I my terms the nema does not refer to a
valid (live) object. Though the storage is still there as no one ordered its
deallocation.

> But, after a subsequent placement-new (of appropriate type)
> at the old location, the name refers to the resurrected object, and
> demons go away.  Right?

It is not a resurrected object, you create a brand new fresh object.  It has
no relation to the object you recently destroyes.   And you can use the name
to use that new object -- if all the requirements on the recreation  (quoted
here from the standard recently) were observed.

There's no such thing as recreation of objects in C++, only creation, life
and destruction. (it's imho well summarized even in the standard, 'The C++
object model' section.)

Paul


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 10 Nov 2003 10:38:06 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bokd1p$h22$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + thp@cs.ucr.edu wrote in message news:<bogb49$du1$1@glue.ucr.edu>...
+> +> Bob Bell <belvis@pacbell.net> wrote:
+> +> + I'm unaware of any distinction between a reference and its "value";
+> +> + there are no operations that apply to one but not the other.
+> +>
+> +> Initialization is an operation on the reference itself rather than its
+> +> referent.
+> +
+> + The claim was that "reference value" was something other than the
+> + reference, and something other than the referent (by which I mean the
+> + object that the reference refers to).
+> +
+> + Actually I need to qualify my claim; there are many operations that
+> + apply to a reference that don't apply to a reference value, since
+> + reference values don't exist. So can you suggest an operation that
+> + applies to a "reference value" but not to a reference?
+>
+> So, there are three supposedly distnct notions:
+>
+>   - references, which supposedly get initialized with reference values
+>     at certain points.
+>
+>   - reference values, which supposedly are returned by functions
+>     having reference return types.
+>
+>   - referents, which supposedly are the things referred to by
+>     reference values.
+>
+> Which of the three possible distinctions are accepted and which are
+> under question?
+
+ All are objectionable, since they all use the term "reference value".
+
+ I would use say something more like this:
+
+ -- references, which get initialized with objects
+ -- referents, the objects referred to by references
+
+ As far as I know, these concepts are completely consistent with the
+ way references are defined and used in C++. No "reference value"
+ concept is implied or needed.

There's still the problem of what it is that a reference-valued
function returns.

+> AFAIK, in Algol68, "reference" means exactly what C/C++ calls an
+> "object".  What C++ calls a "reference" would be called an
+> "object-valued object", i.e., a "reference to a reference".  Thus, f
+> would not be said to "return a reference to x" but rather to "return
+> x".  In other words, there is no distinction between "reference value"
+> and "referent".  (Reference-to-referent conversion is then a special
+> case of lvalue-to-rvalue converson.)
+>
+> The general C++ paradigm seems to be that the return value of a
+> T-returning function is a "T-value".  And, an expression involving a
+> call to a T&-returning function has its type immediately "adjusted to
+> 'T'":
+>
+>   If an expression initially has the type "reference to T" (8.3.2,
+>   8.5.3), the type is adjusted to "T" prior to any further analysis,
+>   the expression designates the object or function denoted by the
+>   reference, and the expression is an lvalue.         [5#5, p. 63]
+>
+> That adjustment wouldn't be needed if we adopted the proposal that, by
+> convention, T-valued objects have type T&.
+
+ But we haven't adopted that proposal, the adjustment is needed, and
+ what does this have to do with reference values anyway?

If that proposal were adopted then the type of the return value of

   int& f() { return i; }

would be the same as the type of i.

+> +> + This is
+> +> + the question I posed in the previous post, and the one that would
+> +> + decide the issue for me.
+> +>
+> +> After initialization, by definition, the reference refers all
+> +> operations to its referent.  Nevertheless
+> +>
+> +>   - Others showed how (in a very special case) to change the value,
+> +>     i.e., referent, of a reference.
+> +
+> + No one has shown how to change the value of a reference. There have
+> + been examples of destroying references and recreating new ones in the
+> + same memory.
+> +
+> + void G(Widget* w, int& r)
+> + {
+> +   w->~Widget();
+> +
+> +   new (w) Widget(r);
+> + }
+> +
+> + void F()
+> + {
+> +   int x, y;
+> +   Widget*  w = new Widget(x);
+> +
+> +   G(w, y);
+> + }
+>
+> + Do you think this changes w->r? I don't. Even if G() is really called
+> + operator=().
+>
+> Per the definitions of "declarative region", w denotes the same Widget
+> (having the same reference member) both before and after the execution
+> of G.
+
+ I don't think so. My newfound understanding of declarative region
+ tells me that w denotes the same _pointer object_; what it points to
+ is a dynamic issue and is not affected by static concepts like
+ declarative region.

Huh?  Are you claiming that names of C++ variables refer don't refer
to the object in their definitions but rather to hidden pointers that
point to that object.  AFAIK, unlike say Java, C/C++ uses value
semantics, i.e., there's no indirection between the name and what it
refers to.

+ In this case, one Widget's lifetime ends and a new one begins. Both
+ Widget happen to use the same storage, so w continues to point to a
+ Widget. This is not really any different from:

The name "w" refers to a Widget, the same Widget throughout the scope
of its declaration.

+ void F()
+ {
+   Widget*  w = new Widget();
+
+   delete w;
+
+   w = new Widget();
+ }
+
+ It's entirely possible that the same address is returned, so that w's
+ value doesn't change. So what? It's still two Widgets.

In this case, the name "w" refers to a Widget-pointer, the same
Widget-pointer throughout the body of F.

+ It sounds like you're confusing address with identity; identity is not
+ defined by address.

I'm simply going by the common notions of "scope", which is that all
occurrences of a name within a given scope refer to the same entity.

+> +>   - We can indirectly determine the size of a reference:
+> +>
+> +>       class Widget {
+> +>         int& r;
+> +>       };
+> +>       ...
+> +>       sizeof(Widget);
+> +
+> + There is nothing in the standard I'm aware of that supports the idea
+> + that this somehow determines the size of a reference.
+>
+> That's why I said "indirectly".  This the size of a struct whose only
+> part is a refernece.
+
+ It may not be the only part. The implementation is allowed to put in
+ any padding or hidden members it wants.
+
+> In any case, per the as-if rule,sizeof can return whatever the
+> implementor chooses to say about the sizes of things.
+
+ In other words, after evaluating sizeof(Widget) above you still don't
+ know how big a reference is.

And the same is true of say sizeof(int).

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 10 Nov 2003 10:38:13 +0000 (UTC)
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
+ In article <boilsk$3dd$1@glue.ucr.edu>, thp@cs.ucr.edu writes
+>AFAIK, the destructor of a static or automatic object does not end the
+>object's lifetime but rather puts it into an "unconstructed" state
+>where accessing any part of the object invokes undefined behavior.
+>Placement-new can bring the object and its parts back from that state
+>with new "values" --- that includes parts having reference types.
+
+ Did you mean an explicitly called dtor rather than the normal dtor that
+ the compiler codes for the end of and automatic or static objects
+ lifetime?

Oops.  In either case my claim about lifetimes was incorrect.

The problem is that after we end an object's lifetime and subsequently
create an object of the same type at the same location via
placement-new, the object's name must still refer to "the same entity"
(3.3#1).

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 10 Nov 2003 10:38:21 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<boilsk$3dd$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + Either the declarative region ended with the destructor call above, or
+> + "declarative region" has no meaning in discussing liftime issues.
+>
+> AFAIK, declarative region is a region of code ("part of the program"),
+> a static (compile-time) notion.  Lifetime is an interval of run time,
+> a dynamic (run-time) notion.  The two notions are orthogonal, except
+> for the fact that the lifetime of some objects ends when execution
+> leaves a certain region.  (There are dynamically scoped langauges, but
+> C++ is not one of them.)
+
+ We were discussing lifetimes. Since declarative region is orthogonal
+ to lifetime issues, it was a red herring. My mistaken impressions of
+ declarative region aside, it seems that declarative region doesn't
+ have anything to say one way or the other about this statement:
+
+> +> +> One can take the view that w1's reference member has two lifetimes and
+> +> +> gets re-initialized by the copy constructor at the beginning of its
+> +> +> second lifetime
+
+ So when I said
+
+> +> + This view is correct.
+
+ I was correct.

Unfortunately, that view appears to be incompatible with the
definition of "declarative region", which says that within its
declarative region a name refers to the same entity, e.g., the
instances of "w1" before and after the execution of operator= would
refer to the same entity.

+> + It's inescapable: once a destructor of an object executes, that
+> + object's lifetime (and the lifetimes of all of its parts) ends. To
+> + claim otherwise is to go against one of the foundations of C++.
+>
+> AFAIK, the destructor of a static or automatic object does not end the
+> object's lifetime but rather puts it into an "unconstructed" state
+> where accessing any part of the object invokes undefined behavior.
+> Placement-new can bring the object and its parts back from that state
+> with new "values" --- that includes parts having reference types.

The above paragraph is an error on my part.

[...]
+ Just because the same region of memory is used for both new calls
+ doesn't mean the first Foo was brought back to life, or that the first
+ object somehow continued to exist in an unconstructed state.

The static scoping rules of C++ imply that both instances of "w1"
refer to the same object.  Perhaps that happens via re-incarnation,
not resurrection.  (A language specification doesn't need to be
ontologically consistent to correctly specify the behavior of
programs.)

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 10 Nov 2003 18:54:54 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bolisj$q39$1@glue.ucr.edu>...
> Francis Glassborow <francis@robinton.demon.co.uk> wrote:
> + In article <c87c1cfb.0311071749.787a0737@posting.google.com>, Bob Bell
> + <belvis@pacbell.net> writes
> +>It seems pretty obvious to me that the phrase "largest part of the
> +>program in which that name is valid" must mean that the declarative
> +>region must end at the point at which the destructor executes; after
> +>the destructor of w executes, w.r is no longer valid.
> +
> + I think you are confusing names with objects. A name may be valid (i.e.
> + the compiler must not reject it) even though the object it referred to
> + has ended its lifetime.
>
> I've always understood that (per the definition of scope), within the
> scope of a given name, all occurrences of that name refer to the same
> entity.  So, after an object's destruction, its name refers to the
> ghost of the destructed object, and any use of that name invokes nasal
> demons.  But, after a subsequent placement-new (of appropriate type)
> at the old location, the name refers to the resurrected object, and
> demons go away.  Right?

struct Widget {
   int x;
};

void F()
{
   Widget w;

   w.~Widget();

// summon the nasal demons
   w.x = 10;
}

The nasal demons come because this code treats raw memory like an
object. After executing w.~Widget(), the memory region at &w does not
contain an object; using it as if it were an object is as undefined as
this:

void F()
{
   char  w[sizeof(Widget)];

   reinterpret_cast<Widget*>(&w[0]).x = 10;
}

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 10 Nov 2003 18:56:10 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bolgf3$pub$1@glue.ucr.edu>...
[...]
+ void F()
+ {
+   Widget w;
+
+   w.~Widget();
+
+   w.x = 10;
+ }
+
+ In the line "w.x = 10;", w is in scope. Does it still name the same
+ entity it named before the explicit destructor call?

Per 3.3#1, the name "w" still refers to that same now-destructed
entity.  Referring to people and things whose lifetimes have ended is
not that unusual.

+ No. Scope isn't everything.

AFAIK, in C++, any use of the name of an object whose lifetimes has
ended (and not been reconstructed via placement-new) invokes undefined
behavior, e.g., the line cited above.

+ When control enters a scope, it causes constructors to be called which
+ create the objects defined in that scope. When control leaves a scope,
+ it causes destructors to be called to destroy the objects in that
+ scope. But it's not the scope that controls the lifetimes of objects;
+ the lifetimes of objects are controlled by the calls to the
+ constructors and destructors. You can end an object's lifetime
+ prematurely by calling the destructor early, as above. Likewise, you
+ can use placement new to turn a range of memory into an object. For an
+ example of these things in action, study your implementation's
+ std::vector.
+
+ If you call the destructor of an object, in any context, either
+ explicitly or implicitly, that object is gone. Kaput. Bye bye.

Apparently the authors of the Standard believe that we can refer to
the destructed, but not without invoking undefined behavior (unless,
of course, we reconstruct the destructed via placement-new).  This
doctrine of reconstruction isn't all that strange when you consider
that billions of people subscribe to doctrines like re-incarnation,
transubstantiation, resurrection, etc.

[...]
+> But, that reference now "denotes"
+> the int object j.  So, the expression "w1.r" now "designates" j:
+>
+>    If an expression initially has the type "reference to T" (8.3.2,
+>    8.4.3), the type is adjusted to "T" prior to any further analysis,
+>    the expression designates the object or function denoted by the
+>    reference, and the expression is an lvalue.                  [5#6]
+>
+> Presumably by the phrase "the reference", 5#6 means the reference
+> value of the unadjusted expression.
+
+ That's a big presumption; the phrase "reference value" doesn't appear
+ anywhere in the standard as far as I know. I find it more likely that
+ the phrase "the reference" means "the reference". I still don't
+ understand the need to introduce this "reference value" concept when
+ standard C++ works just fine without it.

I'm not sure it's needed either.  Per 5.2.2#4:

  The value of a function call is the value returned by the called
  function ...

So, to accomodate calls to reference-valued functions in my
presumption, I referred to the value of the expression of type
reference-to-T a "reference value".

+ In any case, I'm not sure I understood if you answered my question. On
+ what line did the reseating take place?

At "w1 = w2;".

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 10 Nov 2003 19:15:23 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bomti5$7lt$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + thp@cs.ucr.edu wrote in message news:<bokd1p$h22$1@glue.ucr.edu>...
> +> So, there are three supposedly distnct notions:
> +>
> +>   - references, which supposedly get initialized with reference values
> +>     at certain points.
> +>
> +>   - reference values, which supposedly are returned by functions
> +>     having reference return types.
> +>
> +>   - referents, which supposedly are the things referred to by
> +>     reference values.
> +>
> +> Which of the three possible distinctions are accepted and which are
> +> under question?
> +
> + All are objectionable, since they all use the term "reference value".
> +
> + I would use say something more like this:
> +
> + -- references, which get initialized with objects
> + -- referents, the objects referred to by references
> +
> + As far as I know, these concepts are completely consistent with the
> + way references are defined and used in C++. No "reference value"
> + concept is implied or needed.
>
> There's still the problem of what it is that a reference-valued
> function returns.

A reference; I feel like I've answered this question a dozen times.
Why is this so hard? I just don't get the problem here. Maybe you
should just spell out what problem the term "reference value" solves.

> +> + No one has shown how to change the value of a reference. There have
> +> + been examples of destroying references and recreating new ones in the
> +> + same memory.
> +> +
> +> + void G(Widget* w, int& r)
> +> + {
> +> +   w->~Widget();
> +> +
> +> +   new (w) Widget(r);
> +> + }
> +> +
> +> + void F()
> +> + {
> +> +   int x, y;
> +> +   Widget*  w = new Widget(x);
> +> +
> +> +   G(w, y);
> +> + }
> +>
> +> + Do you think this changes w->r? I don't. Even if G() is really called
> +> + operator=().
> +>
> +> Per the definitions of "declarative region", w denotes the same Widget
> +> (having the same reference member) both before and after the execution
> +> of G.
> +
> + I don't think so. My newfound understanding of declarative region
> + tells me that w denotes the same _pointer object_; what it points to
> + is a dynamic issue and is not affected by static concepts like
> + declarative region.
>
> Huh?  Are you claiming that names of C++ variables refer don't refer
> to the object in their definitions but rather to hidden pointers that
> point to that object.  AFAIK, unlike say Java, C/C++ uses value
> semantics, i.e., there's no indirection between the name and what it
> refers to.

Read the code again. W is a pointer to a Widget, not a Widget. In G(),
w points to a _new_ Widget, even though the value of w never changes.

It doesn't even matter if w is really called "this":

Widget& Widget::operator=(const Widget& iOther)
{
   if (this != &iOther) {
      this->~Widget();
      new (this) Widget(iOther);
   }
   return *this;
}

Here, even though the pointer value of "this" never changed, it
obviously refers to one Widget at the beginning of the function and
another Widget at the end. Just as in the G() example above.

> + In this case, one Widget's lifetime ends and a new one begins. Both
> + Widget happen to use the same storage, so w continues to point to a
> + Widget. This is not really any different from:
>
> The name "w" refers to a Widget, the same Widget throughout the scope
> of its declaration.

Read again; w is a pointer.

> + void F()
> + {
> +   Widget*  w = new Widget();
> +
> +   delete w;
> +
> +   w = new Widget();
> + }
> +
> + It's entirely possible that the same address is returned, so that w's
> + value doesn't change. So what? It's still two Widgets.
>
> In this case, the name "w" refers to a Widget-pointer, the same
> Widget-pointer throughout the body of F.

I think you missed the point because you thought the first w was a
Widget, not a Widget*. Both examples are equivalent. Both examples
show one Widget dying and a new one coming to life, whether they share
the same space or not.

> + It sounds like you're confusing address with identity; identity is not
> + defined by address.
>
> I'm simply going by the common notions of "scope", which is that all
> occurrences of a name within a given scope refer to the same entity.

Are you claiming that an object's lifetime doesn't end when its
destructor executes?

> +> +>   - We can indirectly determine the size of a reference:
> +> +>
> +> +>       class Widget {
> +> +>         int& r;
> +> +>       };
> +> +>       ...
> +> +>       sizeof(Widget);
> +> +
> +> + There is nothing in the standard I'm aware of that supports the idea
> +> + that this somehow determines the size of a reference.
> +>
> +> That's why I said "indirectly".  This the size of a struct whose only
> +> part is a refernece.
> +
> + It may not be the only part. The implementation is allowed to put in
> + any padding or hidden members it wants.
> +
> +> In any case, per the as-if rule,sizeof can return whatever the
> +> implementor chooses to say about the sizes of things.
> +
> + In other words, after evaluating sizeof(Widget) above you still don't
> + know how big a reference is.
>
> And the same is true of say sizeof(int).

No. sizeof(x) gives the size of x. So sizeof(int) gives the size of an
int. sizeof(Widget) gives the size of a Widget. But sizeof(Widget)
doesn't tell me anything about the size of a reference.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Tue, 11 Nov 2003 05:01:17 +0000 (UTC)
Raw View
belvis@pacbell.net (Bob Bell) wrote in message news:<c87c1cfb.0311091612.17289c18@posting.google.com>...
> thp@cs.ucr.edu wrote in message news:<bolisj$q39$1@glue.ucr.edu>...
> > Francis Glassborow <francis@robinton.demon.co.uk> wrote:
> > + In article <c87c1cfb.0311071749.787a0737@posting.google.com>, Bob Bell
> > + <belvis@pacbell.net> writes
> > +>It seems pretty obvious to me that the phrase "largest part of the
> > +>program in which that name is valid" must mean that the declarative
> > +>region must end at the point at which the destructor executes; after
> > +>the destructor of w executes, w.r is no longer valid.
> > +
> > + I think you are confusing names with objects. A name may be valid (i.e.
> > + the compiler must not reject it) even though the object it referred to
> > + has ended its lifetime.
> >
> > I've always understood that (per the definition of scope), within the
> > scope of a given name, all occurrences of that name refer to the same
> > entity.  So, after an object's destruction, its name refers to the
> > ghost of the destructed object, and any use of that name invokes nasal
> > demons.  But, after a subsequent placement-new (of appropriate type)
> > at the old location, the name refers to the resurrected object, and
> > demons go away.  Right?
>
> struct Widget {
>    int x;
> };
>
> void F()
> {
>    Widget w;
>
>    w.~Widget();
>
> // summon the nasal demons
>    w.x = 10;
> }
>
> The nasal demons come because this code treats raw memory like an
> object. After executing w.~Widget(), the memory region at &w does not
> contain an object; using it as if it were an object is as undefined as
> this:
>
> void F()
> {
>    char  w[sizeof(Widget)];
>
>    reinterpret_cast<Widget*>(&w[0]).x = 10;
> }
>
> Bob

Oops. It's even more undefined than I thought, because it won't even
compile. Let's try

reinterpret_cast<Widget*>(&w[0])->x = 10;

instead.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet@nmhq.net (Niklas Matthies)
Date: Fri, 31 Oct 2003 17:29:00 +0000 (UTC)
Raw View
On 2003-10-27 18:02, Bob Bell wrote:
[...]
> You can pretend references have values if you want, but that view
> isn't supported by the standard and adds complexity for no real
> benefit -- as you say, if you view references as having value, then
> there isn't any semantic change (as long as you insert all the
> exceptions you need in all the right places). So what's the point?

The point is that when you have

   int i;
   int & r1 = i;
   int & r2 = i;

you want to distinguish between (a) the thingies called 'r1' and 'r2'
and (b) the identity of the object they reference. In the example
above, 'r1' and 'r2' are two distinct thingies which happen to
reference the same object. (Whereas in

   int & r1 = f();
   int & r2 = g();

they may or may not end up referencing the same object.)

We need a name for the property (which is, in the general case, a
runtime property) of r1 and r2 that determines which object they refer
to, respectively. Whatever you call this property, it's definitely
there. I call it the "value" of r1/r2 because I happen to think that
this common-language word exactly describes these kinds of properties.
Calling both this property and the (a)-thingies 'references' is being
imprecise and confusing things.

-- Niklas Matthies

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Fri, 31 Oct 2003 23:02:07 +0000 (UTC)
Raw View
usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq4n00.1add.usenet@nmhq.net>...
> On 2003-10-27 18:02, Bob Bell wrote:
> [...]
> > You can pretend references have values if you want, but that view
> > isn't supported by the standard and adds complexity for no real
> > benefit -- as you say, if you view references as having value, then
> > there isn't any semantic change (as long as you insert all the
> > exceptions you need in all the right places). So what's the point?
>
> The point is that when you have
>
>    int i;
>    int & r1 = i;
>    int & r2 = i;
>
> you want to distinguish between (a) the thingies called 'r1' and 'r2'
> and (b) the identity of the object they reference. In the example
> above, 'r1' and 'r2' are two distinct thingies which happen to
> reference the same object.

So what's wrong with

a) reference
b) the object referred to by a reference

> (Whereas in
>
>    int & r1 = f();
>    int & r2 = g();
>
> they may or may not end up referencing the same object.)
>
> We need a name for the property (which is, in the general case, a
> runtime property) of r1 and r2 that determines which object they refer
> to, respectively. Whatever you call this property, it's definitely
> there. I call it the "value" of r1/r2 because I happen to think that
> this common-language word exactly describes these kinds of properties.
> Calling both this property and the (a)-thingies 'references' is being
> imprecise and confusing things.

Only if there is some need to distinguish them. Is there something
that you can do with "reference values" that can't be done with
"(a)-thingies", or vice versa? If so, then maybe we need new
terminology as you suggest. I'm unaware of anything distinguishes
these two concepts.

Note that this distinction exists for objects. For example, there are
operations that apply to an int (like taking its address) and
operations that apply to its value (like addition).

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Sat, 1 Nov 2003 00:28:19 +0000 (UTC)
Raw View
usenet@nmhq.net (Niklas Matthies) wrote
> The point is that when you have
>
>    int i;
>    int & r1 = i;
>    int & r2 = i;
>
> you want to distinguish between (a) the thingies called 'r1' and 'r2'
> and (b) the identity of the object they reference. In the example
> above, 'r1' and 'r2' are two distinct thingies which happen to
> reference the same object.

r1 and r2 are names.  They name exactly the same object that i names.
They do *not* name some mysterious thingie(s).  Honest!

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 1 Nov 2003 08:26:38 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
[....]
+ Note that this distinction exists for objects. For example, there are
+ operations that apply to an int (like taking its address) and
+ operations that apply to its value (like addition).

The function  int f(){return 3;}  returns an int.  You can't take the
return-value's address, and it is its own value.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 1 Nov 2003 08:27:00 +0000 (UTC)
Raw View
johnchx <johnchx2@yahoo.com> wrote:
+ usenet@nmhq.net (Niklas Matthies) wrote
+> The point is that when you have
+>
+>    int i;
+>    int & r1 = i;
+>    int & r2 = i;
+>
+> you want to distinguish between (a) the thingies called 'r1' and 'r2'
+> and (b) the identity of the object they reference. In the example
+> above, 'r1' and 'r2' are two distinct thingies which happen to
+> reference the same object.
+
+ r1 and r2 are names.  They name exactly the same object that i names.
+ They do *not* name some mysterious thingie(s).  Honest!

Consider:

  class Widget {
    int& r;
    Widget(int& i) r(i) {}
  };

Whatever r names at compile time isn't an int.  Whatever r names at
load time isn't an int.  At some point, the entity that r names, which
is commonly called a "reference", gets bound to an int object, but it
can later get bound to a different int object.  Honest.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Niklas Matthies <usenet@nmhq.net>
Date: Sat, 1 Nov 2003 15:30:55 CST
Raw View
On 2003-11-01 00:28, johnchx wrote:
> usenet@nmhq.net (Niklas Matthies) wrote
>> The point is that when you have
>>
>>    int i;
>>    int & r1 = i;
>>    int & r2 = i;
>>
>> you want to distinguish between (a) the thingies called 'r1' and 'r2'
>> and (b) the identity of the object they reference. In the example
>> above, 'r1' and 'r2' are two distinct thingies which happen to
>> reference the same object.
>
> r1 and r2 are names.  They name exactly the same object that i names.
> They do *not* name some mysterious thingie(s).  Honest!

Seeing it this way would make sense if references were always named.
But as function returns, we have unnamed references, which means that
references are things in their own right, neither names nor objects.
So if you want to treat named and unnamed references uniformly, then
r1 and r2 have to be considered as naming references-to-objects, not
as naming objects.

-- Niklas Matthies

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet@nmhq.net (Niklas Matthies)
Date: Mon, 3 Nov 2003 21:36:36 +0000 (UTC)
Raw View
On 2003-10-31 23:02, Bob Bell wrote:
> usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq4n00.1add.usenet@nmhq.net>...
>> On 2003-10-27 18:02, Bob Bell wrote:
>> [...]
>> > You can pretend references have values if you want, but that view
>> > isn't supported by the standard and adds complexity for no real
>> > benefit -- as you say, if you view references as having value, then
>> > there isn't any semantic change (as long as you insert all the
>> > exceptions you need in all the right places). So what's the point?
>>
>> The point is that when you have
>>
>>    int i;
>>    int & r1 = i;
>>    int & r2 = i;
>>
>> you want to distinguish between (a) the thingies called 'r1' and 'r2'
>> and (b) the identity of the object they reference. In the example
>> above, 'r1' and 'r2' are two distinct thingies which happen to
>> reference the same object.
>
> So what's wrong with
>
> a) reference
> b) the object referred to by a reference

(b) is not an object. A function whose return type is a reference type
doesn't pass an object proper (the object remains wherever it is), it
merely passes something that identifies the object.

I'll try to illustrate this with a slightly more complex example:

   int i;
   int & r1 = i;

   int & h(int & r2) { return r2; }
   int & g(int & r3) { return h(r3); }
   int & f(int & r4) { return g(r4); }

   int & r5 = f(r1);

What happens during exectution of the last line is that there's a
"reference to the object denoted by i" originating from r1 that gets
passed through f, g, h and back and eventually ends up being as what
r5 is initialized with. This _single_ thing getting passed forth and
back is neither a reference in the sense of r1 to r5 and the unnamed
function returns (since these are several distinct entities), nor is
it the object-denoted-by-i proper (objects per se remain fixed at their
storage location, they do not get passed around). Rather, what gets
passed around is something-that-indentifies-the-object-denoted-by-i.

>> (Whereas in
>>
>>    int & r1 = f();
>>    int & r2 = g();
>>
>> they may or may not end up referencing the same object.)
>>
>> We need a name for the property (which is, in the general case, a
>> runtime property) of r1 and r2 that determines which object they refer
>> to, respectively. Whatever you call this property, it's definitely
>> there. I call it the "value" of r1/r2 because I happen to think that
>> this common-language word exactly describes these kinds of properties.
>> Calling both this property and the (a)-thingies 'references' is being
>> imprecise and confusing things.
>
> Only if there is some need to distinguish them. Is there something
> that you can do with "reference values" that can't be done with
> "(a)-thingies", or vice versa?

I can pass reference values around. I can bind them to (a)-thingies.
I can't pass (a)-thingies around, and neither can I bind them to
other (a)-thingies. To illustrate the latter, consider

   int i;
   int & r1 = i;
   int & r2 = i;
   int & r3 = r1;
   {
      int & r4 = r2;
      ...
   }

There's nothing that distinguishes r3 from r4 apart from their
initializer expression, their name and their scope, which strongly
suggests that what the names r3 and r4 are bound to is not the
(a)-thingies r1 and r2, respectively, but rather the (single)
(b)-thingy "reference to the object denoted y i".

If you will, the statement "r3 and r4 have the same reference value"
is synonymous to "r3 and r4 are references to the same object", only
that the former gives this property shared by r3 and r4 an actual
name. Since what object a particular (a)-thingy refers to is the most
essential (runtime) property of an (a)-thingy (just as an integer
variable's most essential runtime property is which integer value it
contains), I would believe that this property should be given a name.

> If so, then maybe we need new terminology as you suggest. I'm
> unaware of anything distinguishes these two concepts.
>
> Note that this distinction exists for objects. For example, there are
> operations that apply to an int (like taking its address) and
> operations that apply to its value (like addition).

Well, there is more than these kinds of "applyable" operations that
necessitates distinguishing 'thingies'.

-- Niklas Matthies

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Tue, 4 Nov 2003 18:38:43 +0000 (UTC)
Raw View
usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq6iia.pr7.usenet@nmhq.net>...
> On 2003-10-31 23:02, Bob Bell wrote:
> > usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq4n00.1add.usenet@nmhq.net>...
> >> On 2003-10-27 18:02, Bob Bell wrote:
> >> [...]
> >> > You can pretend references have values if you want, but that view
> >> > isn't supported by the standard and adds complexity for no real
> >> > benefit -- as you say, if you view references as having value, then
> >> > there isn't any semantic change (as long as you insert all the
> >> > exceptions you need in all the right places). So what's the point?
> >>
> >> The point is that when you have
> >>
> >>    int i;
> >>    int & r1 = i;
> >>    int & r2 = i;
> >>
> >> you want to distinguish between (a) the thingies called 'r1' and 'r2'
> >> and (b) the identity of the object they reference. In the example
> >> above, 'r1' and 'r2' are two distinct thingies which happen to
> >> reference the same object.
> >
> > So what's wrong with
> >
> > a) reference
> > b) the object referred to by a reference
>
> (b) is not an object. A function whose return type is a reference type
> doesn't pass an object proper (the object remains wherever it is), it
> merely passes something that identifies the object.
>
> I'll try to illustrate this with a slightly more complex example:
>
>    int i;
>    int & r1 = i;
>
>    int & h(int & r2) { return r2; }
>    int & g(int & r3) { return h(r3); }
>    int & f(int & r4) { return g(r4); }
>
>    int & r5 = f(r1);
>
> What happens during exectution of the last line is that there's a
> "reference to the object denoted by i" originating from r1 that gets
> passed through f, g, h and back and eventually ends up being as what
> r5 is initialized with. This _single_ thing getting passed forth and
> back is neither a reference in the sense of r1 to r5 and the unnamed
> function returns (since these are several distinct entities), nor is
> it the object-denoted-by-i proper (objects per se remain fixed at their
> storage location, they do not get passed around). Rather, what gets
> passed around is something-that-indentifies-the-object-denoted-by-i.

But that isn't what happens. Nothing gets copied.

I think we're just going round and round here. You think references
have values that get copied. OK, fine you can think that. I claim you
can't write code that demonstrates that in any way, so what's the
point? You think failing to distinguish between a reference and its
value is confusing and ambiguous. I've never made this distinction and
I've never experienced any confusion as a result.

References are never copied, they're simply initialized to refer to
some other object. Period. No exceptions.

Consider:

   int i;
   int& r = i;

Here, r is initialized to refer to i; nothing is copied.

   void f(int& r1);

   int i;

   f(i);

Here, the _same thing_ happens as above: r1 is initialized to refer to
i; nothing is copied. It's exactly the same process.

   void f2(int& r2);

   void f3(int& r3)
   {
      f2(r3);
   }

Here, all that happens is r2 is initialized to refer to whatever r3
refers to -- remember, once initialized, all uses of a reference are
actually uses of the object that is referenced. So again, we have the
_same thing_ happening as in the previous two examples.

References are always _initialized_ at the beginnings of their
lifetimes; they are never copied.

[snip]

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 5 Nov 2003 19:13:42 +0000 (UTC)
Raw View
Niklas Matthies <usenet@nmhq.net> wrote:
+ On 2003-10-31 23:02, Bob Bell wrote:
+> usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq4n00.1add.usenet@nmhq.net>...
+>> On 2003-10-27 18:02, Bob Bell wrote:
+>> [...]
+>> > You can pretend references have values if you want, but that view
+>> > isn't supported by the standard and adds complexity for no real
+>> > benefit -- as you say, if you view references as having value, then
+>> > there isn't any semantic change (as long as you insert all the
+>> > exceptions you need in all the right places). So what's the point?
+>>
+>> The point is that when you have
+>>
+>>    int i;
+>>    int & r1 = i;
+>>    int & r2 = i;
+>>
+>> you want to distinguish between (a) the thingies called 'r1' and 'r2'
+>> and (b) the identity of the object they reference. In the example
+>> above, 'r1' and 'r2' are two distinct thingies which happen to
+>> reference the same object.
+>
+> So what's wrong with
+>
+> a) reference
+> b) the object referred to by a reference
+
+ (b) is not an object. A function whose return type is a reference type
+ doesn't pass an object proper (the object remains wherever it is), it
+ merely passes something that identifies the object.
+
+ I'll try to illustrate this with a slightly more complex example:
+
+   int i;
+   int & r1 = i;
+
+   int & h(int & r2) { return r2; }
+   int & g(int & r3) { return h(r3); }
+   int & f(int & r4) { return g(r4); }
+
+   int & r5 = f(r1);
+
+ What happens during exectution of the last line is that there's a
+ "reference to the object denoted by i" originating from r1 that gets
+ passed through f, g, h and back and eventually ends up being as what
+ r5 is initialized with. This _single_ thing getting passed forth and
+ back is neither a reference in the sense of r1 to r5 and the unnamed
+ function returns (since these are several distinct entities), nor is
+ it the object-denoted-by-i proper (objects per se remain fixed at their
+ storage location, they do not get passed around). Rather, what gets
+ passed around is something-that-indentifies-the-object-denoted-by-i.

Before I studied C++, I would say: "x gets passed by reference".  Now
I say: "A reference to x gets passed".

+>> (Whereas in
+>>
+>>    int & r1 = f();
+>>    int & r2 = g();
+>>
+>> they may or may not end up referencing the same object.)
+>>
+>> We need a name for the property (which is, in the general case, a
+>> runtime property) of r1 and r2 that determines which object they refer
+>> to, respectively. Whatever you call this property, it's definitely
+>> there. I call it the "value" of r1/r2 because I happen to think that
+>> this common-language word exactly describes these kinds of properties.
+>> Calling both this property and the (a)-thingies 'references' is being
+>> imprecise and confusing things.
+>
+> Only if there is some need to distinguish them. Is there something
+> that you can do with "reference values" that can't be done with
+> "(a)-thingies", or vice versa?
+
+ I can pass reference values around. I can bind them to (a)-thingies.
+ I can't pass (a)-thingies around, and neither can I bind them to
+ other (a)-thingies. To illustrate the latter, consider
+
+   int i;
+   int & r1 = i;
+   int & r2 = i;
+   int & r3 = r1;
+   {
+      int & r4 = r2;
+      ...
+   }
+
+ There's nothing that distinguishes r3 from r4 apart from their
+ initializer expression, their name and their scope, which strongly
+ suggests that what the names r3 and r4 are bound to is not the
+ (a)-thingies r1 and r2, respectively, but rather the (single)
+ (b)-thingy "reference to the object denoted y i".
+
+ If you will, the statement "r3 and r4 have the same reference value"
+ is synonymous to "r3 and r4 are references to the same object", only
+ that the former gives this property shared by r3 and r4 an actual
+ name.

And why should we have to say "reference value" rather that simply
"value"?

+ Since what object a particular (a)-thingy refers to is the most
+ essential (runtime) property of an (a)-thingy (just as an integer
+ variable's most essential runtime property is which integer value it
+ contains), I would believe that this property should be given a name.
+
+> If so, then maybe we need new terminology as you suggest. I'm
+> unaware of anything distinguishes these two concepts.
+>
+> Note that this distinction exists for objects. For example, there are
+> operations that apply to an int (like taking its address) and
+> operations that apply to its value (like addition).
+
+ Well, there is more than these kinds of "applyable" operations that
+ necessitates distinguishing 'thingies'.

In fact, we need to distinguish between int thingies and int-object
thingies.  It has been claimed that one can take the address of an
int, but in fact the function f defined by "int f(){return 1;}"
returns an int whose address cannot directly be taken, i.e., "&f()" is
not valid.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 6 Nov 2003 18:52:34 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq6iia.pr7.usenet@nmhq.net>...
+> On 2003-10-31 23:02, Bob Bell wrote:
+> > usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbq4n00.1add.usenet@nmhq.net>...
+> >> On 2003-10-27 18:02, Bob Bell wrote:
+> >> [...]
+> >> > You can pretend references have values if you want, but that view
+> >> > isn't supported by the standard and adds complexity for no real
+> >> > benefit -- as you say, if you view references as having value, then
+> >> > there isn't any semantic change (as long as you insert all the
+> >> > exceptions you need in all the right places). So what's the point?
+> >>
+> >> The point is that when you have
+> >>
+> >>    int i;
+> >>    int & r1 = i;
+> >>    int & r2 = i;
+> >>
+> >> you want to distinguish between (a) the thingies called 'r1' and 'r2'
+> >> and (b) the identity of the object they reference. In the example
+> >> above, 'r1' and 'r2' are two distinct thingies which happen to
+> >> reference the same object.
+> >
+> > So what's wrong with
+> >
+> > a) reference
+> > b) the object referred to by a reference
+>
+> (b) is not an object. A function whose return type is a reference type
+> doesn't pass an object proper (the object remains wherever it is), it
+> merely passes something that identifies the object.
+>
+> I'll try to illustrate this with a slightly more complex example:
+>
+>    int i;
+>    int & r1 = i;
+>
+>    int & h(int & r2) { return r2; }
+>    int & g(int & r3) { return h(r3); }
+>    int & f(int & r4) { return g(r4); }
+>
+>    int & r5 = f(r1);
+>
+> What happens during exectution of the last line is that there's a
+> "reference to the object denoted by i" originating from r1 that gets
+> passed through f, g, h and back and eventually ends up being as what
+> r5 is initialized with. This _single_ thing getting passed forth and
+> back is neither a reference in the sense of r1 to r5 and the unnamed
+> function returns (since these are several distinct entities), nor is
+> it the object-denoted-by-i proper (objects per se remain fixed at their
+> storage location, they do not get passed around). Rather, what gets
+> passed around is something-that-indentifies-the-object-denoted-by-i.
+
+ But that isn't what happens. Nothing gets copied.
+
+ I think we're just going round and round here. You think references
+ have values that get copied. OK, fine you can think that. I claim you
+ can't write code that demonstrates that in any way, so what's the
+ point? You think failing to distinguish between a reference and its
+ value is confusing and ambiguous. I've never made this distinction and
+ I've never experienced any confusion as a result.
+
+ References are never copied, they're simply initialized to refer to
+ some other object. Period. No exceptions.
+
+ Consider:
+
+   int i;
+   int& r = i;
+
+ Here, r is initialized to refer to i; nothing is copied.
+
+   void f(int& r1);
+
+   int i;
+
+   f(i);
+
+ Here, the _same thing_ happens as above: r1 is initialized to refer to
+ i; nothing is copied. It's exactly the same process.
+
+   void f2(int& r2);
+
+   void f3(int& r3)
+   {
+      f2(r3);
+   }
+
+ Here, all that happens is r2 is initialized to refer to whatever r3
+ refers to -- remember, once initialized, all uses of a reference are
+ actually uses of the object that is referenced. So again, we have the
+ _same thing_ happening as in the previous two examples.
+
+ References are always _initialized_ at the beginnings of their
+ lifetimes; they are never copied.

Consider:

    #include<new>
    #include<iostream>
    class Widget {
    public:
      int& r;
      Widget( int& i ) : r( i ) {}
      void reseat( int& i ) {
        this->~Widget() ;
        new( this ) Widget( i ) ;
      }
      Widget& operator=( Widget const& other ) {
        if ( this != &other ) {
          this->~Widget() ;
          new ( this ) Widget( other ) ;
        }
        return *this ;
      }
    } ;

    int main() {
      int i, j;
      Widget w1(i);
      Widget w2(j);
      assert( &w1.r == &i );
      w1 = w2;                 // change of state or new lifetime?
      assert( &w1.r == &j );
    }

One can take the view that w1's reference member has two lifetimes and
gets re-initialized by the copy constructor at the beginning of its
second lifetime -- in fact, the updating of any object could be
described that way.  And, that view is in harmony with the Standard's
terminology regarding the ontology of references.  It's more standard,
however, to view things that have state as changing state rather than
as ceasing to exist and coming back into existence with a new initial
state.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Thu, 6 Nov 2003 18:52:37 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bnvg7m$783$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> [....]
> + Note that this distinction exists for objects. For example, there are
> + operations that apply to an int (like taking its address) and
> + operations that apply to its value (like addition).
>
> The function  int f(){return 3;}  returns an int.  You can't take the
> return-value's address, and it is its own value.

That's interesting, and true, but I don't see the relevance. We were
discussing whether or not it makes sense to distinguish references
from "reference values". The point I made above is that I can make a
distinction between ints and int values based on the things I can do
with one or the other. Your example shows that the line is not as
neatly drawn as I made it seem, but your example doesn't disprove my
point. I can still take the address of an int object, but not the
address of an int value; thus it makes sense to talk about ints and
int values. Do you disagree with this?

I'm unaware of any distinction between a reference and its "value";
there are no operations that apply to one but not the other. This is
the question I posed in the previous post, and the one that would
decide the issue for me.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Thu, 6 Nov 2003 23:59:26 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<boarh4$s6j$1@glue.ucr.edu>...
> Consider:
>
>     #include<new>
>     #include<iostream>
>     class Widget {
>     public:
>       int& r;
>       Widget( int& i ) : r( i ) {}
>       void reseat( int& i ) {
>         this->~Widget() ;
>         new( this ) Widget( i ) ;
>       }
>       Widget& operator=( Widget const& other ) {
>         if ( this != &other ) {
>           this->~Widget() ;
>           new ( this ) Widget( other ) ;
>         }
>         return *this ;
>       }
>     } ;
>
>     int main() {
>       int i, j;
>       Widget w1(i);
>       Widget w2(j);
>       assert( &w1.r == &i );
>       w1 = w2;                 // change of state or new lifetime?
>       assert( &w1.r == &j );
>     }
>
> One can take the view that w1's reference member has two lifetimes and
> gets re-initialized by the copy constructor at the beginning of its
> second lifetime

This view is correct.

> -- in fact, the updating of any object could be
> described that way.

You can describe it any way you want, but that doesn't make it
correct.

   int x;

   x = 10;

does not end x's lifetime and then reinitialize it to contain 10.

> And, that view is in harmony with the Standard's
> terminology regarding the ontology of references.

...which is why it's correct.

> It's more standard,
> however, to view things that have state as changing state rather than
> as ceasing to exist and coming back into existence with a new initial
> state.

An incorrect view, no matter how convenient, is still incorrect.

References are never copied, only initialized. Your own example shows
references being initialized, not copied.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sun, 19 Oct 2003 19:23:07 +0000 (UTC)
Raw View
On Thu, 16 Oct 2003 08:47:03 +0000, DrPizza wrote:

>> As an
>> additional optimization the compiler is free to not allocate it if the
>> result is the same, but it's already stated elsewhere that the program can
>> be compiled differently if you can't observe the difference.
> Why use a model that can be wrong when you can use a model that's always
> right?

Because the program effect is the same.

And it's equally true for pointers, so it's not a reason to not explain
references in terms of pointers.

>> And now you have been misled by your own definition!
>> No, it would not be acceptable in general:
> An unusual counter-example (aliasing of globals?  Who uses globals in this day
> and age?) is hardly a demonstration that it can't be used in general.

Why use a model that can be wrong when you can use a model that's always
right?

> True, C++ is hindered by the general assumption that aliasing can occur.
> But this will (or at least, should) change sooner rather than later

You mean C99's restrict? Well, aliasing still can occur *by default* and I
don't believe it can be changed.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Sun, 19 Oct 2003 19:29:27 +0000 (UTC)
Raw View
drpizza@anti-flash.co.uk ("DrPizza") wrote in message news:<vop821pdealc67@corp.supernews.com>...
...
> Reference members are (or probably should be) a rarity.  I said "in general".
> In some situations there may be no choice but to have a unreseatable pointer.
> In some situations it may be desirable (e.g. arguments longer than maybe two
> pointers in length).  But for something such as:
>
> int i;
> int& ri(i);
> std::cout << ri << std::endl;

Why would anyone write such code? Why use 'ri' when 'i' is right
there? At best, it's a notational convenience when the original name
is very long, but I don't think that's a common use of references.
Most of the references I've seen were either function parameters or
class members. I think that a reference member always require storage
of a hidden pointer object, and that reference function parameter
usually require it too, except when the function can be inlined.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: drpizza@anti-flash.co.uk ("DrPizza")
Date: Sun, 19 Oct 2003 19:29:35 +0000 (UTC)
Raw View
""Marcin 'Qrczak' Kowalczyk"" <qrczak@knm.org.pl> wrote in message
news:pan.2003.10.17.07.26.49.749342@knm.org.pl...
> On Fri, 17 Oct 2003 05:06:53 +0000, DrPizza wrote:
> > int i;
> > int& ri(i);
> > std::cout << ri << std::endl;
> I don't see why a programmer would want to make a reference like this.
Well, would you understand it if a Win32 programmer wrote something like:

void* memory(::VirtualAlloc(0, 4096 * 1024, MEM_COMMIT, PAGE_READWRITE));
const ScopeGuard& sg(MakeGuard(&::VirtualFree, memory, 0, MEM_RELEASE);

(where ScopeGuard is from
http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/ )

There's no reason for that reference to have any actual representation.

> It's impractical for a compiler to implement this as copy in, copy out.
> Since it doesn't work in all cases, there would have to be two calling
> conventions for pasing reference parameter (of the same type).
There are certainly compilers that will do this kind of thing, though --
they'll generate custom calling conventions depending on how the function is
used.  So this doesn't seem to me to be a prohibitive difficulty.

> Because
> of function pointers, thye compiler would have to either emit two entry
> points for a function using references, or apply the copy in, copy out
> technique only to static functions / private methods which don't have
> their pointer taken where the compiler was able to make sure that this
> technique is safe - IMHO not worth the trouble.
Depends what you're doing, really.

> Does any compiler use copy in, copy out?
No idea.

> Of course inlining the whole function makes the question of calling
> convention meaningless.
Depends on the compiler; I'm aware of some compilers with pisspoor optimizers
which, when inlining, don't bother removing the prologue or epilogue code, so
the inlined function call looks exactly like a normal function call, except
without the jump or return.  In such a compiler the calling convention still
has an impact on inlined functions.  Of course, this isn't the least bit
desirable....

--
Now Playing:  Sandra - Secret land(ultra violet club) (D I G I T A L L Y - I M
P O R T E D - European Trance, Techno, Hi-NRG... we can't define it!)


char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 19 Oct 2003 19:29:53 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.18.09.24.17.883365@knm.org.pl>...
> On Sat, 18 Oct 2003 05:22:13 +0000, Bob Bell wrote:
>
> > Assuming the static cast succeeds, you've casted a and b to char&, then
> > applied the & operator to char&'s, which returns the address of a char,
> > then you compared the addresses of two chars.
>
> If this is not what you mean by "compare references", then what is?

I meant "there's no way to compare two references." What would make
you think "compare references" means "compare the addresses of objects
referred to by references?"

References are not objects -- there's nothing to compare.

> You mean "compare them by writing r1==r2"? Obviously you can't, because
> they are automatically dereferenced - I don't have to state that explicitly.

I mean "compare them by writing anything," as in "there's no way to
compare them by writing anything."

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sun, 19 Oct 2003 23:45:50 +0000 (UTC)
Raw View
On Sun, 19 Oct 2003 19:29:53 +0000, Bob Bell wrote:

> I meant "there's no way to compare two references." What would make you
> think "compare references" means "compare the addresses of objects
> referred to by references?"

Because references *are* addresses of objects.

(Please prove that they aren't, i.e. why this view would be wrong.)

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 20 Oct 2003 04:46:44 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") writes:

| On Sun, 19 Oct 2003 02:46:52 +0000, John Potter wrote:
|
| > The return type of function g is int&.  The expression g() is an lvalue of
| > type int.  It is consistent with the variable i.
|
| Unfortunately I don't have the final standard, but a public draft says
| otherwise (expr.call):
|
| 3 The  type  of  the  function call expression is the return type of the
|   statically chosen function (i.e., ignoring the virtual keyword),  even
|   if  the  type of the function actually called is different.  This type
|   shall be a complete object type, a reference type or the type void.

If you're going to do any elaboration on the semantics of a call, you have
to take into account:

5/6

  If an expression initially has the type  reference to T  (8.3.2,
  8.5.3), the type is adjusted to  T  prior to any further analysis,
  the expression designates the object or function denoted by the
  reference, and the expression is an lvalue.


--
                                                       Gabriel Dos Reis
                                           gdr@integrable-solutions.net

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 20 Oct 2003 04:47:32 +0000 (UTC)
Raw View
On Sun, 19 Oct 2003 17:37:17 +0000 (UTC), qrczak@knm.org.pl ("Marcin
'Qrczak' Kowalczyk") wrote:

> On Sun, 19 Oct 2003 02:46:52 +0000, John Potter wrote:

> > The return type of function g is int&.  The expression g() is an lvalue of
> > type int.  It is consistent with the variable i.

> Unfortunately I don't have the final standard, but a public draft says
> otherwise (expr.call):

> 3 The  type  of  the  function call expression is the return type of the
>   statically chosen function (i.e., ignoring the virtual keyword),  even
>   if  the  type of the function actually called is different.  This type
>   shall be a complete object type, a reference type or the type void.

No change in final.  So much for consistent.  10 A function call is an
lvalue if and only if the result type is a reference.

int i;
int& r(i);
int* p(&i);
int& g ();

i;   // an lvalue of type int
r;   // an lvalue of type int
*p;  // an lvalue of type int
g(); // an lvalue of type int&
static_cast<int const&>(i); // an lvalue of type ???

There may be something somewhere that says that for all purposes,
X& is of type X.  I seem to remember something like this, but it
may have been in a specific context.  Since references are figments
and there are no objects of those types, it seems absurd to talk
about a value as being of a reference type.  Since lvalues refer
to objects, an lvalue of type int& must refer to an object of type
int&, but there are none.  A defect?

My apologies for trying to make sense of law.

John

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 20 Oct 2003 05:07:27 +0000 (UTC)
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
+ On Sun, 19 Oct 2003 01:30:50 +0000 (UTC), qrczak@knm.org.pl ("Marcin
+ 'Qrczak' Kowalczyk") wrote:
+
+> I wonder about this too. For some unknown reason C++ doesn't say that i
+> has type int &. It says that it has type int and is an lvalue, where for
+>    int f();
+>    int &g();
+> the expression f() has type int too (but is an rvalue), and g() has type
+> int & (and thus is an lvalue). Why the type of i is said to be the same as
+> the type of f() and not g(), where things you can do with i are roughly
+> the same as for g() and not f()?
+
+ The return type of function g is int&.  The expression g() is an lvalue
+ of type int.  It is consistent with the variable i.

Of course, to those who know the quirks of the lanugage.  But, it's a
bit surprising to people who see that i has type int, and the return
value of g() is of type reference-to-int --- an unfortunate quirk.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Mon, 20 Oct 2003 16:15:49 +0000 (UTC)
Raw View
"Marcin 'Qrczak' Kowalczyk" wrote:
> On Sat, 18 Oct 2003 16:50:38 +0000, Balog Pal wrote:
>
>> I think I asked the question before and didn;t get an answer.  If we
>> should consider the reference as automatically derefered pointer, why we
>> should not consider the original names the same way?
>>
>> int i = 0;
>>
>> from now on 'i' works exactly as if it was really a pointer to an int, but
>> automatically dereferenced on any use.  Why not use these terms to i but
>> use
>>
>> to an int& ri=i;?
>
> I wonder about this too. For some unknown reason C++ doesn't say that i
> has type int &. It says that it has type int and is an lvalue, where for
>    int f();
>    int &g();
> the expression f() has type int too (but is an rvalue), and g() has type
> int & (and thus is an lvalue). Why the type of i is said to be the same as
> the type of f() and not g(), where things you can do with i are roughly
> the same as for g() and not f()?

Section 5 paragraph 6 says:

   "If an expression initially has the type "reference to T" (8.3.2,
    8.5.3), the type is adjusted to "T" prior to any further analysis,
    the expression designates the object or function denoted by the
    reference, and the expression is an lvalue."

which I interpret as meaning that expressions can't *really* have
reference type.

> C++ describes things in terms of lvalueness instead of using reference
> types. For example it says that the argument of unary & must be an lvalue
> and if it has type T, the &-expression has the type T *. And conversely
> for unary *. Since it must use reference types anyway, why doesn't it say
> that unary & converts between T & and T *, and unary * conversely, and not
> talk about lvalueness at all but distinguish them by their types (whether
> it's a reference or not)?

That would seem to make sense.  References do appear to be a way to
fit the lvalue concept into the type system (just as cv-qualifiers
are a way to fit access restrictions into the type system).

> Can C++ description be reworded using references instead of lvalueness?
> Are there any cases when C++ distinguishes between lvalue of type T from
> lvalue of type T &?

I think it might cause problems in some areas of the standard.
Bitfields would need some careful attention, for example, as their
special treatment doesn't really fit into the type system and so
references to bitfields aren't allowed.

I started a new thread to discuss standard definitions

> Note that with this treatment of lvalues it would be obvious that
> references carry the same information as pointers. You can use unary & and
> unary * to convert between them with no loss of information except null
> pointers.
>
> This shows that the disallowance of null references is rather artificial.

No it isn't!  Lvalues *must* evaluate to actual objects or functions
at run-time, and references are interchangeable with lvalues of the same
type, so references must follow the same rules.

> While it allows some minor optimizations (if the compiler is sure that
> an address is not null, some casts can be cheaper) the * operator itself
> doesn't act on the object and thus there would be no technical problem
> to allow null references. It's hard to imagine when a program using
> null references (illegally) actually breaks, except because of those
> optimizations.

On some machines, merely loading an address into an address register
causes pre-fetching from that address.  This, I believe, was the
main reason for the requirement on validity of lvalues in C and
subsequently C++.

>> Okey, lets use that view.  Just let's use it to everything we should -- so
>> include the original names too.
>
> Fine for me.
>
>> And more importantly,   we must point
>> out htat term 'pointer'  used in this view is not the same thing we call
>> 'pointer' in C/C++.    It is near, but not the same.  The mean difference
>> is that this pointer is NOT an *object*
>
> Why?

A C++ pointer is an object (has storage of which you can get the
address and size), but a C++ reference is not.  So if a reference
is described as a kind of pointer, this "pointer" must be something
other than a C++ pointer.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 20 Oct 2003 22:39:31 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") writes:

| On Sun, 19 Oct 2003 19:29:53 +0000, Bob Bell wrote:
|
| > I meant "there's no way to compare two references." What would make you
| > think "compare references" means "compare the addresses of objects
| > referred to by references?"
|
| Because references *are* addresses of objects.

if that were true then, given a reference r to an object, &r would be
the address of the address of the object.  Yet, that is not the case:
&r is the address of the refered-to object.

--
                                                       Gabriel Dos Reis
                                           gdr@integrable-solutions.net

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 20 Oct 2003 22:39:43 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.19.19.40.57.941520@knm.org.pl>...
> On Sun, 19 Oct 2003 19:29:53 +0000, Bob Bell wrote:
>
> > I meant "there's no way to compare two references." What would make you
> > think "compare references" means "compare the addresses of objects
> > referred to by references?"
>
> Because references *are* addresses of objects.
>
> (Please prove that they aren't, i.e. why this view would be wrong.)

One simple definition of "address" would be "the result of applying
the address-of operator (unary &)." If I apply unary & to an int do I
get an int&? No, I get an int*.

References don't behave like addresses. Addresses are objects,
references are not. I can perform arithmetic with addresses, but not
with references. I can put addresses into arrays and other containers,
but not references. I can copy and assign addresses, but not
references. How can they be the same if they behave so differently?

In this and the "No Subject Given" threads we've seen several examples
of misconceptions about references that have at their roots the idea
that references are really a special kind of pointer. How many more
such examples will you need?

Is this enough "proof"? I don't know if I've "proved" that references
aren't addresses, but it seems pretty obvious to me that they behave
so differently that they can't be the same.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl>
Date: Mon, 20 Oct 2003 21:56:17 CST
Raw View
On Mon, 20 Oct 2003 16:15:49 +0000, Ben Hutchings wrote:

>    "If an expression initially has the type "reference to T" (8.3.2,
>     8.5.3), the type is adjusted to "T" prior to any further analysis, the
>     expression designates the object or function denoted by the reference,
>     and the expression is an lvalue."

Great, this solves my doubt.

>> C++ describes things in terms of lvalueness instead of using reference
>> types. For example it says that the argument of unary & must be an
>> lvalue and if it has type T, the &-expression has the type T *. And
>> conversely for unary *. Since it must use reference types anyway, why
>> doesn't it say that unary & converts between T & and T *, and unary *
>> conversely, and not talk about lvalueness at all but distinguish them by
>> their types (whether it's a reference or not)?
>
> That would seem to make sense.

But this also implies that it would make perfect sense - all that is
changed is that you would say "value of type T&" instead of "lvalue of
type T", and "value of type T" instead of "rvalue of type T". It's only
a different naming scheme with isomorphic properties. The lvalueness bit
gets attached to the type. C++ already does that in the syntax. I believe
that in summary the presentation would be simpler.

> I think it might cause problems in some areas of the standard. Bitfields
> would need some careful attention, for example, as their special treatment
> doesn't really fit into the type system and so references to bitfields
> aren't allowed.

Right. But the translation of bitfield restrictions from the language of
lvalues to the language of references would probably be easy. You would
say that yes, you can form references to bitfields, but only for immediate
use as the argument of = or conversion to the corresponding non-reference
type.

>> This shows that the disallowance of null references is rather
>> artificial.
>
> No it isn't!  Lvalues *must* evaluate to actual objects or functions at
> run-time, and references are interchangeable with lvalues of the same
> type, so references must follow the same rules.

Only because C++ standard says so. I'm saying that it would not cause
problems for implementations (unless they indeed can have a simpler
representation of references than of pointers because of the null pointer)
nor for users (because it would only turn some undefined behavior into
defined).

> On some machines, merely loading an address into an address register
> causes pre-fetching from that address.  This, I believe, was the main
> reason for the requirement on validity of lvalues in C and subsequently
> C++.

I'm not saying that they should be able to process dangling references
with garbage representations, only the null reference. Your point would
be true if they are currently unable to use those address registers for
storing pointers. Are they? I'm saying that the reference could be allowed
to store as much as the pointer, not more; currently the only difference
is the null pointer.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Tue, 21 Oct 2003 18:45:39 +0000 (UTC)
Raw View
In article <c87c1cfb.0310192215.784ea203@posting.google.com>,
Bob Bell wrote:
> qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message
> news:<pan.2003.10.19.19.40.57.941520@knm.org.pl>...
>> On Sun, 19 Oct 2003 19:29:53 +0000, Bob Bell wrote:
>>
>> > I meant "there's no way to compare two references." What would make you
>> > think "compare references" means "compare the addresses of objects
>> > referred to by references?"
>>
>> Because references *are* addresses of objects.
>>
>> (Please prove that they aren't, i.e. why this view would be wrong.)
>
> One simple definition of "address" would be "the result of applying
> the address-of operator (unary &)." If I apply unary & to an int do I
> get an int&? No, I get an int*.
>
> References don't behave like addresses. Addresses are objects,
> references are not. I can perform arithmetic with addresses, but not
> with references.

You can perform arithmetic with *pointers*, and there are objects
(and rvalues, and lvalues) of *pointer* type.

<snip>
> Is this enough "proof"? I don't know if I've "proved" that references
> aren't addresses, but it seems pretty obvious to me that they behave
> so differently that they can't be the same.

You've conflated pointers with addresses.

Given any object or function, we can get a pointer or reference to
it, and given either of those we can get the other.  So they hold
the same information, and what is that if that if not an address
(in the abstract - not necessarily a memory address)?  One of them
is primarily useful for manipulating the address and the other is
primarily useful for manipulating the object it addresses, but
both of them hold addresses.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet@nmhq.net (Niklas Matthies)
Date: Fri, 24 Oct 2003 03:28:06 +0000 (UTC)
Raw View
On 2003-10-22 00:40, Bob Bell wrote:
> usenet@nmhq.net (Niklas Matthies) wrote:
[...]
>> I think we need to make the distinction between reference "entities"
>> and the reference "value" they hold. For example, in
>>
>>    int i = 5;
>>    int & f() { return i; }
>>    int & r1 = i;
>>    int & r2 = f();
>>
>> r1, r2 and the "temporary" resulting from the expression 'f()' would
>> be three different reference "entities", though all three hold the
>> same reference value (something that identifies the object named 'i').
>
> The term "value" implies certain things in C++: values can be copied
> and assigned, can be compared, can be temporary, etc.

Objects can be temporary, not values. And not all values can actually
be accessed for the purpose of assignment and comparison (for example
(signalling) NaNs, indeterminate pointer values, or in C the address
of an object with 'register' storage class). Being directly accessible
within the programming language is not a prerequisite for something to
be a value.

> None of those things apply to references, so it doesn't make sense
> to talk about an reference's "value."

Well, what _do_ you call the runtime thing that is passed back from
f() (as opposed to a reference entity like r1 and r2)? It's one thing
out of the possible set of things determined by the type 'int &'. In
general, a type defines (among other things) a set of values, where
each instance of the type represents one of these values at any given
moment (modulo trap representations and such). References fit this
model. The set is the set of (things that identify) int objects, and
each instance of reference type holds one element of that set at any
given moment. I would think that the term 'value' is quite adequate,
in particular for something that can get passed around at runtime.
The standard also doesn't define any special meaning for 'value'
that would contradict this.

-- Niklas Matthies

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Fri, 24 Oct 2003 19:48:29 +0000 (UTC)
Raw View
usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbph43t.9pm.usenet@nmhq.net>...
> On 2003-10-22 00:40, Bob Bell wrote:
> > usenet@nmhq.net (Niklas Matthies) wrote:
>  [...]
> >> I think we need to make the distinction between reference "entities"
> >> and the reference "value" they hold. For example, in
> >>
> >>    int i = 5;
> >>    int & f() { return i; }
> >>    int & r1 = i;
> >>    int & r2 = f();
> >>
> >> r1, r2 and the "temporary" resulting from the expression 'f()' would
> >> be three different reference "entities", though all three hold the
> >> same reference value (something that identifies the object named 'i').
> >
> > The term "value" implies certain things in C++: values can be copied
> > and assigned, can be compared, can be temporary, etc.
>
> Objects can be temporary, not values. And not all values can actually
> be accessed for the purpose of assignment and comparison (for example
> (signalling) NaNs, indeterminate pointer values, or in C the address
> of an object with 'register' storage class). Being directly accessible
> within the programming language is not a prerequisite for something to
> be a value.

I'll give you this one; I may have been typing too fast. However, you
haven't addressed my objection over the copying of references. To me,
that's the show-stopper. References are never copied, thus they
aren't/don't have values.

> > None of those things apply to references, so it doesn't make sense
> > to talk about an reference's "value."
>
> Well, what _do_ you call the runtime thing that is passed back from
> f() (as opposed to a reference entity like r1 and r2)?

I call it a reference.

int& r2 = f();

Calling f() creates a temporary int reference and initializes it with
the result of f(). The temporary reference is not copied from the
result of f(), it is initialized with the object to which f() refers;
this is an important distinction. The temporary int reference is then
used to initialize r2. Again, r2 is not copied from the temporary, it
is initialized with the object to which the temporary refers.

Consider:

int f();

int x;

x = f();

Here, calling f() produces a temporary int value which is initialized
with the result of calling f(). That temporary value is then _copied_
into x. There is no equivalent with references; references are never
copied.

> It's one thing
> out of the possible set of things determined by the type 'int &'. In
> general, a type defines (among other things) a set of values, where
> each instance of the type represents one of these values at any given
> moment (modulo trap representations and such). References fit this
> model.

Until you expand the model to account for all the things values can
do. Thus, references are not values, even if there is a little
overlap.

> The set is the set of (things that identify) int objects, and
> each instance of reference type holds one element of that set at any
> given moment. I would think that the term 'value' is quite adequate,
> in particular for something that can get passed around at runtime.
> The standard also doesn't define any special meaning for 'value'
> that would contradict this.

This is like saying that bananas and lemons are the same because they
are both yellow. You have identified one way in which values and
references are alike, but values and references have other properties
that preclude references from being values.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet@nmhq.net (Niklas Matthies)
Date: Sat, 25 Oct 2003 00:02:43 +0000 (UTC)
Raw View
On 2003-10-24 19:48, Bob Bell wrote:
> usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbph43t.9pm.usenet@nmhq.net>...
>> On 2003-10-22 00:40, Bob Bell wrote:
[...]
>> > The term "value" implies certain things in C++: values can be copied
>> > and assigned, can be compared, can be temporary, etc.
>>
>> Objects can be temporary, not values. And not all values can actually
>> be accessed for the purpose of assignment and comparison (for example
>> (signalling) NaNs, indeterminate pointer values, or in C the address
>> of an object with 'register' storage class). Being directly accessible
>> within the programming language is not a prerequisite for something to
>> be a value.
>
> I'll give you this one; I may have been typing too fast. However, you
> haven't addressed my objection over the copying of references. To me,
> that's the show-stopper. References are never copied, thus they
> aren't/don't have values.

They can be copy-initialized (or copy-constructed, to stay with C++
terminology):

   int i;
   int & r1 = i;
   int & r2 = r1;
   // r2 now refers to the same object that r1 refers to:
   // IOW, r2 now holds a copy of r1's reference value.
   // IYOW, a reference's value _is_ what object it refers to.

After being initialized, their value is immutable, but this doesn't
mean that there's no value.

>> > None of those things apply to references, so it doesn't make sense
>> > to talk about an reference's "value."
>>
>> Well, what _do_ you call the runtime thing that is passed back from
>> f() (as opposed to a reference entity like r1 and r2)?
>
> I call it a reference.
>
> int& r2 = f();
>
> Calling f() creates a temporary int reference and initializes it with
> the result of f().

What do you call the result of f() that the temporary int reference is
initialized with? Another temporary int reference?

> The temporary reference is not copied from the result of f(), it is
> initialized with the object to which f() refers;

What does that mean? It's certainly not the object that gets passed
around to initialize references with. Rather, it must be the object
location, or something equivalent to the object location, that gets
passed around. This is what I call a value.

> this is an important distinction. The temporary int reference is then
> used to initialize r2. Again, r2 is not copied from the temporary, it
> is initialized with the object to which the temporary refers.

So the temporary holds something, since it's initialized with
something and it doesn't become the object itself. Consider:

   int x, y;

   int & f() { return rand() % 2 ? x : y; }

   int & r = f();

The temporary reference created from the result of f() can either
refer to x or to y. This are two different possible values for that
temporary. What could be more straightforward than calling these
things values? Whoever invented the term lvalue (yes, I know it is
used to denote a syntactic construct) seemed to share that feeling.

> Consider:
>
> int f();
>
> int x;
>
> x = f();
>
> Here, calling f() produces a temporary int value which is initialized
> with the result of calling f(). That temporary value is then _copied_
> into x. There is no equivalent with references; references are never
> copied.

IMHO references are quite equivalent. There's no change in semantics
whatsoever when you view references as holding object-identifying
values that get passed around to initialize other references with,
just like int values get passed around to initialize (or possibly
reassign) other int objects with. The only difference between ints
and references here is that references can't be reassigned. But
that doesn't affect the "valueness", and actually the same can be
said to hold for const ints.

>> It's one thing
>> out of the possible set of things determined by the type 'int &'. In
>> general, a type defines (among other things) a set of values, where
>> each instance of the type represents one of these values at any given
>> moment (modulo trap representations and such). References fit this
>> model.
>
> Until you expand the model to account for all the things values can
> do. Thus, references are not values, even if there is a little
> overlap.

I didn't say that references are values, but that they hold values.
References doesn't grant gratuitous access to those values to a
program, but that doesn't concern the value itself.

If I write a smart (or dumb) pointer class that is non-copyable,
are its instances suddenly losing their valueness?

>> The set is the set of (things that identify) int objects, and
>> each instance of reference type holds one element of that set at any
>> given moment. I would think that the term 'value' is quite adequate,
>> in particular for something that can get passed around at runtime.
>> The standard also doesn't define any special meaning for 'value'
>> that would contradict this.
>
> This is like saying that bananas and lemons are the same because they
> are both yellow. You have identified one way in which values and
> references are alike, but values and references have other properties
> that preclude references from being values.

It seems that your understanding of "value" is somewhat narrower than
mine. Would you agree if I replaced "value" with "element of a set"?

-- Niklas Matthies

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 26 Oct 2003 08:19:15 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbph43t.9pm.usenet@nmhq.net>...
[...]
+> Well, what _do_ you call the runtime thing that is passed back from
+> f() (as opposed to a reference entity like r1 and r2)?
+
+ I call it a reference.
+
+ int& r2 = f();
+
+ Calling f() creates a temporary int reference and initializes it with
+ the result of f(). The temporary reference is not copied from the
+ result of f(), it is initialized with the object to which f() refers;
+ this is an important distinction.  The temporary int reference is then
+ used to initialize r2. Again, r2 is not copied from the temporary, it
+ is initialized with the object to which the temporary refers.
+
+ Consider:
+
+ int f();
+
+ int x;
+
+ x = f();
+
+ Here, calling f() produces a temporary int value which is initialized
+ with the result of calling f(). That temporary value is then _copied_
+ into x. There is no equivalent with references; references are never
+ copied.

So, consider:

  int* f();
  int* x = f();

Now x is "initialized with" the result of f(), just as r2 was
"initialized with" the result of f() in the reference example.
Of course, initialization is usually implemented by copying, but
that's not necessarily so in either the int& or the int* case.

+> It's one thing
+> out of the possible set of things determined by the type 'int &'. In
+> general, a type defines (among other things) a set of values, where
+> each instance of the type represents one of these values at any given
+> moment (modulo trap representations and such). References fit this
+> model.
+
+ Until you expand the model to account for all the things values can
+ do. Thus, references are not values, even if there is a little
+ overlap.
+
+> The set is the set of (things that identify) int objects, and
+> each instance of reference type holds one element of that set at any
+> given moment. I would think that the term 'value' is quite adequate,
+> in particular for something that can get passed around at runtime.
+> The standard also doesn't define any special meaning for 'value'
+> that would contradict this.
+
+ This is like saying that bananas and lemons are the same because they
+ are both yellow. You have identified one way in which values and
+ references are alike, but values and references have other properties
+ that preclude references from being values.

Each type has its own set of operators on its range of values.  So, of
course, values of some types will "do" things that values of other
types don't.  That's to be expected.  A green banana is still a
banana.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 27 Oct 2003 18:02:32 +0000 (UTC)
Raw View
usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbpj4mv.832.usenet@nmhq.net>...
>    int i;
>    int & r1 = i;
>    int & r2 = r1;
>    // r2 now refers to the same object that r1 refers to:
>    // IOW, r2 now holds a copy of r1's reference value.
>    // IYOW, a reference's value _is_ what object it refers to.
>
> After being initialized, their value is immutable, but this doesn't
> mean that there's no value.

You're right to say that r1 and r2 refer to the same object. Saying
that one is a copy of the other, however, is not supported, as far as
I know, by anything in the standard. If I'm wrong, please quote the
standard.

You seem to think that when r2 was initialized, it was done by copying
r1 somehow, but this doesn't match my understanding of references. In
_all_ contexts, use of a reference uses the object to which the
reference refers. Therefore, the use of r1 was actually a use of i,
and r2 was therefore initialized to refer to i.

The problem with your viewpoint is that it demands exceptions to what
are otherwise simple and clear rules.

[snip]

> > this is an important distinction. The temporary int reference is then
> > used to initialize r2. Again, r2 is not copied from the temporary, it
> > is initialized with the object to which the temporary refers.
>
> So the temporary holds something, since it's initialized with
> something and it doesn't become the object itself.

References don't "hold" anything.

The temporary is initialized to refer to the same object the return
result refers to. Nothing is copied.

Maybe your view comes from asking how the implementation makes this
happen. For all I know, the implementation probably passes as address
back from f(), but so what? We're talking about the logical behavior
of a C++ program here; looking too closely at how it's implemented is
distracting, and can even be misleading. For example, most compilers I
know of will eliminate the temporary; if we were to factor that in, we
might become confused about C++'s calling conventions, and then have
to create exceptions to those rules -- just as you have to create
exceptions to the rules about references (such as the "references
can't be copied" rule and the "use of a reference uses the underlying
object" rule).

The rules don't need exceptions; they already work as they are.

> Consider:
>
>    int x, y;
>
>    int & f() { return rand() % 2 ? x : y; }
>
>    int & r = f();
>
> The temporary reference created from the result of f() can either
> refer to x or to y.

So what? Calling f creates a reference that refers to an int. What
difference does it make whether you can predict which int it will
refer to?

> This are two different possible values for that
> temporary. What could be more straightforward than calling these
> things values?

Calling them references.

> Whoever invented the term lvalue (yes, I know it is
> used to denote a syntactic construct) seemed to share that feeling.

Huh? The term lvalue predates C++ by at least about a decade.

> > Consider:
> >
> > int f();
> >
> > int x;
> >
> > x = f();
> >
> > Here, calling f() produces a temporary int value which is initialized
> > with the result of calling f(). That temporary value is then _copied_
> > into x. There is no equivalent with references; references are never
> > copied.
>
> IMHO references are quite equivalent.

Please show how to write the equivalent of

int f();

int x;

x = f();

with references.

> There's no change in semantics
> whatsoever when you view references as holding object-identifying
> values that get passed around to initialize other references with,
> just like int values get passed around to initialize (or possibly
> reassign) other int objects with.

No, there's no change in semantics, just more complexity as things
that were formerly simple must be explained as exceptions.

> The only difference between ints
> and references here is that references can't be reassigned. But
> that doesn't affect the "valueness", and actually the same can be
> said to hold for const ints.

When we talk about "value semantics" we are primarily talking about
whether a type is copyable. So, yes, whether a type is copyable has a
lot to do with whether or not there are values of that type.

The const int analogy is a red herring; I may not be able to copy _to_
a const int, but I can copy _from_ a const int. Thus, a const int has
a value.

References can't be copied _to_ or copied _from_.

> It seems that your understanding of "value" is somewhat narrower than
> mine. Would you agree if I replaced "value" with "element of a set"?

I doubt I'll agree to anything that states that references are copied.

You can pretend references have values if you want, but that view
isn't supported by the standard and adds complexity for no real
benefit -- as you say, if you view references as having value, then
there isn't any semantic change (as long as you insert all the
exceptions you need in all the right places). So what's the point?

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Mon, 13 Oct 2003 17:48:08 +0000 (UTC)
Raw View
On Mon, 13 Oct 2003 06:51:10 +0000, Michael Terrazas wrote:

> But if your description causes confusion in some of your listeners, how
> beneficial is it?

Ok, what is a better description? For any description some people will be
confused... Maybe even some people will be confused by any description :-)

>> What is the difference between references and automatically dereferenced
>> const pointers which can't be null and can be bound to temporaries?
>
> Well, pointers CAN hold null, therefore they aren't the same, are they?

I don't say that references are the same as pointers, but that they are
similar enough that it's easier to describe them by explaining differences
from pointers than by explaining them separately from objects at all.

> I CAN create an array of const pointers, but I CANNOT create an
> array of references.

Ok, I forgot the third difference: you can't have pointers, references nor
arrays of references. And I didn't say that only references to const can
bind to temporaries.

It doesn't change my point. With a description without comparing to
pointers you too have to explain that references to const can bind to
temporaries while references to non-const can't - it doesn't follow from
their nature but it's an explicitly made decision which must be learned.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 13 Oct 2003 17:48:25 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.12.08.25.01.367587@knm.org.pl>...
> On Sun, 12 Oct 2003 02:02:19 +0000, Bob Bell wrote:
>
> > I frankly don't see the advantage in pretending that references are
> > automatically dereferenced pointers. What do you gain from this view?
>
> That you don't have to describe them from scratch using words which must
> be understood by intuition, but you can shortly describe them by words
> which must be known anyway from other parts of the language.

That logic applies to describing namespaces as "classes with no
non-static members, no virtual functions, don't support inheritance
and that can be defined in more than one place." For that matter, your
logic applies equally well to describing pointers in terms of
references.

I can see the benefit of _introducing_ a concept this way, but I don't
understand the benefit you get from sticking with such an introductory
view. After a while, it seems to be better to abandon the analogy (due
to the complexity of all of the exceptions) and just go with a new
concept in its own right. References _aren't_ pointers, they are their
own thing, just as namespaces _aren't_ classes, they are their own
thing.

> What is the difference between references and automatically dereferenced
> const pointers which can't be null and can be bound to temporaries?

How about "reference" is correct and "automatically dereferenced const
pointers which can't be null and can be bound to temporaries" is
incorrect (you forgot at least "can't be reseated", "can't be
compared", and "can't take the address of").

Which illustrates another problem with viewing references as "like
pointers, but...": the list after "but" is quite long.

Why is understanding references in terms of a long list of things they
are not better than a description of what they are?

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Mon, 13 Oct 2003 18:34:23 +0000 (UTC)
Raw View
On Mon, 13 Oct 2003 17:48:25 +0000, Bob Bell wrote:

> How about "reference" is correct and "automatically dereferenced const
> pointers which can't be null and can be bound to temporaries" is
> incorrect (you forgot at least "can't be reseated",

Follows from "const".

> "can't be compared",

They can be compared: &x == &y compares them.
That x == y doesn't compare them follows from "automatically dereferenced".

> and "can't take the address of").

Follows from "automatically dereferenced" and from the fact that &foo is
not an l-value.

> Why is understanding references in terms of a long list of things they
> are not better than a description of what they are?

IMHO the list of differences from pointers is short and easy to understand
- it doesn't use new concepts like "refers" or "names" or "alias" but
delegates its intuition to the "points to" of pointers and shares
lifetime issues, calling virtual functions, covariant return, template
parameter deduction, casts (except failed dynamic_cast) etc.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 13 Oct 2003 22:32:21 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bmbdln$smb$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + I frankly don't see the advantage in pretending that references are
> + automatically dereferenced pointers. What do you gain from this view?
>
> Advantage is a relative notion, and the predominant alternative to the
> automatically-dereferenced-pointer view is the references-are-aliases
> view.  Let's compare the usefulness of those two perspectives in
> resolving question and claims that people pose about references.
>
> Consider "int& r = a[i];".  Does *p get reevaluated each time r is
> used?  The references-are-aliases perspective cannot resolve that
> question, because "#define r a[i]" also make r an alias for "a[i]".

[snip]

> The list goes on and on.

For the record, I think the real problem with "references are aliases"
is that it merely shifts the question: so what is an alias?

In any case, this has never been (at least for me) a question of
whether references are better described as "pointers but..." or
"aliases". It's a question of whether or not references are best
described as "pointers but..." For me, the answer is a pretty obvious
no.

If I've got to have a list, I'd rather have it be a list of what
references _are_, instead of a list of what they are _not_.

For the heck of it, here's my attempt to define what a reference is:

A reference is an entity that names an object in the system. That
object can be an lvalue, or in the case of reference-to-const, can
also be an rvalue, in which case the rvalue is converted to an unnamed
object. Once initialized with an rvalue or lvalue, any use of a
reference is actually a use of the object the reference names.

This pretty much captures the way I think of references. I'd be
curious to hear where you think it falls down.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 14 Oct 2003 21:05:28 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
[...]
+ For the heck of it, here's my attempt to define what a reference is:
+
+ A reference is an entity that names an object in the system.
                                ^^^^^
As we've already noted, a name is a string of characters, which you
obviously don't mean.  Moreover, you've labeled as "silly" the notion
that aliases apply only to named objects.

+ That object can be an lvalue, or in the case of reference-to-const, can
+ also be an rvalue, in which case the rvalue is converted to an unnamed
+ object.

Lvalues and rvalues are *expressions*, syntactic objects that exist
only at compile time.

+ Once initialized with an rvalue or lvalue, any use of a
+ reference is actually a use of the object the reference names.

... which is what would happen with an automatically derefereced
pointer.

+ This pretty much captures the way I think of references. I'd be
+ curious to hear where you think it falls down.

See above.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 14 Oct 2003 21:05:36 +0000 (UTC)
Raw View
"Adam H. Peterson" <ahp6@email.byu.edu> wrote:
+ thp@cs.ucr.edu wrote:
+> + On the other hand, in terms of usage I foresee problems with a pointer
+> + type that is usually automatically dereferenced and sometimes not.  For
+> + example, in the context of these declarations:
+> +     T t1, t2;
+> +     ref<T> r1=t1, r2=t2;
+> + how would you handle the following operations:
+> +     t1=t2;  // This looks to me like a standard value assignment.
+> +             //   I expect you agree.
+> +     t1=r2;  // Again, a standard value assignment.
+> +     r1=t2;  // Is this a "reseating"?
+> +             //   If so, how do I say <r1's referent> gets
+> +             //   assigned the value of t2?
+> +             //   Also, this creates an odd asymmetry in assignment of
+> +             //   this type, although I admit it isn't the first
+> +             //   occurence of such in C++.
+> +     r1=r2;  // I assume this also is a "reseating", which begs
+> +             //   the same question as above.  How do I do value
+> +             //   assignment, without reseating?
+> + The ambiguities increase in number when you start to put ref<T> objects
+> + in containers.  Do you get containers of values or of handles?
+> + Whichever one you get, how do you derive the other?  (Not unaddressable,
+> + but it doesn't seem straightforward to me.)
+>
+> Presumably, to designate the referent of r1 via a normal lvalue, one
+> could write "*&r1" or more elegantly "referent(r1)" where referent is
+> defined: T& referent( ref<T> r ) { return r; }
+
+ So, you're telling me that:
+     r1=r2;
+ results in a reseating, but:
+     r1=&r2;
+ results in a value copy?  Or was it:
+     &r1=r2;
+ for a value copy?  Either way, this looks very poorly thought out to me.

But that's not what I wrote.  Please re-read.

+> + It becomes a real mess when
+> + you deal with associative containers, who cannot allow their "index"
+> + type to be mutable in any way that affects ordering.
+>
+> Many experts claim that it's a real mess to put pointers into
+> containers, but I've never found a way to avoid it.  It seems I always
+> have objects that I want to put on multiple lists.  In such cases,
+> however, I don't see that hiding this level of indirection would be
+> intrinsically dangerous, except that (for now) it would be
+> non-idiomatic.
+
+ Pointers in containers can be tricky.

Right.  And implicitly dereferenced pointers would be even trickier.
I'd recommend against using them that way.

+ I usually encapsulate indirect
+ containers.  But what I was talking specifically about is using ref<T>
+ values as keys in a map<> or set<> or such.  When a value is set in such
+ a container, the reference would be copied as the (indirect) key, but
+ when a comparison (of the general form less<>(ref<T> left, ref<T>
+ right)) occurs, their referent would be compared.  This looks to me like
+ a recipe for violating the class invariants of such containers.  When
+ you use pointers as keys, at least both copy and comparison is on the
+ address.

Good point.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: drpizza@anti-flash.co.uk ("DrPizza")
Date: Wed, 15 Oct 2003 02:05:46 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bm8riq$806$3@glue.ucr.edu...
> "DrPizza" <drpizza@anti-flash.co.uk> wrote:
> + <thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...
> +> Auto-dereferencing appears not to confuse Java, C#, and Python
> +> programmers.
> +
> + I disagree.  I've found plenty of Java programmers who are confused why
> + equality comparisons don't dereference (i.e. test identity) but member
access
> + does dereference.  It appears inconsistent to them.
>
> That's predictable for programmers who first learned value semantics,
> e.g., those who started with C or C++.  I've not heard that complaint
> from those who started with Java.

I have.  It is my experience that the value model is the more readily
understood.

--
Now Playing:  040 - Ibiza dreams (original mix) (D I G I T A L L Y - I M P O R
T E D - European Trance, Techno, Hi-NRG... we can't define it!)


char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Wed, 15 Oct 2003 04:43:02 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bmfsmb$5oo$3@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> [...]
> + For the heck of it, here's my attempt to define what a reference is:
> +
> + A reference is an entity that names an object in the system.
>                                 ^^^^^
> As we've already noted, a name is a string of characters, which you
> obviously don't mean.

No, of course I didn't mean that. Perhaps it's a poor choice of words.
I was trying to avoid the word "refers". By "names" I mean
"identifies" or "indicates". If you don't like "names", how about
"provides access to"?

> Moreover, you've labeled as "silly" the notion
> that aliases apply only to named objects.

Here is the "silly" passage you refer to:

> No. int& f(){return *new int;} (besides being poor code) returns a
> reference to a dynamically allocated int. The idea that aliases must
> be restricted to named objects is silly, and only obscures the issues.

I'm using the word "named" here in a different sense than in the
definition above. Here the phrase "named object" means an object that
already has an identifier associated with it. Your example "int&
f(){return *new int;}" shows how to create an (int) object which has
no identifier associated with it, and then you said that this example
somehow refuted the "references are aliases" view. My point was that
the idea that aliases only make sense when the aliased object already
has an identifier associated with it is "silly"; why should aliases be
restricted this way?

In any case, I don't subscribe to the "references are aliases" view,
because as I've said before it simply shifts the question without
really answering it.

> + That object can be an lvalue, or in the case of reference-to-const, can
> + also be an rvalue, in which case the rvalue is converted to an unnamed
> + object.
>
> Lvalues and rvalues are *expressions*, syntactic objects that exist
> only at compile time.

Then let's take that sentence out.

> + Once initialized with an rvalue or lvalue, any use of a
> + reference is actually a use of the object the reference names.
>
> ... which is what would happen with an automatically derefereced
> pointer.

...except I don't have to list all the pointer properties not shared
by references.

With some more massaging:

A reference is an entity that provides access to an object in the
system. Once initialized with an object, any use of a reference is
actually a use of the object the reference provides access to.

How about now? I think this is pretty close, and to me, this is a lot
simpler than a long list of exceptions.

In any case, we've come a far distance from the original topic. What
does this have to do with your ref<> idea again? ;-)

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 15 Oct 2003 19:22:38 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
[...]
+ With some more massaging:
+
+ A reference is an entity that provides access to an object in the
+ system. Once initialized with an object, any use of a reference is
+ actually a use of the object the reference provides access to.

+ How about now? I think this is pretty close, and to me, this is a lot
+ simpler than a long list of exceptions.

That definition relies on two undefined notions: "use" and "provides
access to".  Also, it would seem to provide very little information,
i.e., it doesn't answer a lot of obvious questions:
  - can references have names?
  - must references have names?
  - do they have scopes?
  - can functions return references?
  - can reference be arguments to functons?
  - lifetimes?  If so what is the lifetime of a referece?
  - can they dangle?  If so, how?
  - what's the difference between a reference to x and x itself?
The list goes on.

+ In any case, we've come a far distance from the original topic. What
+ does this have to do with your ref<> idea again? ;-)

Agreed.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 16 Oct 2003 02:21:51 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.12.08.25.01.367587@knm.org.pl>...
+> On Sun, 12 Oct 2003 02:02:19 +0000, Bob Bell wrote:
+>
+> > I frankly don't see the advantage in pretending that references are
+> > automatically dereferenced pointers. What do you gain from this view?
+>
+> That you don't have to describe them from scratch using words which must
+> be understood by intuition, but you can shortly describe them by words
+> which must be known anyway from other parts of the language.

[...]
+ For that matter, your
+ logic applies equally well to describing pointers in terms of
+ references.

Huh? How?

+ I can see the benefit of _introducing_ a concept this way, but I don't
+ understand the benefit you get from sticking with such an introductory
+ view. After a while, it seems to be better to abandon the analogy (due
+ to the complexity of all of the exceptions) and just go with a new
+ concept in its own right. References _aren't_ pointers, they are their
+ own thing, just as namespaces _aren't_ classes, they are their own
+ thing.
+
+> What is the difference between references and automatically dereferenced
+> const pointers which can't be null and can be bound to temporaries?
+
+ How about "reference" is correct and "automatically dereferenced const
+ pointers which can't be null and can be bound to temporaries" is
+ incorrect (you forgot at least "can't be reseated", "can't be
+ compared", and "can't take the address of").
+
+ Which illustrates another problem with viewing references as "like
+ pointers, but...": the list after "but" is quite long.
+
+ Why is understanding references in terms of a long list of things they
+ are not better than a description of what they are?

First of all, the list of exceptions to the claim that "references
behave like implicitly dereferenced pointers" is relatively short.  A
few years ago, I attempted to listed of all of them here or at
c.l.c.mod that came up during some very extensive newsgroup
discussions with James Kanze, Steve Clamage and some other very
knowledgeable folks.  IIRC, there were fewer than ten.  The list of
properties of references listed in the Standard would be several times
that long.  (Note that many of differences that you mention above,
e.g., that references cannot be reseated, are simple consequences of
the fact that they are implictly dereferenced in all context, except
initialization).

Regardless of the relative lengths of those lists, there are other
reasons:

  - Comparing and contrasting two related notions have well-known
    pedagogical benefits.

  - Learned facts about one notion immediately imply a related fact
    about the other, e.g., once one understands how pointers might
    dangle, one immediately understand that fact carries over to
    references.

  - This more accurate view of references dispells the common
    misimpressions that are left by claims that "references are
    aliases", e.g., that:
      * References require no space.
      * Functions can't return references.
      * References initialized by expressions are re-evaluated
        at each use.
      * Unlike pointers, reference can't dangle.  (If an alias
        is out of scope the compiler should catch it.)

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kristov@arcor.de ("Christoph Schulz")
Date: Thu, 16 Oct 2003 02:48:27 +0000 (UTC)
Raw View
"Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl> wrote:

> On Mon, 13 Oct 2003 17:48:25 +0000, Bob Bell wrote:
>
>> How about "reference" is correct and "automatically dereferenced
>> const pointers which can't be null and can be bound to
>> temporaries" is incorrect (you forgot at least "can't be
>> reseated",
>
> Follows from "const".
>
>> "can't be compared",
>
> They can be compared: &x == &y compares them.

That's not right. Consider

  class X {
     in operator& () const {return 42;}
  };

  X x, y, &r1 = x, &r2 = y;
  bool b = &r1 == &r2;

"b" will be true, because "&r1 == &r2" is a short form for
r1.operator&() == r2.operator&(). The references are not
compared, but the results of operator &() applied to the
referents. As you see, a user-defined operator&() can always
be defined in classes (as in the example above), so &r1 == &r2
is not correct _in all cases_ for comparing two references.

(You *could* de-type the objects the references refer to:

  bool b = &static_cast <char&>(r1)
    == &static_cast <char&>(r2);

but that is neither obvious nor understandable for anyone
not familiar with the internals of C++, I think.)

Regards,
  Christoph


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: drpizza@anti-flash.co.uk ("DrPizza")
Date: Thu, 16 Oct 2003 08:47:03 +0000 (UTC)
Raw View
""Marcin 'Qrczak' Kowalczyk"" <qrczak@knm.org.pl> wrote in message
news:pan.2003.10.11.09.20.15.757056@knm.org.pl...
> Why is this misleading?
'cos it ain't necessarily so.

> Why? You could say exactly the same about all const objects, that the
> compiler shouldn't allocate storage for them except when it's forced to
> (e.g. because the programmer takes its address, or to avoid recomputation
> of its value). But it's an unnecessary complication.
It's an accurate abstraction.  A reference's implementation /may/ require
storage, but it shouldn't be assumed to.

> It's simpler to not mention this choice and explain references as if they
> used storage, because it's always a valid compilation strategy,
But it's not always accurate.  Leaving the reference as an abstraction, on the
other hand, /is/ accurate.

> especially
> as it's almost always the only possible compilation strategy.
Not really.

> As an
> additional optimization the compiler is free to not allocate it if the
> result is the same, but it's already stated elsewhere that the program can
> be compiled differently if you can't observe the difference.
Why use a model that can be wrong when you can use a model that's always
right?

> And now you have been misled by your own definition!
> No, it would not be acceptable in general:
An unusual counter-example (aliasing of globals?  Who uses globals in this day
and age?) is hardly a demonstration that it can't be used in general.

True, C++ is hindered by the general assumption that aliasing can occur.  But
this will (or at least, should) change sooner rather than later and can in any
case be manually controlled to some degree in most or all mainstream compilers
anyway.

--
Now Playing:  Solar Stone - Seven Cities (armin van buuren remix) (D I G I T A
L L Y - I M P O R T E D - European Trance, Techno, Hi-NRG... we can't define
it!)

char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 16 Oct 2003 08:47:16 +0000 (UTC)
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bm8riq$806$3@glue.ucr.edu...
+> "DrPizza" <drpizza@anti-flash.co.uk> wrote:
+> + <thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...
+> +> Auto-dereferencing appears not to confuse Java, C#, and Python
+> +> programmers.
+> +
+> + I disagree.  I've found plenty of Java programmers who are confused why
+> + equality comparisons don't dereference (i.e. test identity) but member
+ access
+> + does dereference.  It appears inconsistent to them.
+>
+> That's predictable for programmers who first learned value semantics,
+> e.g., those who started with C or C++.  I've not heard that complaint
+> from those who started with Java.
+
+ I have.  It is my experience that the value model is the more readily
+ understood.

I'm happy to hear that, since I advocate C++ for our students.  But it
goes against what I hear both from students who started with Java and
from colleagues who've taught both langauges.  But I'm dealing with
somewhat small sample sizes.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Thu, 16 Oct 2003 20:07:59 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bmh1sa$ev4$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.12.08.25.01.367587@knm.org.pl>...
> +> On Sun, 12 Oct 2003 02:02:19 +0000, Bob Bell wrote:
> +>
> +> > I frankly don't see the advantage in pretending that references are
> +> > automatically dereferenced pointers. What do you gain from this view?
> +>
> +> That you don't have to describe them from scratch using words which must
> +> be understood by intuition, but you can shortly describe them by words
> +> which must be known anyway from other parts of the language.
>
> [...]
> + For that matter, your
> + logic applies equally well to describing pointers in terms of
> + references.
>
> Huh? How?

I could easily argue that references "must be known anyway from other
parts of the language", and that I could therefore "shortly describe
[pointers] by words which must be known anyway from other parts of the
language". In other words, his logic applies equally well to demanding
that references be understood initially, and understanding of pointers
built on top of references.

> + Why is understanding references in terms of a long list of things they
> + are not better than a description of what they are?
>
> First of all, the list of exceptions to the claim that "references
> behave like implicitly dereferenced pointers" is relatively short.  A
> few years ago, I attempted to listed of all of them here or at
> c.l.c.mod that came up during some very extensive newsgroup
> discussions with James Kanze, Steve Clamage and some other very
> knowledgeable folks.  IIRC, there were fewer than ten.  The list of
> properties of references listed in the Standard would be several times
> that long. (Note that many of differences that you mention above,
> e.g., that references cannot be reseated, are simple consequences of
> the fact that they are implictly dereferenced in all context, except
> initialization).

The point of the question "Why is understanding references in terms of
a long list of things they are not better than a description of what
they are?" is really "why is the cost of this view ("references are
pointers except...") better than the cost of the other view
("references are...")?" Because there _are_ costs to viewing
references as pointers; if you want to ignore those costs or pretend
you aren't paying them, then there doesn't seem to be much else to
discuss. If you think the costs just aren't that big a deal, that the
costs of viewing references in their own right are worse, then we'll
have to agree to disagree.

> Regardless of the relative lengths of those lists, there are other
> reasons:
>
>   - Comparing and contrasting two related notions have well-known
>     pedagogical benefits.

Agreed. But "comparing and contrasting" is not the same as "defining A
in terms of B", which is what I object to.

>   - Learned facts about one notion immediately imply a related fact
>     about the other, e.g., once one understands how pointers might
>     dangle, one immediately understand that fact carries over to
>     references.

But one is left with no guidance as to when facts carry over from
pointers to references, and when they don't. Why can't references be
placed in arrays? Because you believe references are really a kind of
pointer, this seems like an arbitrary restriction. Because I
understand that references and pointers are separate concepts, I have
no trouble with the restriction. Specifically:

-- arrays contain values
-- references (by definition) do not have values
-- therefore, arrays can't contain references

>   - This more accurate view of references dispells the common
>     misimpressions that are left by claims that "references are
>     aliases", e.g., that:
>       * References require no space.
>       * Functions can't return references.
>       * References initialized by expressions are re-evaluated
>         at each use.
>       * Unlike pointers, reference can't dangle.  (If an alias
>         is out of scope the compiler should catch it.)

These objections are circular; they assume a definition of "alias"
which precludes the conclusion "references are aliases."

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 17 Oct 2003 04:08:53 +0000 (UTC)
Raw View
"Christoph Schulz" <kristov@arcor.de> wrote:
+ "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl> wrote:
+
+> On Mon, 13 Oct 2003 17:48:25 +0000, Bob Bell wrote:
+>
+>> How about "reference" is correct and "automatically dereferenced
+>> const pointers which can't be null and can be bound to
+>> temporaries" is incorrect (you forgot at least "can't be
+>> reseated",
+>
+> Follows from "const".
+>
+>> "can't be compared",
+>
+> They can be compared: &x == &y compares them.
+
+ That's not right. Consider
+
+  class X {
+     in operator& () const {return 42;}
+  };
+
+  X x, y, &r1 = x, &r2 = y;
+  bool b = &r1 == &r2;
+
+ "b" will be true, because "&r1 == &r2" is a short form for
+ r1.operator&() == r2.operator&(). The references are not
+ compared, but the results of operator &() applied to the
+ referents. As you see, a user-defined operator&() can always
+ be defined in classes (as in the example above), so &r1 == &r2
+ is not correct _in all cases_ for comparing two references.
+
+ (You *could* de-type the objects the references refer to:
+
+  bool b = &static_cast <char&>(r1)
+    == &static_cast <char&>(r2);
+
+ but that is neither obvious nor understandable for anyone
+ not familiar with the internals of C++, I think.)

You're right, of course.  But Marcin was responding to the claim that
references "can't be compared", but usually they can be.  Obviously,
if one overloads unary-&, it becomes much more tedious to compare
them, but (thanks) you've provided the solution to that case.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: drpizza@anti-flash.co.uk ("DrPizza")
Date: Fri, 17 Oct 2003 05:06:53 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bm8rci$806$2@glue.ucr.edu...
> "DrPizza" <drpizza@anti-flash.co.uk> wrote:
> [...]
> + In general, a compiler should
> + set aside no storage for a reference (i.e. the reference should exist
purely
> + as a name for the programmer to manipulate without any representation).
The
> + exception is passing by reference.  In this situation an address may be
> + needed, though I would think that for e.g. small built-in types copy in,
copy
> + out would be an acceptable and sometimes desirable implementation.
>
>
> Consider:
>
>   class Widget {
>     ...
>     Whatever& r;
>     Widget(...) r(*new Whatever) {...}
>     ...
>   }
>
> And suppose the number of widgets we create has to do with external
> input.  How do you propose to implement Widget without setting aside
> storage for holding the address of r's referent, just as you would if
> r were a const pointer?


Reference members are (or probably should be) a rarity.  I said "in general".
In some situations there may be no choice but to have a unreseatable pointer.
In some situations it may be desirable (e.g. arguments longer than maybe two
pointers in length).  But for something such as:

int i;
int& ri(i);
std::cout << ri << std::endl;

or

namespace
{
void foo(int& i)
{ ++i; }
}

int main()
{
    int i(0);
    foo(i);
    std::cout << i << std::endl;
}

or what have you, the reference should in the first case be eliminated
entirely (no code representation at all, purely a convenience for the
programmer), and in the second it ought to use copy in, copy out (or be
inlined away entirely, of course).


--
Now Playing:  Solar Stone - Seven Cities (armin van buuren remix) (D I G I T A
L L Y - I M P O R T E D - European Trance, Techno, Hi-NRG... we can't define
it!)


char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Fri, 17 Oct 2003 15:32:05 +0000 (UTC)
Raw View
On Fri, 17 Oct 2003 05:06:53 +0000, DrPizza wrote:

> int i;
> int& ri(i);
> std::cout << ri << std::endl;

I don't see why a programmer would want to make a reference like this.

> and in the second it ought to use copy in, copy out (or be
> inlined away entirely, of course).

It's impractical for a compiler to implement this as copy in, copy out.
Since it doesn't work in all cases, there would have to be two calling
conventions for pasing reference parameter (of the same type). Because
of function pointers, thye compiler would have to either emit two entry
points for a function using references, or apply the copy in, copy out
technique only to static functions / private methods which don't have
their pointer taken where the compiler was able to make sure that this
technique is safe - IMHO not worth the trouble.

Does any compiler use copy in, copy out?

Of course inlining the whole function makes the question of calling
convention meaningless.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sat, 18 Oct 2003 05:22:13 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bmld3v$kei$2@glue.ucr.edu>...
> "Christoph Schulz" <kristov@arcor.de> wrote:
> + "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl> wrote:
> +
> +> On Mon, 13 Oct 2003 17:48:25 +0000, Bob Bell wrote:
> +>
> +>> How about "reference" is correct and "automatically dereferenced
> +>> const pointers which can't be null and can be bound to
> +>> temporaries" is incorrect (you forgot at least "can't be
> +>> reseated",
> +>
> +> Follows from "const".
> +>
> +>> "can't be compared",
> +>
> +> They can be compared: &x == &y compares them.
> +
> + That's not right. Consider
> +
> +  class X {
> +     in operator& () const {return 42;}
> +  };
> +
> +  X x, y, &r1 = x, &r2 = y;
> +  bool b = &r1 == &r2;
> +
> + "b" will be true, because "&r1 == &r2" is a short form for
> + r1.operator&() == r2.operator&(). The references are not
> + compared, but the results of operator &() applied to the
> + referents. As you see, a user-defined operator&() can always
> + be defined in classes (as in the example above), so &r1 == &r2
> + is not correct _in all cases_ for comparing two references.
> +
> + (You *could* de-type the objects the references refer to:
> +
> +  bool b = &static_cast <char&>(r1)
> +    == &static_cast <char&>(r2);
> +
> + but that is neither obvious nor understandable for anyone
> + not familiar with the internals of C++, I think.)
>
> You're right, of course.  But Marcin was responding to the claim that
> references "can't be compared", but usually they can be.  Obviously,
> if one overloads unary-&, it becomes much more tedious to compare
> them, but (thanks) you've provided the solution to that case.

I responded to Marcin's post, but somehow it got lost.

Sorry, references can never be compared, period. No matter how you
slice it,

Foo a, b;
Foo& ra = a, rb = b;

ra == rb;

will always compare the Foo objects.

&ra == &rb;

will always apply the & operator to a and b and compare the results,
whether the & operator is overloaded or not.

&static_cast <char&>(ra) == &static_cast <char&>(rb);

Assuming the static cast succeeds, you've casted a and b to char&,
then applied the & operator to char&'s, which returns the address of a
char, then you compared the addresses of two chars.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Sat, 18 Oct 2003 16:50:38 +0000 (UTC)
Raw View
[repost attempt -- I see no sign of approving the original in several days,
though i got a 'received' notification. drop this if finally got through]

<thp@cs.ucr.edu> wrote in message news:bmbdln$smb$1@glue.ucr.edu...

>    - Case 1: D&E states that the ability to initialize const
>      references from non-lvalues is important because "this is what
>      allows a Fortran function to be called with a constant".  Definitely
>      not intrinsic to the notion of reference.

I recall the time period when binding temp to nonconst ref worked, and then
stoppped working. Uncovering a few questionable points in the codebase I
maintained.  (Can't remember whether any of those actually lead to defects
but I could understand he reasons removing that danger.)

But unability to pass temporaries to functions with const & params would
cripple the language to almost useless.  (It seems to me.)   So maybe an
initial reason was that fortran thingy, but we shall not think of it as some
strong reason shading others.

> Consider "int& r = a[i];".  Does *p get reevaluated each time r is
> used?  The references-are-aliases perspective cannot resolve that
> question, because "#define r a[i]" also make r an alias for "a[i]".

You seem still not get what the alias concept refers to.
"alias" means "another name". Another name to an *object*. You do not and
can not name an expression (like that).  a[i] is an expression, it just
can't play role here.

And textual replacement is completely different thing than an alias.
[whoever remembers MASM, both alias and text could be  created using   EQU
but  they  were listed separately in the symbol table.]

I think I asked the question before and didn;t get an answer.  If we should
consider the reference as automatically derefered pointer, why we should not
consider the original names the same way?

int i = 0;

from now on 'i' works exactly as if it was really a pointer to an int, but
automatically dereferenced on any use.  Why not use these terms to i but use

to an int& ri=i;?
Or if we do use that, why it is not acceptable, that there's no difference
between behavior of names i and ri, so we could treat them the same way?
[certainly after moment they're created.]

> If one thinks that all references (except those used to pass objects)
> are mere aliases, it's reasonable to expect that they can go away
> after compilation.

I try to find reason why that should happen and see none. For that same
reason everything should go away, leaving nothing.

> The automatically-dereferenced-pointer view makes
> it clear that the run-time state of references has to be stored unless
> in can be inferred at compile time, which can't happen when the
> referent or its location isn't known until run time.

Okey, lets use that view.  Just let's use it to everything we should -- so
include the original names too.   And more importantly,   we must point out
htat term 'pointer'  used in this view is not the same thing we call
'pointer' in C/C++.    It is near, but not the same.  The mean difference is
that this pointer is NOT an *object* while the real C++ pointer IS an
*object*.     If we do that distinction, someone will probably say 'not
rally productive to call different things using the same term in close
context, it leads to confusion'.  If we do not do that distinction we do
lie.

> Consider the question of whether a reference can dangle.  Everyone
> knows that pointers can dangle, and everyone knows how and why that
> happens.  But what's meant by "a dangling alias"?

Object lifetime issues shall be taught carefully.    I honestly dislike
'dangling' and  approach the problem from that side.  And IMHO there's no
wander if you get in trouble explaining things on that path.  As dropping in
placement new and explicit dtor calls you can create dangling primary
objects too.     Though it;s the most common way to handle dynamic objects
using pointers,   lifetime issues are bound to the objects, not the
pointerrs, or references or names used to reach that object.    and the rule
to grasp is the object shall live whatever way you reach it.

And dhe idea of lifetime and validiti of a referent is an even broader one
in programming, think STL iterators as a good example.

We can reach to the abstract concept of a 'pointer' what is nothing more
than an item referring to some other item.      Explaining references and
everything else using that is IMHO not a bad way, just aviod the homonime
problem somehow.

> Consider the question of whether the return value of a function can be
> a reference, and, if so, what does it mean to return a reference.

The function call is an expression. If the function's return type is a
reference, it is an lvalue expression.   I fail to see the problem.
IMHO it's more productive to think in language concept elements (here
expression)  than in some picked implementation  (say: function returns an
address in register EAX).

> >From the automatically-dereferenced-pointer perspective, the answer is
> obvious.  But from the references-are-aliases perspective we are left
> to wonder exactly what alias gets returned.

Gee, but the whole purpose of an alias is that you not think of it as an
alias, but as the *same* as the original.

The function psoduce an object (or select one already existing) and return
it.  Either as rvalue or lvalue.

Those are (AFAIK) the C++ terms.   [hope somebody of the C++ gurus still
read this thread and can tell whether it's so or I managed to confuse
myself.]

Then you can teach lvalues as an 'address' or 'location' and rvalue as the
'content'.

But washing together 'pointer' with either 'address' or 'lvalue' is not
good. That is a one way road -- pointers can be explained with these same
term, as pointer will be an object whose rvalue is something else's address.

Paul




---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sat, 18 Oct 2003 16:51:44 +0000 (UTC)
Raw View
On Sat, 18 Oct 2003 05:22:13 +0000, Bob Bell wrote:

> Assuming the static cast succeeds, you've casted a and b to char&, then
> applied the & operator to char&'s, which returns the address of a char,
> then you compared the addresses of two chars.

If this is not what you mean by "compare references", then what is?

You mean "compare them by writing r1==r2"? Obviously you can't, because
they are automatically dereferenced - I don't have to state that explicitly.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sun, 19 Oct 2003 01:30:50 +0000 (UTC)
Raw View
On Sat, 18 Oct 2003 16:50:38 +0000, Balog Pal wrote:

> I think I asked the question before and didn;t get an answer.  If we
> should consider the reference as automatically derefered pointer, why we
> should not consider the original names the same way?
>
> int i = 0;
>
> from now on 'i' works exactly as if it was really a pointer to an int, but
> automatically dereferenced on any use.  Why not use these terms to i but
> use
>
> to an int& ri=i;?

I wonder about this too. For some unknown reason C++ doesn't say that i
has type int &. It says that it has type int and is an lvalue, where for
   int f();
   int &g();
the expression f() has type int too (but is an rvalue), and g() has type
int & (and thus is an lvalue). Why the type of i is said to be the same as
the type of f() and not g(), where things you can do with i are roughly
the same as for g() and not f()?

C++ describes things in terms of lvalueness instead of using reference
types. For example it says that the argument of unary & must be an lvalue
and if it has type T, the &-expression has the type T *. And conversely
for unary *. Since it must use reference types anyway, why doesn't it say
that unary & converts between T & and T *, and unary * conversely, and not
talk about lvalueness at all but distinguish them by their types (whether
it's a reference or not)?

Can C++ description be reworded using references instead of lvalueness?
Are there any cases when C++ distinguishes between lvalue of type T from
lvalue of type T &?

Note that with this treatment of lvalues it would be obvious that
references carry the same information as pointers. You can use unary & and
unary * to convert between them with no loss of information except null
pointers.

This shows that the disallowance of null references is rather artificial.
While it allows some minor optimizations (if the compiler is sure that
an address is not null, some casts can be cheaper) the * operator itself
doesn't act on the object and thus there would be no technical problem
to allow null references. It's hard to imagine when a program using
null references (illegally) actually breaks, except because of those
optimizations.

> Okey, lets use that view.  Just let's use it to everything we should -- so
> include the original names too.

Fine for me.

> And more importantly,   we must point
> out htat term 'pointer'  used in this view is not the same thing we call
> 'pointer' in C/C++.    It is near, but not the same.  The mean difference
> is that this pointer is NOT an *object*

Why?

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sun, 19 Oct 2003 02:46:52 +0000 (UTC)
Raw View
On Sun, 19 Oct 2003 01:30:50 +0000 (UTC), qrczak@knm.org.pl ("Marcin
'Qrczak' Kowalczyk") wrote:

> I wonder about this too. For some unknown reason C++ doesn't say that i
> has type int &. It says that it has type int and is an lvalue, where for
>    int f();
>    int &g();
> the expression f() has type int too (but is an rvalue), and g() has type
> int & (and thus is an lvalue). Why the type of i is said to be the same as
> the type of f() and not g(), where things you can do with i are roughly
> the same as for g() and not f()?

The return type of function g is int&.  The expression g() is an lvalue
of type int.  It is consistent with the variable i.

John

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sun, 19 Oct 2003 17:37:17 +0000 (UTC)
Raw View
On Sun, 19 Oct 2003 02:46:52 +0000, John Potter wrote:

> The return type of function g is int&.  The expression g() is an lvalue of
> type int.  It is consistent with the variable i.

Unfortunately I don't have the final standard, but a public draft says
otherwise (expr.call):

3 The  type  of  the  function call expression is the return type of the
  statically chosen function (i.e., ignoring the virtual keyword),  even
  if  the  type of the function actually called is different.  This type
  shall be a complete object type, a reference type or the type void.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet@nmhq.net (Niklas Matthies)
Date: Tue, 21 Oct 2003 18:46:06 +0000 (UTC)
Raw View
On 2003-10-20 22:39, Bob Bell wrote:
> qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.19.19.40.57.941520@knm.org.pl>...
>> On Sun, 19 Oct 2003 19:29:53 +0000, Bob Bell wrote:
>>
>> > I meant "there's no way to compare two references." What would make you
>> > think "compare references" means "compare the addresses of objects
>> > referred to by references?"
>>
>> Because references *are* addresses of objects.
>>
>> (Please prove that they aren't, i.e. why this view would be wrong.)
>
> One simple definition of "address" would be "the result of applying
> the address-of operator (unary &)." If I apply unary & to an int do I
> get an int&? No, I get an int*.
>
> References don't behave like addresses. Addresses are objects,

I'd say that addresses are values. One question to ask is whether
references are values, or hold an (immutable) value. Then, if we
accept that (the combination of a type and) an address uniquely
identifies an object or function (and nothing more), then a (typed)
reference value is equivalent to (= represents the the same
information as) a (typed) address.

[...]
> Is this enough "proof"? I don't know if I've "proved" that references
> aren't addresses, but it seems pretty obvious to me that they behave
> so differently that they can't be the same.

I think we need to make the distinction between reference "entities"
and the reference "value" they hold. For example, in

   int i = 5;
   int & f() { return i; }
   int & r1 = i;
   int & r2 = f();

r1, r2 and the "temporary" resulting from the expression 'f()' would
be three different reference "entities", though all three hold the
same reference value (something that identifies the object named 'i').

-- Niklas Matthies

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Wed, 22 Oct 2003 00:40:35 +0000 (UTC)
Raw View
do-not-spam-benh@bwsint.com (Ben Hutchings) wrote in message news:<slrnbpa3rl.1ho.do-not-spam-benh@tin.bwsint.com>...
> In article <c87c1cfb.0310192215.784ea203@posting.google.com>,
> Bob Bell wrote:
> > Is this enough "proof"? I don't know if I've "proved" that references
> > aren't addresses, but it seems pretty obvious to me that they behave
> > so differently that they can't be the same.
>
> You've conflated pointers with addresses.

Sure, but in the context of the discussion, that was appropriate. This
subthread began when I refuted the claim that references could be
compared by comparing the addresses of the objects the references
refer to, as in

bool b = &static_cast <char&>(r1) == &static_cast <char&>(r2);

Note that in this context, address == pointer, because what really
gets compared are the values of the (temporary) pointers returned from
applying the unary & operator. If I had used the word "pointer"
throughout the discussion, perhaps your objection could have been
avoided.

> Given any object or function, we can get a pointer or reference to
> it, and given either of those we can get the other.  So they hold
> the same information, and what is that if that if not an address
> (in the abstract - not necessarily a memory address)?  One of them
> is primarily useful for manipulating the address and the other is
> primarily useful for manipulating the object it addresses, but
> both of them hold addresses.

I don't really see how this matters. So I can do similar things with
pointers and references; so what? It's the differences that prove my
point, and you haven't addressed them.

Look, this whole discussion has been about whether or not it makes
sense to view references as "a kind of pointer." I claim it doesn't. I
claim that using this view leads to confusion and mistakes, and the
history of this and the "No subject given" thread have supported this
claim, as proponents of the "references are pointers" view have
demonstrated confusion and mistakes. Examples:

Why can't I have a NULL reference?

Why can't I put references into arrays like I can put pointers into
arrays?

Why can't I compare two references like I can compare pointers?

Why can't I assign a reference to refer to another object like I can
with pointers?

For those who view references as a kind of pointer, these questions
are confusing and/or have arbitrary answers that must simply be
memorized. However, for those who see references for what they are,
these questions all have simple, logical answers.

Why can't I have a NULL reference?

Because references by definition must refer to an existing object.
NULL references don't make sense.

Why can't I put references into arrays like I can put pointers into
arrays?

Arrays contain values. References aren't values. Therefore, arrays
can't hold references.

Why can't I compare two references like I can compare pointers?

Comparison works on values. References aren't values. Therefore,
references can't be compared.

Why can't I assign a reference to refer to another object like I can
with pointers?

Assignment is defined in terms of rvalues and lvalues. There is no
lvalue associated with a reference itself. Therefore, there is no way
to apply the assignment operator to a reference.

The "references are pointers" view provides no guideline for when
references stop being just like pointers and start following other
rules. All of the above questions demonstrate this. Here's another
example: I can't initialize a pointer to point to a temporary, but I
can create a reference that refers to a temporary. Why is that? The
"references are pointers" view is silent on this question.

It has been claimed that those new to references may have an easier
time being introduced to references as a simplified, automatically
dereferenced pointer. However, there is no guarantee that the subject
has any familiarity with pointers; for these subjects, there is no
gain, and in fact there is additional cost, as the subject must first
be taught pointers. Given the subtleties associated with pointers
(such as pointer/array duality), pointers are not often introduced
early to newcomers.

But assuming that the subject already has a grasp of pointers, this
introductory view is useful as exactly that: an introductory view.
Precisely because the "references are pointers" view doesn't scale
well, it is better to abandon this view when the subtleties of
references are encountered, lest the subject fall prey to the
misconceptions and confusion I illustrated earlier.

Given all these cognitive negatives, what could motivate one to cling
to the "references are pointers" view? Perhaps viewing references and
pointers as variations on a theme is simpler.

It should be pretty obvious by now what I think of that idea. How can
one idea which leads to "misconception and confusion" be simpler than
two separate ideas which allow correct reasoning?

Elsewhere in this thread I asked "why is the cost of the "references
are pointers" view better than the cost of an independent view of
references?" (I'm paraphrasing.) There are costs associated with both
views.

The independent views ("references and pointers are two different
things") carry the cost of demanding more mental muscle power up
front, since two separate concepts must be understood. (Although I
could argue that this isn't really the case, since an understanding of
pointers is completely unnecessary for understanding references, so
the cost of understanding pointers shouldn't be included in the cost
of understanding references.) The benefit is correct reasoning about
the behavior of references and pointers. This amounts to a short-term
cost and a long-term benefit.

The combined view ("references are pointers") view has the benefit of
appearing to require less mental muscle power. However, the cost is
dealing with surprises and problems that come up when it turns out
that references don't really behave like pointers -- leaving one
wondering what the differences are, why they exist, how they can be
avoided, etc. This amounts to a short-term benefit and a long-term
cost.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Wed, 22 Oct 2003 00:40:52 +0000 (UTC)
Raw View
usenet@nmhq.net (Niklas Matthies) wrote in message news:<slrnbpajsd.143d.usenet@nmhq.net>...
> On 2003-10-20 22:39, Bob Bell wrote:
> > qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.19.19.40.57.941520@knm.org.pl>...
> >> On Sun, 19 Oct 2003 19:29:53 +0000, Bob Bell wrote:
> >>
> >> > I meant "there's no way to compare two references." What would make you
> >> > think "compare references" means "compare the addresses of objects
> >> > referred to by references?"
> >>
> >> Because references *are* addresses of objects.
> >>
> >> (Please prove that they aren't, i.e. why this view would be wrong.)
> >
> > One simple definition of "address" would be "the result of applying
> > the address-of operator (unary &)." If I apply unary & to an int do I
> > get an int&? No, I get an int*.
> >
> > References don't behave like addresses. Addresses are objects,
>
> I'd say that addresses are values.

Agreed.

> One question to ask is whether
> references are values,

They're not.

> or hold an (immutable) value.

They don't.

> Then, if we
> accept that (the combination of a type and) an address uniquely
> identifies an object or function (and nothing more), then a (typed)
> reference value is equivalent to (= represents the the same
> information as) a (typed) address.

Throughout this discussion, we've seen posts along the lines of
"references and pointers are similar because of XYZ, so doesn't it
make sense to view them as the same thing?" This question ignores the
differences between references and pointers; it is their (significant)
differences that make it more sensible to not combine the concepts.

> [...]
> > Is this enough "proof"? I don't know if I've "proved" that references
> > aren't addresses, but it seems pretty obvious to me that they behave
> > so differently that they can't be the same.
>
> I think we need to make the distinction between reference "entities"
> and the reference "value" they hold. For example, in
>
>    int i = 5;
>    int & f() { return i; }
>    int & r1 = i;
>    int & r2 = f();
>
> r1, r2 and the "temporary" resulting from the expression 'f()' would
> be three different reference "entities", though all three hold the
> same reference value (something that identifies the object named 'i').

The term "value" implies certain things in C++: values can be copied
and assigned, can be compared, can be temporary, etc. None of those
things apply to references, so it doesn't make sense to talk about an
reference's "value."

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Wed, 8 Oct 2003 17:46:15 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<blre5d$h1f$1@glue.ucr.edu>...

> "Balog Pal" <pasa@lib.hu> wrote:
> > <thp@cs.ucr.edu> wrote in message news:bldutm$4da$1@glue.ucr.edu...

> >> > consider this:

> >> > void Foo(Whatever a, Whatever b)
> >> > {
> >> >    a = b;

> >> >    b >= 1;     b.Increment(); // do anything that changes the state of b
> >> > here

> >> >    // ** what here
> >> > }

> > You didn;t consider the meat of this example did you?
> > BTW it's the same case James Kanze pointed out on the other group
> > with dimension. Please try to understand what is the problem with
> > the approach, and how it leads to errors in current java.  As soon
> > as you have mutable objects.

> Perhaps I missed your point, which IIUC is that in Java variables of
> built-in types have value semantics, while variables of class types
> have reference semantics, and the two semantics coincide on immutable
> objects but not on objects (since reference semantics involves an
> added level of indirection).  I agree.

> [...]
> > With mutable objects you must renenber what poiters point where, and
> > what did you share actually.

> Agreed.  Except in single-assignment langauges, we always have the
> possibility of aliasing.  And in dealing with indirection (whether
> implicitly or explicly dereferenced) one has to be mindful of what
> points where.

> > Just try it, create a string class for java that works similar to
> > std::string. (use named functions to replace overloaded operators.)
> > And give it to java students to use -- you'll see they will find a
> > plenty of their strings unexpectedly having unexpected value.

> Those students claim to be used to reference semantics and to find it
> natural.

Could it be simply because they've only written simple, student projects
in which the only types which needed value semantics were int, double
and String (and of course, the java.lang.String is immutable, so the
difference between reference and value semantics is invisible)?

All I can say is that from actual experience, I found the reference
semantics of java.awt.Dimension confusing.  Of course, this is because
the class is poorly designed; if it had been immutable, like String, I
never would have noticed it or have been bothered.

> And, they don't find C++ refreshingly free of possibilities for
> aliasing.

Certainly not.  But you can limit it more than in Java.

--
James Kanze           GABI Software        mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/     http://www.gabi-soft.fr
                    Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Wed, 8 Oct 2003 20:17:15 +0000 (UTC)
Raw View
> Could it be simply because they've only written simple, student projects
> in which the only types which needed value semantics were int, double
> and String (and of course, the java.lang.String is immutable, so the
> difference between reference and value semantics is invisible)?

Perhaps this is minutia, but it's not quite true that value semantics
and reference semantics are equivalent for immutable objects.  If two
references compare equal, they have the same value, but the converse is
not always true (unless you register/intern the value or something of
the like).

For example:

if ("hello"=="he"+"llo")
 System.out.println("They refer to the same object");

My knowledge of Java optimization semantics is a bit shaky, but if the
above snippet calls println, then I'm confident a variation of the same
will not.

Adam Peterson

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 8 Oct 2003 23:17:06 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ "Bob Bell" <belvis@pacbell.net> wrote in message
+ news:c87c1cfb.0310071155.2be548c5@posting.google.com...
+> thp@cs.ucr.edu wrote in message news:<blr63a$f5f$1@glue.ucr.edu>...
+
+> You wrote
+>
+> >   int   x = 3;
+> >   int&  r = x;
+> >
+> > Here x refers to the integer three, and r refers to the integer
+> > variable x.
+>
+> At best, it's misleading to use the same term ("refers") to describe
+> what happens on these two lines of code. What happens is _not_ the
+> same; thinking it is the same will lead to problems and
+> inconsistencies.
+
+ I would describe the above as:
+
+> >   int   x = 3;
+
+ The compiler creates an object (region of storage) type 'int' somewhere, and
+ associate the name (identfier) 'x' with that region for further reference.
+ It also initializes that storage with a representation for that type of
+ value 3.
+
+> >   int&  r = x;
+
+ The compiler associates another name 'r' with the same region allocated in
+ the prior step.
+
+ So after those two lines we end up with a single int, and 2 labels to access
+ it, both labels are equivalent from the practical point of use.
+
+ r is not a "pointer to variable x that is handily dereferened" but simply
+ equivalent with x.
+
+ Certainly in some situations the compiler must communicate it to a point far
+ away -- and having no magic way it will likely pass the address of x, that
+ is really similar to the use of a const pointer.

So, what's different about the need for runtime storage between r and
p in:

   int  x = 3;
   int& r = x;
   const int* p = &x;

Of course, if the address of p were taken, we would need to allocate
storage for p; but we wouldn't need to use it.

+ But that is merely an
+ implementation detail and should better not mislead the nature of C++
+ references.

Your entire discourse has been about "mere implementation details".
But, let's continue with them.  Suppose that the value of f() cannot
be statically inferred.  Consider:

  int x = 3;
  int y = 4;

  class Widget {
    int& r;
    Widget() : r( f() ? x : y ) {}
  } widget;

  class Thingamabob {
    const int* p;
    Widget() : p( f() ? &x : &y ) {}
  } thingamabob;

What's the difference in implementation here, other than the
artificial constraint that thingamabob, being of a POD type, is
required to have a non-zero size ?

+> > Some people find that coding with implicitly dereferenced handles
+> > leads to more readable code.  But readability is in the eye of the
+> > reader.
+
+ And I agree with that in an environment where all you have is those handles.
+ Attach dereferencing to everything is ugly and redundant.  Ugly, because
+ redundant.

I rest my case.  ;-)

+ But as soon redundancy is lifted  --  say by introducing other stuff an
+ important piece of information is getting lost.
+
+ Suppose we had a type that does increment its object's value automatically
+ anytime you mention it.  So you need no longetr put that ++.  Will using
+ such objects really make code readable?    IMHO all it does is introducing
+ confusion.    As using an imperative language we're used to state a name and
+ an operation to carry out on it.  No operation stated, none shall happen.
+ And nothing but explicitly ordered is expected to happen.  [Implicit
+ conversions may seem to violate that -- IMHO not necessarily if used in a
+ sane way, but the main argument against them is on the same line.]

We already have implicit lvalue-to-rvalue conversion and implicit
reference-to-referent conversion.  They are governed by relatively
simple and intuitive rules that are common to a lot of languages.
They don't seem to cause an inordinate amount of confusion.
Nevertheless, long-time C programmers avoid references, and many
programmers raised on C++ would much rather write f(&x) than f(x),
whenever f might change the value of x.  There's room for taste in
such matters.

+ So, readability due to such automatism may really be good in special cases,
+ where you use nothing but types like that; short learning programs, and a
+ selected target audience.

Prohibiting the use of reseatable references would be a simple as
hiding ref.h.

+ IMHO we had a ton of proposals that would serve much more programmers --
+ those doing real work, and who actually took time to learn and use this
+ language, and are even easy to implement, and still getting rejected.

Hopefully there were sound technical reasons for those rejections.

+> Of course I've seen those proposals. What I'm saying is that it's rare
+> to see a post along the lines of "Python has XYZ, we should add XYZ to
+> C++." We often see posts like "Java has XYZ, we should add XYZ to
+> C++."
+
+ Yep. I'd glad to see some things. labeled break of the extra-light features.
+ reflection and some strengthened RTTI support on the heavy side.
+
+> IMHO, it's the syntactic similarity that leads to those posts. For
+> example, the posts I'm talking about often go something like this: "I
+> was trying to do XYZ in C++ because that's what works in Java. Imagine
+> my surprise to find out I couldn't get it to work! We should add XYZ
+> to C++."
+
+ Yes, and that works the other way around too.  There are migration books
+ explaining common mistakes users of some language do.
+ It pretty much varies whether some like mistake is just annoyance or leads
+ to disaster.
+
+ I recall people migrating from C to C++.  Writing pretty bad C++ code.
+ Even though semantics are similar here  the wisdom says C++ is another
+ language with its distinct approach.   One shall learn that in the firts
+ place, syntax comes only after that.
+
+ Merging or blending languages may be good to help machines, converters, code
+ generators, but IMO it's a bad approach for humans.

C++ has adopted and adapted features from all sorts of languages:
  - the entirety of C89
  - classes and objects from Simula 67
  - references from Algol 68
  - etc.
If that's such a bad thing, why program in this multiparadigm langauge?

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Wed, 8 Oct 2003 23:17:20 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.08.06.47.09.169398@knm.org.pl>...
> On Wed, 08 Oct 2003 00:43:02 +0000, Balog Pal wrote:
>
> > So after those two lines we end up with a single int, and 2 labels to access
> > it, both labels are equivalent from the practical point of use.
> >
> > r is not a "pointer to variable x that is handily dereferened" but simply
> > equivalent with x.
>
> This is a popular myth. Well, in this case they are equivalent because the
> initialization expression of the reference is so simple that it's easy to
> infer at compile time the pointed to variable, but it's a wrong way to
> think about references because it doesn't work in the general case. OTOH
> the automatically dereferenced pointer view works always.

The problem with the phrase "automatically dereferenced pointer" is
the use of the word "pointer"; it creates the inaccurate impression
that references are pointers. If a reference is an "automatically
dereferenced pointer", then I would expect a reference to behave like
a pointer, except for the automatic dereferencing. In particular, I
would expect to be able to

-- change what it points to
-- compare its pointer value with other pointers

But I can't do those things, because references aren't pointers. They
may be _implemented_ with pointers, but that doesn't make them
pointers. Pointers to functions are usually implemented the same way
as pointers to primitive values, but that doesn't make them the same
thing either.

> Using your view some people think that with
>    int &r = a[i];
> accessing r will evaluate a[i] each time.

People thinking that would be wrong. So what?

This view is quite simple: it just means that r is another name for
the object named by a[i] when r is created. That doesn't mean that
using r means getting the address of "a" and adding "i" to it, and I
don't know why anyone would think that.

> You can't say that r is another
> name for a[i]; you must say that it's another name for the object which
> a[i] referred to at that point of time, in other words - it's an
> automatically dereferenced pointer to that object.

No, it's a _reference_ to that object.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Wed, 8 Oct 2003 23:17:35 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bm01f6$p0v$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + You wrote
> +
> +>   int   x = 3;
> +>   int&  r = x;
> +>
> +> Here x refers to the integer three, and r refers to the integer
> +> variable x.
> +
> + At best, it's misleading to use the same term ("refers") to describe
> + what happens on these two lines of code. What happens is _not_ the
> + same; thinking it is the same will lead to problems and
> + inconsistencies.
>
> So choose some other verb than "refer".

I did. I used the verb "contain".

One verb for "int x = 3" ("contain") and another verb for "int& r = x"
("refer").

The exact choice of the two verbs is less important than the notion
that two different verbs are needed.

> So let's focus on the differences: when x occurs on the left side of
> the assignment operator it stops referring to 3 and suddenly
> represents itself.

First, it never "referred" to 3 in the first place, it "contained" 3.

Second, "x" always means itself. In this statement,

y = x + 10;

the "x" means itself; it is the operator "+" that digs inside x to get
the value it contains and add 10 to it.

Similarly, in

x = 10;

It is the assignment operator that (as a side effect) puts a new value
into x; x doesn't "stop referring" to one value and "start referring"
to another.

This is another way of stating that "x" is an lvalue, and that lvalues
can be used where rvalues are required.

> +> + Beyond making C++ easier for non-C++ programmers, what benefit is
> +> + there?
> +>
> +> Some people find that coding with implicitly dereferenced handles
> +> leads to more readable code.  But readability is in the eye of the
> +> reader.
> +
> + That's what I mean by "making C++ easier for non-C++ programmers". How
> + many of these people are C++ programmers, as opposed to (for example)
> + Java programmers who want to learn C++?
>
> The people I have in mind are multilingual, fluent in Java, C++,
> Python and other languages.

How is someone "fluent" in C++ going to have a problem with *p? I
can't imagine anyone except a C++ newbie or casual C++ programmer
having a problem reading and writing *p.

I'm sorry, but you're just not convincing me that there is a problem
worth solving here.

> +> +> It's not simply a matter of syntactic similarity.  Python programmers
> +> +> come from a language that has quite different syntax from C++, but
> +> +> they're equally perplexed at the lack of handles that are reseatable
> +> +> and implicitly dereferenced.
> +> [...]
> +> + It seems we regularly see proposals to add Java semantics to C++; I
> +> + can't remember the last time I saw a proposal to add Python semantics.
> +>
> +> Surely you've seen proposals to add GC, which Python has.  And now
> +> you're seeing a proposal to add a library type that implements
> +> reference semantics, which (IIUC) Python has.  IMHO, there's nothing
> +> Java specific about this proposal except the prevalence of Java
> +> trained students entering courses that use C++.
> +
> + Of course I've seen those proposals. What I'm saying is that it's rare
> + to see a post along the lines of "Python has XYZ, we should add XYZ to
> + C++." We often see posts like "Java has XYZ, we should add XYZ to
> + C++."
> +
> + IMHO, it's the syntactic similarity that leads to those posts. For
> + example, the posts I'm talking about often go something like this: "I
> + was trying to do XYZ in C++ because that's what works in Java. Imagine
> + my surprise to find out I couldn't get it to work! We should add XYZ
> + to C++."
>
> Depending on what they ask for, their requests may be reasonable:
>   - standard libraries for threading and graphics, etc.
>   - GC
>   - reseatable references
>   - portable object code
>   - the ability to link modules compiled under different compilers
>     for the same architecture.

I note that these things are all Java features that C++ lacks. I think
that supports my opinion: the similarity between (the syntax of) C++
and Java leads people to suggest the two languages share or merge
features. This process can only lead to starting with two languages
and ending with one; I just don't see the advantage of doing that.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Thu, 9 Oct 2003 03:04:04 +0000 (UTC)
Raw View
> So, what's different about the need for runtime storage between r and
> p in:
>
>    int  x = 3;
>    int& r = x;
>    const int* p = &x;

I believe you mean:
 int *const p=&x;

One of the differences is that you can have:
 int *const p=NULL;

That concept doesn't make sense with C++ references.  It makes sense
with Java references, but most things that make sense with Java
references tend to make sense with C++ pointers.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 9 Oct 2003 05:28:35 +0000 (UTC)
Raw View
"Adam H. Peterson" <ahp6@email.byu.edu> wrote:
+> So, what's different about the need for runtime storage between r and
+> p in:
+>
+>    int  x = 3;
+>    int& r = x;
+>    const int* p = &x;
+
+ I believe you mean:
+        int *const p=&x;
+
+ One of the differences is that you can have:
+        int *const p=NULL;

That's a difference, but it not a diffrence "about the need for
runtime storage between r and p" in the above.  Also, note this
difference is a byproduce of the initialization syntax for references.

+ That concept doesn't make sense with C++ references.  It makes sense
+ with Java references, but most things that make sense with Java
+ references tend to make sense with C++ pointers.

That's because java references are not dereferenced in each and every
context.  In particular, they are not dereferenced when they occur
as operands of =, ==, or !=.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 10 Oct 2003 15:55:42 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.08.06.47.09.169398@knm.org.pl>...
+> On Wed, 08 Oct 2003 00:43:02 +0000, Balog Pal wrote:
+>
+> > So after those two lines we end up with a single int, and 2 labels to access
+> > it, both labels are equivalent from the practical point of use.
+> >
+> > r is not a "pointer to variable x that is handily dereferened" but simply
+> > equivalent with x.
+>
+> This is a popular myth. Well, in this case they are equivalent because the
+> initialization expression of the reference is so simple that it's easy to
+> infer at compile time the pointed to variable, but it's a wrong way to
+> think about references because it doesn't work in the general case. OTOH
+> the automatically dereferenced pointer view works always.
+
+ The problem with the phrase "automatically dereferenced pointer" is
+ the use of the word "pointer"; it creates the inaccurate impression
+ that references are pointers.

Marcin's claim is that the automatically-dereferenced-pointer view
"always works", not that it is metaphyically accurate.  Take for
example the claims you make below:

+ If a reference is an "automatically
+ dereferenced pointer", then I would expect a reference to behave like
+ a pointer, except for the automatic dereferencing.

... and properly so.

+ In particular, I would expect to be able to
+
+ -- change what it points to
+ -- compare its pointer value with other pointers

Suppose x were an automatically dereferenced, and we evaluate an
expression of the form "x=...", which would be equivalent to "*x=..."
if x were a normal pointer.  Why would you expect that to change
the value of x?

+ But I can't do those things, because references aren't pointers.

You can't do those things automatically dereferenced pointer are
automatically dereferenced in all contexts.  It's as simple as that.

So, Let's phrase the automaticaly-dereferenced-pointer view more
precisely as a hypothesis:

  If in a given program we replace:
    - a declaration the form "T& x" with "T* x" and
    - the subsequent initialization "x(...)" with "x(&...)" and
    - all subsequent occurrences of x in the scope of that
      declaration with "*x"
  the behavior of the program will not change.

The important things to notice about this hypothesis are that:

  - It doesn't say that references *are* automatically dereferenced
    pointers.  Rather, it says that references *behave* as would
    automatically dereferenced pointers.

  - It has nothing to do with how references and/or pointers are
    implemented.

As far as I know the hypothesis is almost always true, but there are a
few of special cases that need to be mentioned:

  - if x had been a const reference than its initializer could have
    been an rvalue, in which case the above wouldn't work, unless
    we also declared a temporary that value, etc.

  - if x is a member of a class-or-struct type and the only thing
    that keeps that type from being POD (plain-old-data), then
    the above transformation would make the type POD and subject
    it to C's layout rules, which require that space be allocated
    for objects that can otherwise be optimized away, i.e., the
    size of the type might expand a bit in rare cases.

  - There is another obscure case occurs during construction or
    destruction of some objects that I don't remember right now.
    (James Kanze showed it to me several years ago.)

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 11 Oct 2003 01:38:31 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bm01f6$p0v$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + You wrote
+> +
+> +>   int   x = 3;
+> +>   int&  r = x;
+> +>
+> +> Here x refers to the integer three, and r refers to the integer
+> +> variable x.
+> +
+> + At best, it's misleading to use the same term ("refers") to describe
+> + what happens on these two lines of code. What happens is _not_ the
+> + same; thinking it is the same will lead to problems and
+> + inconsistencies.
+>
+> So choose some other verb than "refer".
+
+ I did. I used the verb "contain".

If an object p is on a list q, it makes sense to say that q "contains"
p.  AFAIK integer variables are not of a container type.  So, I see no
justification for this use of the verb "contain".

IMHO, preferable verbs would include: "denote", "designate",
"specify", or "refer to".

+ One verb for "int x = 3" ("contain") and another verb for "int& r = x"
+ ("refer").
+
+ The exact choice of the two verbs is less important than the notion
+ that two different verbs are needed.

What's so different?

+> So let's focus on the differences: when x occurs on the left side of
+> the assignment operator it stops referring to 3 and suddenly
+> represents itself.
+
+ First, it never "referred" to 3 in the first place, it "contained" 3.
+
+ Second, "x" always means itself. In this statement,
+
+ y = x + 10;
+
+ the "x" means itself; it is the operator "+" that digs inside x to get
+ the value it contains and add 10 to it.

It was my impression that in the above context the expression "x"
undergoes lvalue-to-rvalue conversion, i.e., "x" becomes an int
expression whose value is 3.  Thus this occurrence of the expression
"x" designates 3.

+ Similarly, in
+
+ x = 10;
+
+ It is the assignment operator that (as a side effect) puts a new value
+ into x; x doesn't "stop referring" to one value and "start referring"
+ to another.

Before the evaluation of the expression "x=10", x whatevered 3.
Following the evaluation of "x=10", x no longer whatevers 3 and now
whatevers 10.  Obviously, x did indeed stop whatevering 3 and started
whatevering 10.  And obviously, x is not a "container".

+ This is another way of stating that "x" is an lvalue, and that lvalues
+ can be used where rvalues are required.

The above has nothing to do with lvalue-to-rvalue conversion.  Rather
it's a matter of the semantics of =.

+> +> + Beyond making C++ easier for non-C++ programmers, what benefit is
+> +> + there?
+> +>
+> +> Some people find that coding with implicitly dereferenced handles
+> +> leads to more readable code.  But readability is in the eye of the
+> +> reader.
+> +
+> + That's what I mean by "making C++ easier for non-C++ programmers". How
+> + many of these people are C++ programmers, as opposed to (for example)
+> + Java programmers who want to learn C++?
+>
+> The people I have in mind are multilingual, fluent in Java, C++,
+> Python and other languages.
+
+ How is someone "fluent" in C++ going to have a problem with *p?

I said that: "Some people find that coding with implicitly derferenced
handles leads to more readable code."

+ I can't imagine anyone except a C++ newbie or casual C++ programmer
+ having a problem reading and writing *p.

I didn't say that they had "a problem with" explicit dereferencing.
Think of it as a "preference for" implicit derferencing", rather than
a problem.

+ I'm sorry, but you're just not convincing me that there is a problem
+ worth solving here.

That doesn't surprise me.

+> +> +> It's not simply a matter of syntactic similarity.  Python programmers
+> +> +> come from a language that has quite different syntax from C++, but
+> +> +> they're equally perplexed at the lack of handles that are reseatable
+> +> +> and implicitly dereferenced.
+> +> [...]
+> +> + It seems we regularly see proposals to add Java semantics to C++; I
+> +> + can't remember the last time I saw a proposal to add Python semantics.
+> +>
+> +> Surely you've seen proposals to add GC, which Python has.  And now
+> +> you're seeing a proposal to add a library type that implements
+> +> reference semantics, which (IIUC) Python has.  IMHO, there's nothing
+> +> Java specific about this proposal except the prevalence of Java
+> +> trained students entering courses that use C++.
+> +
+> + Of course I've seen those proposals. What I'm saying is that it's rare
+> + to see a post along the lines of "Python has XYZ, we should add XYZ to
+> + C++." We often see posts like "Java has XYZ, we should add XYZ to
+> + C++."
+> +
+> + IMHO, it's the syntactic similarity that leads to those posts. For
+> + example, the posts I'm talking about often go something like this: "I
+> + was trying to do XYZ in C++ because that's what works in Java. Imagine
+> + my surprise to find out I couldn't get it to work! We should add XYZ
+> + to C++."
+>
+> Depending on what they ask for, their requests may be reasonable:
+>   - standard libraries for threading and graphics, etc.
+>   - GC
+>   - reseatable references
+>   - portable object code
+>   - the ability to link modules compiled under different compilers
+>     for the same architecture.
+
+ I note that these things are all Java features that C++ lacks.

Of course.  They are reasonable things that I thought you might be
referring to.

+ I think that supports my opinion: the similarity between (the syntax of)
+ C++ and Java leads people to suggest the two languages share or merge
+ features. This process can only lead to starting with two languages
+ and ending with one; I just don't see the advantage of doing that.

C++ has imported features from C, Simula67, Algol68, and various other
languages.  What makes you think that importing a feature that Java
had first would somehow contaminate the langauge?

Tom Payne


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Sat, 11 Oct 2003 01:42:55 +0000 (UTC)
Raw View
belvis@pacbell.net (Bob Bell) wrote in message news:<c87c1cfb.0310080919.4d44213@posting.google.com>...
...
> that references are pointers. If a reference is an "automatically
> dereferenced pointer", then I would expect a reference to behave like
> a pointer, except for the automatic dereferencing. In particular, I
> would expect to be able to
>
> -- change what it points to
> -- compare its pointer value with other pointers

int i;
int *p=&i;
int &r=i;

i = (p == &r);

Comparing the pointer value of a reference with other pointers
requires only a different syntax. Except for reseatability, it's a
purely sytactic difference. A reference can be described as an
automatically dereferenced pointer; in the same sense a pointer can be
described as an automatically addressed reference. Except for the
reseatability issue, the choice between a pointer and a reference
could be made by just figuring out whether you'd end up writing "*p"
or "&r" more often.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 11 Oct 2003 01:43:06 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.08.06.47.09.169398@knm.org.pl>...
+> On Wed, 08 Oct 2003 00:43:02 +0000, Balog Pal wrote:
+>
+> > So after those two lines we end up with a single int, and 2 labels to access
+> > it, both labels are equivalent from the practical point of use.
+> >
+> > r is not a "pointer to variable x that is handily dereferened" but simply
+> > equivalent with x.
+>
+> This is a popular myth. Well, in this case they are equivalent because the
+> initialization expression of the reference is so simple that it's easy to
+> infer at compile time the pointed to variable, but it's a wrong way to
+> think about references because it doesn't work in the general case. OTOH
+> the automatically dereferenced pointer view works always.
+
+ The problem with the phrase "automatically dereferenced pointer" is
+ the use of the word "pointer"; it creates the inaccurate impression
+ that references are pointers. If a reference is an "automatically
+ dereferenced pointer", then I would expect a reference to behave like
+ a pointer, except for the automatic dereferencing. In particular, I
+ would expect to be able to
+
+ -- change what it points to
+ -- compare its pointer value with other pointers
+
+ But I can't do those things, because references aren't pointers.

No.  You can't do those things because automatically dereferenced
pointers would be automatically dereferenced in all contexts:

   - attempting to assign to them would assign to their referent and

   - attempting to compare to them would compare to their referent

which is exactly what happens with C++ references.

+ They may be _implemented_ with pointers, but that doesn't make them
+ pointers.

Even pointers are not necessarily implemented with pointers.  Rather,
the point is that const pointers and references have the same
implementation options, because they are the same notion except that:

  - C++ references are dereferenced at each use.

  - C++ references have been subjected to various restrictions for
    well-intentioned software-engineering reasons.

  - const C++ references can be initialized via an rvalue.

  - POD objects must allocate space to member const pointers whether
    needed or not.

+> Using your view some people think that with
+>    int &r = a[i];
+> accessing r will evaluate a[i] each time.
+
+ People thinking that would be wrong. So what?
+
+ This view is quite simple: it just means that r is another name for
+ the object named by a[i] when r is created.

As a name, "r" is a one-character string.  As a reference, r has
run-time state.  Consider int& f(){return a[i];}.  Now f() is a
reference that refers to the object a[i].  But f() is not a name.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Sat, 11 Oct 2003 01:43:47 +0000 (UTC)
Raw View
<snip>
> + One of the differences is that you can have:
> +        int *const p=NULL;
>
<snip>
 > Also, note this
> difference is a byproduce of the initialization syntax for references.

I don't follow.  How is this a byproduct of the reference init syntax?
I feel that one of the fundamental things about C++ references is that
they always refer to a valid object (unless its lifetime has ended).  It
never makes sense to test if a reference refers to the "NULL object"
because it can't, without invoking undefined behavior.  While I am not a
definitive expert on C++, I get the impression that this is by design.
I would hardly dismiss it as a "byproduct" as if it happened to work out
that way, but might not have if we had just "thought of it when we could
have made a difference".  Perhaps I'm reading more into this statement
than you intended.

Perhaps we're getting a bit afield of your direct question about storage
(I've always felt storage issues were mostly implementation details, and
never cared much about them), although it is worthy to note that you
_cannot_ take the address of a reference.  Likewise, you can't create
containers of references, or arrays of references allocated from the heap.

On the other hand, in terms of usage I foresee problems with a pointer
type that is usually automatically dereferenced and sometimes not.  For
example, in the context of these declarations:
     T t1, t2;
     ref<T> r1=t1, r2=t2;
how would you handle the following operations:
     t1=t2;  // This looks to me like a standard value assignment.
             //   I expect you agree.
     t1=r2;  // Again, a standard value assignment.
     r1=t2;  // Is this a "reseating"?
             //   If so, how do I say <r1's referent> gets
             //   assigned the value of t2?
             //   Also, this creates an odd asymmetry in assignment of
             //   this type, although I admit it isn't the first
             //   occurence of such in C++.
     r1=r2;  // I assume this also is a "reseating", which begs
             //   the same question as above.  How do I do value
             //   assignment, without reseating?
The ambiguities increase in number when you start to put ref<T> objects
in containers.  Do you get containers of values or of handles?
Whichever one you get, how do you derive the other?  (Not unaddressable,
but it doesn't seem straightforward to me.)  It becomes a real mess when
you deal with associative containers, who cannot allow their "index"
type to be mutable in any way that affects ordering.

Adam Peterson

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: drpizza@anti-flash.co.uk ("DrPizza")
Date: Sat, 11 Oct 2003 01:46:37 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...
> Auto-dereferencing appears not to confuse Java, C#, and Python
> programmers.

I disagree.  I've found plenty of Java programmers who are confused why
equality comparisons don't dereference (i.e. test identity) but member access
does dereference.  It appears inconsistent to them.






--
char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: drpizza@anti-flash.co.uk ("DrPizza")
Date: Sat, 11 Oct 2003 01:46:50 +0000 (UTC)
Raw View
""Marcin 'Qrczak' Kowalczyk"" <qrczak@knm.org.pl> wrote in message
news:pan.2003.10.08.06.47.09.169398@knm.org.pl...
> This is a popular myth.
It's no myth.

> Well, in this case they are equivalent because the
> initialization expression of the reference is so simple that it's easy to
> infer at compile time the pointed to variable, but it's a wrong way to
> think about references because it doesn't work in the general case.
It sure does.

> OTOH
> the automatically dereferenced pointer view works always.
But leads to sundry misconceptions.

> Using your view some people think that with
>    int &r = a[i];
> accessing r will evaluate a[i] each time.
Why would they think that?  What they would think is that the name 'r' refers
to the object that a[i] instantaneously refers to.  Which is accurate.

> You can't say that r is another
> name for a[i];
No -- r is another name for the object instantaneously referred to by a[i].

> you must say that it's another name for the object which
> a[i] referred to at that point of time, in other words - it's an
> automatically dereferenced pointer to that object.
That would lead some people to think that there were a pointer and that it
were dereferenced -- which is both more likely, and more misleading, than
thinking that a[i] will be evaluated each time.

> I would say differently. Certainly in some situations the compiler doesn't
> have to communicate the address which is known statically, and as an
> optimization in these cases it can omit the physical creation of the
> reference. But this is an implementation detail, in general it requires
> as much information as a const pointer whose address is never taken.
In general it shouldn't require any such thing.  In general, a compiler should
set aside no storage for a reference (i.e. the reference should exist purely
as a name for the programmer to manipulate without any representation).  The
exception is passing by reference.  In this situation an address may be
needed, though I would think that for e.g. small built-in types copy in, copy
out would be an acceptable and sometimes desirable implementation.

--
char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */



---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 11 Oct 2003 22:57:57 +0000 (UTC)
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...
+> Auto-dereferencing appears not to confuse Java, C#, and Python
+> programmers.
+
+ I disagree.  I've found plenty of Java programmers who are confused why
+ equality comparisons don't dereference (i.e. test identity) but member access
+ does dereference.  It appears inconsistent to them.

That's predictable for programmers who first learned value semantics,
e.g., those who started with C or C++.  I've not heard that complaint
from those who started with Java.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 11 Oct 2003 23:00:53 +0000 (UTC)
Raw View
"Adam H. Peterson" <ahp6@email.byu.edu> wrote:
+ <snip>
+> + One of the differences is that you can have:
+> +        int *const p=NULL;
+>
+ <snip>
+ > Also, note this
+> difference is a byproduce of the initialization syntax for references.
+
+ I don't follow.  How is this a byproduct of the reference init syntax?
+ I feel that one of the fundamental things about C++ references is that
+ they always refer to a valid object (unless its lifetime has ended).  It
+ never makes sense to test if a reference refers to the "NULL object"
+ because it can't, without invoking undefined behavior.  While I am not a
+ definitive expert on C++, I get the impression that this is by design.
+ I would hardly dismiss it as a "byproduct" as if it happened to work out
+ that way, but might not have if we had just "thought of it when we could
+ have made a difference".  Perhaps I'm reading more into this statement
+ than you intended.

All I meant was that reference is a notion imported into C++ from
other langauges, some of which support null references.  In C++,
however, it is required that references be initialized via lvalues and
the evaluation of an lvalue that doesn't denote a valid object invokes
undefined behavior.

[...]
+ On the other hand, in terms of usage I foresee problems with a pointer
+ type that is usually automatically dereferenced and sometimes not.  For
+ example, in the context of these declarations:
+     T t1, t2;
+     ref<T> r1=t1, r2=t2;
+ how would you handle the following operations:
+     t1=t2;  // This looks to me like a standard value assignment.
+             //   I expect you agree.
+     t1=r2;  // Again, a standard value assignment.
+     r1=t2;  // Is this a "reseating"?
+             //   If so, how do I say <r1's referent> gets
+             //   assigned the value of t2?
+             //   Also, this creates an odd asymmetry in assignment of
+             //   this type, although I admit it isn't the first
+             //   occurence of such in C++.
+     r1=r2;  // I assume this also is a "reseating", which begs
+             //   the same question as above.  How do I do value
+             //   assignment, without reseating?
+ The ambiguities increase in number when you start to put ref<T> objects
+ in containers.  Do you get containers of values or of handles?
+ Whichever one you get, how do you derive the other?  (Not unaddressable,
+ but it doesn't seem straightforward to me.)

Presumably, to designate the referent of r1 via a normal lvalue, one
could write "*&r1" or more elegantly "referent(r1)" where referent is
defined: T& referent( ref<T> r ) { return r; }

+ It becomes a real mess when
+ you deal with associative containers, who cannot allow their "index"
+ type to be mutable in any way that affects ordering.

Many experts claim that it's a real mess to put pointers into
containers, but I've never found a way to avoid it.  It seems I always
have objects that I want to put on multiple lists.  In such cases,
however, I don't see that hiding this level of indirection would be
intrinsically dangerous, except that (for now) it would be
non-idiomatic.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sat, 11 Oct 2003 23:02:10 +0000 (UTC)
Raw View
On Sat, 11 Oct 2003 01:46:50 +0000, DrPizza wrote:

>> you must say that it's another name for the object which
>> a[i] referred to at that point of time, in other words - it's an
>> automatically dereferenced pointer to that object.
> That would lead some people to think that there were a pointer and that it
> were dereferenced -- which is both more likely, and more misleading, than
> thinking that a[i] will be evaluated each time.

Why is this misleading?

> In general it shouldn't require any such thing.  In general, a compiler
> should set aside no storage for a reference (i.e. the reference should
> exist purely as a name for the programmer to manipulate without any
> representation).

Why? You could say exactly the same about all const objects, that the
compiler shouldn't allocate storage for them except when it's forced to
(e.g. because the programmer takes its address, or to avoid recomputation
of its value). But it's an unnecessary complication.

It's simpler to not mention this choice and explain references as if they
used storage, because it's always a valid compilation strategy, especially
as it's almost always the only possible compilation strategy. As an
additional optimization the compiler is free to not allocate it if the
result is the same, but it's already stated elsewhere that the program can
be compiled differently if you can't observe the difference.

> The exception is passing by reference.  In this
> situation an address may be needed, though I would think that for e.g.
> small built-in types copy in, copy out would be an acceptable and
> sometimes desirable implementation.

And now you have been misled by your own definition!
No, it would not be acceptable in general:

int x = 0;
int test(const int &r) {
   ++x;
   return r;
}
int main() {
   cout << test(x) << endl;
}

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 12 Oct 2003 02:02:19 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bm625i$f35$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + The problem with the phrase "automatically dereferenced pointer" is
> + the use of the word "pointer"; it creates the inaccurate impression
> + that references are pointers.
>
> Marcin's claim is that the automatically-dereferenced-pointer view
> "always works", not that it is metaphyically accurate.

[snip]

> So, Let's phrase the automaticaly-dereferenced-pointer view more
> precisely as a hypothesis:
>
>   If in a given program we replace:
>     - a declaration the form "T& x" with "T* x" and
>     - the subsequent initialization "x(...)" with "x(&...)" and
>     - all subsequent occurrences of x in the scope of that
>       declaration with "*x"
>   the behavior of the program will not change.
>
> The important things to notice about this hypothesis are that:
>
>   - It doesn't say that references *are* automatically dereferenced
>     pointers.  Rather, it says that references *behave* as would
>     automatically dereferenced pointers.
>
>   - It has nothing to do with how references and/or pointers are
>     implemented.
>
> As far as I know the hypothesis is almost always true, but there are a
> few of special cases that need to be mentioned:
>
>   - if x had been a const reference than its initializer could have
>     been an rvalue, in which case the above wouldn't work, unless
>     we also declared a temporary that value, etc.
>
>   - if x is a member of a class-or-struct type and the only thing
>     that keeps that type from being POD (plain-old-data), then
>     the above transformation would make the type POD and subject
>     it to C's layout rules, which require that space be allocated
>     for objects that can otherwise be optimized away, i.e., the
>     size of the type might expand a bit in rare cases.
>
>   - There is another obscure case occurs during construction or
>     destruction of some objects that I don't remember right now.
>     (James Kanze showed it to me several years ago.)

These "special cases" demonstrate that a) the
"automatically-dereferenced-pointer view" _doesn't_ always work, and
b) your hypothesis is false.

I put "special cases" in quotes because they're not really all that
special; they are consequences of the definition of references, and
consequences of the fact that references are not pointers, not even
conceptually.

I frankly don't see the advantage in pretending that references are
automatically dereferenced pointers. What do you gain from this view?

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 12 Oct 2003 02:02:28 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bm2cuf$ev3$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + thp@cs.ucr.edu wrote in message news:<bm01f6$p0v$1@glue.ucr.edu>...
> +> Bob Bell <belvis@pacbell.net> wrote:
> +> + You wrote
> +> +
> +> +>   int   x = 3;
> +> +>   int&  r = x;
> +> +>
> +> +> Here x refers to the integer three, and r refers to the integer
> +> +> variable x.
> +> +
> +> + At best, it's misleading to use the same term ("refers") to describe
> +> + what happens on these two lines of code. What happens is _not_ the
> +> + same; thinking it is the same will lead to problems and
> +> + inconsistencies.
> +>
> +> So choose some other verb than "refer".
> +
> + I did. I used the verb "contain".
>
> If an object p is on a list q, it makes sense to say that q "contains"
> p.  AFAIK integer variables are not of a container type.  So, I see no
> justification for this use of the verb "contain".
>
> IMHO, preferable verbs would include: "denote", "designate",
> "specify", or "refer to".
>
> + One verb for "int x = 3" ("contain") and another verb for "int& r = x"
> + ("refer").
> +
> + The exact choice of the two verbs is less important than the notion
> + that two different verbs are needed.
>
> What's so different?

int x = 3;
int& r = x;

I claim that these two lines of code do two different things. I claim
that the first line describes a relationship (between x and 3) that is
different from the relationship (between r and x) described on the
second line. Therefore, we need one verb to describe what x does with
3, and another verb to describe what r does with x.

Here's another example of why they're different:

int x = y;

Whatever y is, it is always converted to an r-value.

int& r = y;

Whatever y is, it is never converted to an r-value.

Again, these two lines:

int x = 3;
int& r = x;

do two different things. Using the same verb ("refer") to describe
both lines of code leads to confusion and inaccuracies.

> +> So let's focus on the differences: when x occurs on the left side of
> +> the assignment operator it stops referring to 3 and suddenly
> +> represents itself.
> +
> + First, it never "referred" to 3 in the first place, it "contained" 3.
> +
> + Second, "x" always means itself. In this statement,
> +
> + y = x + 10;
> +
> + the "x" means itself; it is the operator "+" that digs inside x to get
> + the value it contains and add 10 to it.
>
> It was my impression that in the above context the expression "x"
> undergoes lvalue-to-rvalue conversion, i.e., "x" becomes an int
> expression whose value is 3.  Thus this occurrence of the expression
> "x" designates 3.

This occurrence of the expression "x" designates 3 AFTER the
lvalue-to-rvalue conversion. "x" by itself always means "the lvalue
x". It only converts to an rvalue when used with operators that
require the conversion.

> + Similarly, in
> +
> + x = 10;
> +
> + It is the assignment operator that (as a side effect) puts a new value
> + into x; x doesn't "stop referring" to one value and "start referring"
> + to another.
>
> Before the evaluation of the expression "x=10", x whatevered 3.
> Following the evaluation of "x=10", x no longer whatevers 3 and now
> whatevers 10.  Obviously, x did indeed stop whatevering 3 and started
> whatevering 10.  And obviously, x is not a "container".

Fine: we'll use "whatever" to mean the relationship between the lvalue
x and what you get when the lvalue x is converted to an rvalue. Which
means that in "a" "whatever" "b", "a" is an lvalue and "b" is an
rvalue.

It's should be clear that in

int x = 3;
int& r = x;

r does not "whatever" x, because x is not an rvalue; it is an lvalue.

> + I can't imagine anyone except a C++ newbie or casual C++ programmer
> + having a problem reading and writing *p.
>
> I didn't say that they had "a problem with" explicit dereferencing.
> Think of it as a "preference for" implicit derferencing", rather than
> a problem.

If it's not a problem, why should the standard be changed (to add the
ref<> type you advocate)?

> +> + IMHO, it's the syntactic similarity that leads to those posts. For
> +> + example, the posts I'm talking about often go something like this: "I
> +> + was trying to do XYZ in C++ because that's what works in Java. Imagine
> +> + my surprise to find out I couldn't get it to work! We should add XYZ
> +> + to C++."
> +>
> +> Depending on what they ask for, their requests may be reasonable:
> +>   - standard libraries for threading and graphics, etc.
> +>   - GC
> +>   - reseatable references
> +>   - portable object code
> +>   - the ability to link modules compiled under different compilers
> +>     for the same architecture.
> +
> + I note that these things are all Java features that C++ lacks.
>
> Of course.  They are reasonable things that I thought you might be
> referring to.

Reasonable as in "makes sense for addition to C++"? Not hardly.

I don't want to start a C++ vs. Java war, I'm just saying that I've
seen multiple posts, on this group and others, asking for these and
other Java features, where the poster indicates that "C++ should do
this because Java does". On the other hand, I can't recall the last
time I saw a post requesting a feature where the poster indicates "C++
should do this because Python does".

I think this is symptomatic of the syntactic similarity between Java
and C++ creating the impression in the minds of programmers who use
both that the languages should have an equivalent semantic similarity.

That's just my opinion; if you don't agree, that's fine. I don't
really want to belabor this point any more, especially since it has
little to do with the ref<> proposal, so this is the last time I'll
say it.

> + I think that supports my opinion: the similarity between (the syntax of)
> + C++ and Java leads people to suggest the two languages share or merge
> + features. This process can only lead to starting with two languages
> + and ending with one; I just don't see the advantage of doing that.
>
> C++ has imported features from C, Simula67, Algol68, and various other
> languages.  What makes you think that importing a feature that Java
> had first would somehow contaminate the langauge?

Nothing -- as long as said feature is a good idea, integrates well
with existing C++ features, maintains the spirit of C++, doesn't
preclude desirable implementation properties, doesn't introduce
error-prone or confusing idioms, etc., etc., etc. Thankfully, the
standard committee gets this, so we won't be seeing (e.g.) "finally"
added to C++ any time soon.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sun, 12 Oct 2003 19:41:30 +0000 (UTC)
Raw View
On Sun, 12 Oct 2003 02:02:19 +0000, Bob Bell wrote:

> I frankly don't see the advantage in pretending that references are
> automatically dereferenced pointers. What do you gain from this view?

That you don't have to describe them from scratch using words which must
be understood by intuition, but you can shortly describe them by words
which must be known anyway from other parts of the language.

What is the difference between references and automatically dereferenced
const pointers which can't be null and can be bound to temporaries?

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 13 Oct 2003 04:28:14 +0000 (UTC)
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote:
[...]
+ In general, a compiler should
+ set aside no storage for a reference (i.e. the reference should exist purely
+ as a name for the programmer to manipulate without any representation).  The
+ exception is passing by reference.  In this situation an address may be
+ needed, though I would think that for e.g. small built-in types copy in, copy
+ out would be an acceptable and sometimes desirable implementation.


Consider:

  class Widget {
    ...
    Whatever& r;
    Widget(...) r(*new Whatever) {...}
    ...
  }

And suppose the number of widgets we create has to do with external
input.  How do you propose to implement Widget without setting aside
storage for holding the address of r's referent, just as you would if
r were a const pointer?

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: michael.s.terrazas@worldnet.att.net ("Michael Terrazas")
Date: Mon, 13 Oct 2003 06:51:10 +0000 (UTC)
Raw View
This whole discussion has the feel of two dark ages theologians discussing
angels and pins.

""Marcin 'Qrczak' Kowalczyk"" <qrczak@knm.org.pl> wrote in message
news:pan.2003.10.12.08.25.01.367587@knm.org.pl...
[snip]
> That you don't have to describe them from scratch using words which must
> be understood by intuition, but you can shortly describe them by words
> which must be known anyway from other parts of the language.

But if your description causes confusion in some of your listeners, how
beneficial is it?

> What is the difference between references and automatically dereferenced
> const pointers which can't be null and can be bound to temporaries?

Well, pointers CAN hold null, therefore they aren't the same, are they?
Pointers can't point at temporaries, so references aren't ponters.
I CAN create an array of const pointers, but I CANNOT create an
array of references.

Note: I am not in the camp of always describing references as aliases
either.  Both descriptions fall short.  In my experience of teaching
thousands of people C++ from many different backgrounds, including
Java, C, Assembly, Smalltalk, Lisp, LOOPS; different analogies are
needed for different people.  I have seen just as many people confused
by "automatically dereferenced pointers" as by "aliases".  Both are just
approximations and I don't believe one is more wrong than the other.

My 2 cents

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 13 Oct 2003 15:59:50 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bm625i$f35$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + The problem with the phrase "automatically dereferenced pointer" is
+> + the use of the word "pointer"; it creates the inaccurate impression
+> + that references are pointers.
+>
+> Marcin's claim is that the automatically-dereferenced-pointer view
+> "always works", not that it is metaphyically accurate.
+
+ [snip]
+
+> So, Let's phrase the automaticaly-dereferenced-pointer view more
+> precisely as a hypothesis:
+>
+>   If in a given program we replace:
+>     - a declaration the form "T& x" with "T* x" and
+>     - the subsequent initialization "x(...)" with "x(&...)" and
+>     - all subsequent occurrences of x in the scope of that
+>       declaration with "*x"
+>   the behavior of the program will not change.
+>
+> The important things to notice about this hypothesis are that:
+>
+>   - It doesn't say that references *are* automatically dereferenced
+>     pointers.  Rather, it says that references *behave* as would
+>     automatically dereferenced pointers.
+>
+>   - It has nothing to do with how references and/or pointers are
+>     implemented.
+>
+> As far as I know the hypothesis is almost always true, but there are a
+> few of special cases that need to be mentioned:
+>
+>   - if x had been a const reference than its initializer could have
+>     been an rvalue, in which case the above wouldn't work, unless
+>     we also declared a temporary that value, etc.
+>
+>   - if x is a member of a class-or-struct type and the only thing
+>     that keeps that type from being POD (plain-old-data), then
+>     the above transformation would make the type POD and subject
+>     it to C's layout rules, which require that space be allocated
+>     for objects that can otherwise be optimized away, i.e., the
+>     size of the type might expand a bit in rare cases.
+>
+>   - There is another obscure case occurs during construction or
+>     destruction of some objects that I don't remember right now.
+>     (James Kanze showed it to me several years ago.)
+
+ These "special cases" demonstrate that a) the
+ "automatically-dereferenced-pointer view" _doesn't_ always work, and
+ b) your hypothesis is false.
+
+ I put "special cases" in quotes because they're not really all that
+ special; they are consequences of the definition of references, and
+ consequences of the fact that references are not pointers, not even
+ conceptually.

It is, of course, your perogative to see any differences as intrinsic
to the nature of references and pointers.  To me they seem more than a
bit arbitrary.  In fact, we don't know what the third case, but it
appears that the first two cases are features having to do with
compatibility with Fortran and C respectively:

First case: According to D&E page 86, allowing all references to be
initialized with rvalues was tried and removed, but the ability to
initialize const references from rvalues was retained and is important
because "this is what allows a Fortran function to be called with a
constant."

Second case: I'm told that the distinction between POD and non-POD
objects was introduced to allow certain space optimizations without
losing C compatibility.

+ I frankly don't see the advantage in pretending that references are
+ automatically dereferenced pointers. What do you gain from this view?

Pedagogical efficiency.  To people who understand the notion of
pointers, the notion that references are automatically dereferenced
pointers instantly confers most of what they need to know about the
semantics of references.  They instantly understand, for example,
that:

  - references can dangle and when and how and why

  - references can be returned from functions

  - a reference to "a[i]" (for example) doesn't get re-evaluated each
    time it is used

  - reference normally require space.

Misimpressions on each of these four points are compatible with (or
even follow from) the notion that "references are mere aliases".

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Mon, 13 Oct 2003 17:47:41 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote:
> + On the other hand, in terms of usage I foresee problems with a pointer
> + type that is usually automatically dereferenced and sometimes not.  For
> + example, in the context of these declarations:
> +     T t1, t2;
> +     ref<T> r1=t1, r2=t2;
> + how would you handle the following operations:
> +     t1=t2;  // This looks to me like a standard value assignment.
> +             //   I expect you agree.
> +     t1=r2;  // Again, a standard value assignment.
> +     r1=t2;  // Is this a "reseating"?
> +             //   If so, how do I say <r1's referent> gets
> +             //   assigned the value of t2?
> +             //   Also, this creates an odd asymmetry in assignment of
> +             //   this type, although I admit it isn't the first
> +             //   occurence of such in C++.
> +     r1=r2;  // I assume this also is a "reseating", which begs
> +             //   the same question as above.  How do I do value
> +             //   assignment, without reseating?
> + The ambiguities increase in number when you start to put ref<T> objects
> + in containers.  Do you get containers of values or of handles?
> + Whichever one you get, how do you derive the other?  (Not unaddressable,
> + but it doesn't seem straightforward to me.)
>
> Presumably, to designate the referent of r1 via a normal lvalue, one
> could write "*&r1" or more elegantly "referent(r1)" where referent is
> defined: T& referent( ref<T> r ) { return r; }

So, you're telling me that:
     r1=r2;
results in a reseating, but:
     r1=&r2;
results in a value copy?  Or was it:
     &r1=r2;
for a value copy?  Either way, this looks very poorly thought out to me.

>
> + It becomes a real mess when
> + you deal with associative containers, who cannot allow their "index"
> + type to be mutable in any way that affects ordering.
>
> Many experts claim that it's a real mess to put pointers into
> containers, but I've never found a way to avoid it.  It seems I always
> have objects that I want to put on multiple lists.  In such cases,
> however, I don't see that hiding this level of indirection would be
> intrinsically dangerous, except that (for now) it would be
> non-idiomatic.

Pointers in containers can be tricky.  I usually encapsulate indirect
containers.  But what I was talking specifically about is using ref<T>
values as keys in a map<> or set<> or such.  When a value is set in such
a container, the reference would be copied as the (indirect) key, but
when a comparison (of the general form less<>(ref<T> left, ref<T>
right)) occurs, their referent would be compared.  This looks to me like
a recipe for violating the class invariants of such containers.  When
you use pointers as keys, at least both copy and comparison is on the
address.

Adam Peterson

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 13 Oct 2003 17:47:56 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bm625i$f35$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + The problem with the phrase "automatically dereferenced pointer" is
+> + the use of the word "pointer"; it creates the inaccurate impression
+> + that references are pointers.
+>
+> Marcin's claim is that the automatically-dereferenced-pointer view
+> "always works", not that it is metaphyically accurate.
+
+ [snip]
+
+> So, Let's phrase the automaticaly-dereferenced-pointer view more
+> precisely as a hypothesis:
+>
+>   If in a given program we replace:
+>     - a declaration the form "T& x" with "T* x" and
+>     - the subsequent initialization "x(...)" with "x(&...)" and
+>     - all subsequent occurrences of x in the scope of that
+>       declaration with "*x"
+>   the behavior of the program will not change.
+>
+> The important things to notice about this hypothesis are that:
+>
+>   - It doesn't say that references *are* automatically dereferenced
+>     pointers.  Rather, it says that references *behave* as would
+>     automatically dereferenced pointers.
+>
+>   - It has nothing to do with how references and/or pointers are
+>     implemented.
+>
+> As far as I know the hypothesis is almost always true, but there are a
+> few of special cases that need to be mentioned:
+>
+>   - if x had been a const reference than its initializer could have
+>     been an rvalue, in which case the above wouldn't work, unless
+>     we also declared a temporary that value, etc.
+>
+>   - if x is a member of a class-or-struct type and the only thing
+>     that keeps that type from being POD (plain-old-data), then
+>     the above transformation would make the type POD and subject
+>     it to C's layout rules, which require that space be allocated
+>     for objects that can otherwise be optimized away, i.e., the
+>     size of the type might expand a bit in rare cases.
+>
+>   - There is another obscure case occurs during construction or
+>     destruction of some objects that I don't remember right now.
+>     (James Kanze showed it to me several years ago.)
+
+ These "special cases" demonstrate that a) the
+ "automatically-dereferenced-pointer view" _doesn't_ always work, and
+ b) your hypothesis is false.

That, of course, is why I mentioned these special cases.

+ I put "special cases" in quotes because they're not really all that
+ special; they are consequences of the definition of references, and
+ consequences of the fact that references are not pointers, not even
+ conceptually.

None of these differences is intrinsic to the notion of reference or
pointer:

   - Case 1: D&E states that the ability to initialize const
     references from non-lvalues is important because "this is what
     allows a Fortran function to be called with a constant".  Definitely
     not intrinsic to the notion of reference.

   - Case 2: I've read that the distinction between POD and non-POD
     objects was introduced to allow certain space optimizations
     without losing C compatibility.  Definitely not an intrinsic
     difference between references and pointers.

   - Case 3: We haven't yet established what case three is.

+ I frankly don't see the advantage in pretending that references are
+ automatically dereferenced pointers. What do you gain from this view?

Advantage is a relative notion, and the predominant alternative to the
automatically-dereferenced-pointer view is the references-are-aliases
view.  Let's compare the usefulness of those two perspectives in
resolving question and claims that people pose about references.

Consider "int& r = a[i];".  Does *p get reevaluated each time r is
used?  The references-are-aliases perspective cannot resolve that
question, because "#define r a[i]" also make r an alias for "a[i]".

Consider the following claim by Dr. Pizza:

  In general, a compiler should set aside no storage for a reference
  (i.e. the reference should exist purely as a name for the programmer
  to manipulate without any representation).  The exception is passing
  by reference.

If one thinks that all references (except those used to pass objects)
are mere aliases, it's reasonable to expect that they can go away
after compilation.  The automatically-dereferenced-pointer view makes
it clear that the run-time state of references has to be stored unless
in can be inferred at compile time, which can't happen when the
referent or its location isn't known until run time.

Consider the question of whether a reference can dangle.  Everyone
knows that pointers can dangle, and everyone knows how and why that
happens.  But what's meant by "a dangling alias"?

Consider the question of whether the return value of a function can be
a reference, and, if so, what does it mean to return a reference.
>From the automatically-dereferenced-pointer perspective, the answer is
obvious.  But from the references-are-aliases perspective we are left
to wonder exactly what alias gets returned.

The list goes on and on.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Ken@Alverson.net (Ken Alverson)
Date: Tue, 23 Sep 2003 22:45:40 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...
>
> + and would be liklely confusing.  Why would you want to avoid that *
> + after all.
>
> Auto-dereferencing appears not to confuse Java, C#, and Python
> programmers.  I'm told that C# supports both implicit and explicit
> dereferencing.

Apples and oranges.  The only operations you can perform on a non-dereferenced
Java variable are assignment and comparison.  Dot notation in Java *always*
means dereferencing.  C# muddies the water slightly with non-reference types
(which are never dereferenced) and user definable comparison operators (which
dereference if and only if they are defined, otherwise reference comparison is
used).  There is no confusion as to whether something is being dereferenced or
not.

C# does have the concept of user defined implicit conversion operators,
similar to C++, however when evaluating a dot expression, implicit conversions
are not considered, like C++.

I don't know if Python does what you ask or not.

Ken


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Tue, 23 Sep 2003 22:46:10 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bkomfv$aqo$2@glue.ucr.edu>...
> "Balog Pal" <pasa@lib.hu> wrote:
> [...]
> + In generic libraries designers tend to avoid implicit conversions -- in
> + the past it was a frequent debate whether its handy or evil.
>
> Agreed.
>
> + But C++ programmers look at those opjects as smart _pointers_ not as
> + substitute to objects,
>
> Agreed.
>
> + so auto-edreferencing is not a wanted behavior,
>
> I and others want it.
>
> + and would be liklely confusing.  Why would you want to avoid that *
> + after all.
>
> Auto-dereferencing appears not to confuse Java, C#, and Python
> programmers.  I'm told that C# supports both implicit and explicit
> dereferencing.

I'm a little confused. It sounds like you want to type "." instead of
"->".

As far as I can see it would be pretty easy to give you what you want
if you're willing to settle for "->" instead of ".".

But you seem to be claiming that "->" vs. "." is a significant
bottleneck in understanding and learning for people coming from
Java/C#/Python. That sounds very hard to believe. It's syntax, and
can't possibly be more of a problem than e.g., the template syntax
that would be required to use such a hypothetical smart pointer.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Wed, 24 Sep 2003 05:24:43 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bk75n8$dbb$1@glue.ucr.edu...
Bj   rn Sachsenberg <eloso@gmx.de> wrote:

>Thanks.  Unfortunately, the smart pointers I've found so far
>automatically delete but don't automatically dereference -- e.g., per
>the Boost web page:

That's a deliberate choice. Add an operator TYPE & returning *this to have
most of that behavior.   In generic libraries designers tend to avoid
implicit conversions -- in the past it was a frequent debate whether its
handy or evil.

But C++ programmers look at those opjects as smart _pointers_ not as
substitute to objects, so auto-edreferencing is not a wanted behavior, and
would be liklely confusing. Why would you want to avoid that * after all.

(OTOH implicit conversion to the raw pointer type is reasonable.)

Paul



---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Wed, 24 Sep 2003 05:24:59 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...

> + so auto-edreferencing is not a wanted behavior,
>
> I and others want it.

Well, as it was pointed out, you can have a smart ref that can be used as is
on function calls, but you still must use -> instead of . to access members.
Overloading . was discussed several times too here, google it up if
interested.  It's not a painless issue.

> + and would be liklely confusing.  Why would you want to avoid that *
> + after all.
>
> Auto-dereferencing appears not to confuse Java, C#, and Python
> programmers.

C# I dunno. Java has only a single kind of handles, so there you have
nothing to confuse. In C++ you have distinct pointer and ref. To avoid
confusion you had to remove one of those.   People would ot like that. ;-)

Python is variant-typed, not a good parallel for the case.

> I'm told that C# supports both implicit and explicit
> dereferencing.

There were other discussions, on make . -> and :: usage smarter. IOW let the
compiler do the job instead of issuing that all-popular "use . instead
of ->" and "use -> instead of ."

(I personally pretty much miss the feature of accessing typedefs through an
object instance. )

Having something like that would solve much of your problems I guess without
needing an overload of . .  But not without a cost of introducing ambiguity
where none was present before. And even chance to access an unexpected
member.

In practice I find myself use pointers (raw or smart alike) so rarely in the
application code, so I don't see a real benefit of having such an autoref.
As most functions pass objects by regular refs, and is they create one, it's
local.  And my dynamic ones are in collections.

Paul



---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 24 Sep 2003 05:25:12 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
[...]
+ I'm a little confused. It sounds like you want to type "." instead of
+ "->".
+
+ As far as I can see it would be pretty easy to give you what you want
+ if you're willing to settle for "->" instead of ".".
+
+ But you seem to be claiming that "->" vs. "." is a significant
+ bottleneck in understanding and learning for people coming from
+ Java/C#/Python. That sounds very hard to believe. It's syntax, and
+ can't possibly be more of a problem than e.g., the template syntax
+ that would be required to use such a hypothetical smart pointer.

Under reference semantics, "a = b" causes a to refer to the same
object as b (just as with pointers), and "a == b" is true if and only
if a and b refer to the same object (just as with pointers).  The
transition from reference semantics to value semantics is goes beyond
replacing "." with "->"; "a" must be replace by "*a" in ALL contexts
other than assignment and equality/nonequality comparisions.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Wed, 24 Sep 2003 15:24:11 +0000 (UTC)
Raw View
""David B. Held"" <dheld@codelogicconsulting.com> wrote in message
news:bkq1h0$dvd$1@news.astound.net...

> > (OTOH implicit conversion to the raw pointer type is reasonable.)
>
> ???  And give away ownership without so much as a wink and a nod?

That conversion is just implemeted as {return get();}  and has nothing to do
with altering the ownership.  One needs the same observations as when using
get().

[And I just mentioned it as opposite to conversion to an object reference --
don't want to start a debate if it's good, especially for everyone or most
people. I use string and auto_ptr variants with conversions and never had a
problem, but I'm aware of the possibilities.]

Paul




---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 24 Sep 2003 15:25:32 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bkomfv$aqo$2@glue.ucr.edu...
+
+> + so auto-edreferencing is not a wanted behavior,
+>
+> I and others want it.
+
+ Well, as it was pointed out, you can have a smart ref that can be used as is
+ on function calls, but you still must use -> instead of . to access members.
+ Overloading . was discussed several times too here, google it up if
+ interested.  It's not a painless issue.

If a is of type ref<T>, we'd want "cout << a" to print out a's
referent.  Similarly for every other operator.  Perhaps it would be
possible to achieve the semantics I want by overloading *every*
operator.  I hadn't thought of that.

+> + and would be liklely confusing.  Why would you want to avoid that *
+> + after all.
+>
+> Auto-dereferencing appears not to confuse Java, C#, and Python
+> programmers.
+
+ C# I dunno. Java has only a single kind of handles, so there you have
+ nothing to confuse. In C++ you have distinct pointer and ref. To avoid
+ confusion you had to remove one of those.   People would ot like that. ;-)

Huh?  C++ already has two types of handles, one of which (in effect)
features implicit dereferencing.  The rub is that the implicitly
dereferenced handle is not reseatable.

[...]
+ In practice I find myself use pointers (raw or smart alike) so rarely in the
+ application code, so I don't see a real benefit of having such an autoref.
+ As most functions pass objects by regular refs, and is they create one, it's
+ local.  And my dynamic ones are in collections.

C++ is a multiparadigm language, and I've read that there are
STL-based paradigms that avoid the need for explicit memory
management.  Perhaps there are paradigms that avoid the need for
pointers as well -- Fortran programmers seem to manage without them.
But I don't see such drastic paradigm shifts as a way for students
from the Java generation to do significant C++ projects within a
ten-week academic term.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Wed, 24 Sep 2003 15:26:01 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bkqv18$4r$1@glue.ucr.edu>...

> Bob Bell <belvis@pacbell.net> wrote:
> [...]
> > I'm a little confused. It sounds like you want to type "." instead
> > of "->".

> > As far as I can see it would be pretty easy to give you what you
> > want if you're willing to settle for "->" instead of ".".

> > But you seem to be claiming that "->" vs. "." is a significant
> > bottleneck in understanding and learning for people coming from
> > Java/C#/Python. That sounds very hard to believe. It's syntax, and
> > can't possibly be more of a problem than e.g., the template syntax
> > that would be required to use such a hypothetical smart pointer.

> Under reference semantics, "a = b" causes a to refer to the same
> object as b (just as with pointers), and "a == b" is true if and only
> if a and b refer to the same object (just as with pointers).  The
> transition from reference semantics to value semantics is goes beyond
> replacing "." with "->"; "a" must be replace by "*a" in ALL contexts
> other than assignment and equality/nonequality comparisions.

Such as?  The only interest I can see in this proposal is to facilitate
C++ for Java programmers.  Off hand, I can only think of four operators
in Java that are valid for a reference type: =, ==, != and ..  In C++,
these map directly to =, ==, != and ->.

If you need a *, you are doing something that you couldn't do in Java
anyway, so referring to Java is no good.

Personally, I would rather prefer to keep the distinction we now have.
Anyone using C++ MUST deal with the fact that pointers are first class
objects in C++, and that there are two "reference" types.  Just as they
must deal with the fact that C++ supports (and uses) true value types,
including for user defined types.

--
James Kanze           GABI Software        mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/     http://www.gabi-soft.fr
                    Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Wed, 24 Sep 2003 15:27:47 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bkom4q$aqo$1@glue.ucr.edu>...

> For those who prefer explicit dereferencing, C++ offers a plethora of
> explicitly dereferenced pointer types.  But programmers in lots of
> languages (Java, C#, Python, and others) get along very well without
> explicit dereferencing, and some legitimately prefer implicit
> dereferencing.

In this case, I think that the comparison between the languages is not
valid.  As far as I know, none of the languages with implicit
dereferencing have value types, and pointers are not first class objects
in any of them.  That makes a difference.  Implicit dereferencing in C++
would just be one more point of confusion (especially since we would
also still have explicit dereferencing).

C++ and Java are different languages.  With different idioms.  If you
really want Java, it's not too difficult to find.

>  In fact, that is also true of many C++ programmers, i.e., many C++
> programmers use C++ references over pointers whenever possible.

That's to avoid having to check for NULL.  In the case of const
references, it is also to be able to bind a temporary.  In some cases,
it is also nice to know that the reference is never reseated -- it can
make reasoning about class invariants a lot simpler.

>  Unfortunately, C++ references are an incomplete solution for those
> who prefer implicit dereferencing becase, by design, they cannot be
> reseated --- these other languages suspend implicit dereferencing in
> assignments and equality/nonequality comparisons.

That's precisely the main distinction between references and pointers.
If you want to reseat, you use a pointer.  If you want to prevent
reseating, you use a reference.

> The obvious question is: "Why bother?"  In fact, the more pointed
> questions is: "Why open the door to yet another programming paradigm
> in C++, namely the Java paradigm, which is based largely on automatic
> garbage collection and automatic dereferencing, a.k.a., "reference
> semantics".  (C++ already has automatic garbage collection available
> as a non-standard library option.  Unfortunately, ref<T> cannot be
> implemented except via some compiler supported extensions.)

> It's widely claimed that the Java paradigm is more easily learned by
> beginners and supports far more rapid development of certain classes
> of programs.

GC certainly has its advantages.  So does having a grammar without
nearly as many gotchas as C++ -- that's probably the biggest argument
for Java as a learning language.  For very, very small projects (say,
something a student could write in two or three weeks), there is also
something to be said for having the whole works in a single file, and
not being bothered by separating the class definition (interface) from
the member function defintions (implementation), even if it is a
disaster in anything bigger.

If Java fulfils certain needs, and has found a few niches where it is
appropriate, so much the better.  It doesn't bother me.  If C++ decided
to adopt some of the good points of Java, like garbage collection, or
complete and useful libraries, I'm all for it.  On the other hand, I
don't see any reason to try and hide C++'s strengths (like the fact that
pointers are first class objects, or that you can have inout or out
parameters) just to make it look like Java.

> Whether that is true or not, I'm faced with colleagues who believe it
> and a generation of students who learned this paradigm in high
> schools, local community colleges, and undergraduate curricula around
> the world.

Unlike many C++ programmers, I actually think that Java is OK as a
teaching language, at least at the start.  There's no point in trying to
force learners to cope with all of the problems in large scale
programming directly from the start, so they don't need many of C++'s
features.  The lack of typesafe containers is a problem, but IMHO, it
may well be offset by the lack of any of the grammatic gotchas of C++ --
things that a professional programmer learns to handle almost
automatically because they are so basic, but which can be stubling
blocks to beginners.

(For those who might be wondering what gramatical gotchas I'm thinking
of, it is things like:

    std::vector< double > v( std::istream_iterator< double >( source ),
                             std::istream_iterator< double >() ) ;

declaring a function, instead of defining a variable.  For anyone with
any experience programming, the problem is immediately evident when the
program fails to compile, but I can imagine that the actual error
messages you get from the compiler would only cause confusion for a
beginner.)

> I need to rapidly assimilate them into C++-based courses and research
> projects, and that process would be much easier if they didn't need to
> make such a serious shift in programming paradigms.

The shift is necessary if they are to use C++.  Frankly, judging from
most Java programs I've seen, I'd say that a shift in paradigms is
necessary if they are going to write robust Java programs as well.

--
James Kanze           GABI Software        mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/     http://www.gabi-soft.fr
                    Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dheld@codelogicconsulting.com ("David B. Held")
Date: Thu, 25 Sep 2003 02:18:35 +0000 (UTC)
Raw View
""Balog Pal"" <pasa@lib.hu> wrote in message
news:3f7101c6@andromeda.datanet.hu...
> ""David B. Held"" <dheld@codelogicconsulting.com> wrote in message
> news:bkq1h0$dvd$1@news.astound.net...
>
> > > (OTOH implicit conversion to the raw pointer type is reasonable.)
> >
> > ???  And give away ownership without so much as a wink and a nod?
>
> That conversion is just implemeted as {return get();}  and has nothing to
> do with altering the ownership.

I think get() weakens ownership, even if it does not explicitly give it
away.

> One needs the same observations as when using get().

Except that you always know when you are doing something dangerous
with get(), because you have to specify it manually.  With the implicit
conversion, you have to look hard at every usage to make sure you
don't get one where you don't want it.

Dave


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Thu, 25 Sep 2003 02:20:15 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bkrs70$7f3$1@glue.ucr.edu...

> If a is of type ref<T>, we'd want "cout << a" to print out a's
> referent.

Errr, I would think if you have *no* op << working with ref<T> but have one
taking T const& and ref<T> has implicit conversion to T const& it should
just work as you expect.

Certainly there are cases where T and ref<T> behaves differently if T had
implicit concersions itself.

> + C# I dunno. Java has only a single kind of handles, so there you have
> + nothing to confuse. In C++ you have distinct pointer and ref. To avoid
> + confusion you had to remove one of those.   People would ot like that.
;-)
>
> Huh?  C++ already has two types of handles, one of which (in effect)
> features implicit dereferencing.

No way.  In C++ reference is not an object. It's not a handle at all. It's
nothing merely an alias to some object.  You can't d anyting with the
(really nonexistant) reference, in all operations you deal with the object.

> The rub is that the implicitly
> dereferenced handle is not reseatable.

What is the direct consequence of its nature. :)

> C++ is a multiparadigm language, and I've read that there are
> STL-based paradigms that avoid the need for explicit memory
> management.

I follow a policy of 'almost no new and absolutely no delete in application
code' for years. The seldom seen news are creating objects for pImpl and
some called during the startup only to avoid  a static-init-order problem.

All memory management is in libraries. And that "all" is not too much
either. A set of mostly templated classes implementing different flavors of
collections, including POD-restricted and polymorphic ones.

I don't have any problem to manage some memory, especially having those
smart pointers at hand to do it, but it just never appears as a need to do
by hand. :)

> Perhaps there are paradigms that avoid the need for
> pointers as well

Not counting the cases where you deal with OS or some external API I find
pretty limited use of pointers in my programs, mostly where I have an
potional argument and NULL is needed.   Stating again that I never had any
problem with pointers to make me fear or something, just the need seldom
comes to need one.
(though I never measured, I may be mistaken on the statistics...)
As the model works on objects, so does the program.   [Interestingly I find
newcomers use much more pointers in the implementation couldn't yet figure
why.]

> -- Fortran programmers seem to manage without them.
> But I don't see such drastic paradigm shifts as a way for students
> from the Java generation to do significant C++ projects within a
> ten-week academic term.

IMHO java is pretty brain-damaging in this regard.   The hyoe says no
pointers when in fact java has *only* pointers.  (The aut-dereference
property is irrelevant.)   So no wonder they will use pointers, and can't
even think without.    [A decade ago I observed hardcore C-ers couldn't cope
with the C++ way either. ]

Paul



---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 26 Sep 2003 02:57:41 +0000 (UTC)
Raw View
kanze@gabi-soft.fr wrote:
+ thp@cs.ucr.edu wrote in message news:<bkqv18$4r$1@glue.ucr.edu>...
+
+> Bob Bell <belvis@pacbell.net> wrote:
+> [...]
+> > I'm a little confused. It sounds like you want to type "." instead
+> > of "->".
+
+> > As far as I can see it would be pretty easy to give you what you
+> > want if you're willing to settle for "->" instead of ".".
+
+> > But you seem to be claiming that "->" vs. "." is a significant
+> > bottleneck in understanding and learning for people coming from
+> > Java/C#/Python. That sounds very hard to believe. It's syntax, and
+> > can't possibly be more of a problem than e.g., the template syntax
+> > that would be required to use such a hypothetical smart pointer.
+
+> Under reference semantics, "a = b" causes a to refer to the same
+> object as b (just as with pointers), and "a == b" is true if and only
+> if a and b refer to the same object (just as with pointers).  The
+> transition from reference semantics to value semantics is goes beyond
+> replacing "." with "->"; "a" must be replace by "*a" in ALL contexts
+> other than assignment and equality/nonequality comparisions.
+
+ Such as?

cout << a;   // where a has type ref<string>

+ The only interest I can see in this proposal is to facilitate
+ C++ for Java programmers.

Also for programmers who'd like to minimize the distraction of
explicit dereferencing.

+ Off hand, I can only think of four operators
+ in Java that are valid for a reference type: =, ==, != and ..  In C++,
+ these map directly to =, ==, != and ->.
+
+ If you need a *, you are doing something that you couldn't do in Java
+ anyway, so referring to Java is no good.

One would like to use stream I/O.

+ Personally, I would rather prefer to keep the distinction we now have.

It wouldn't go away.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 26 Sep 2003 02:57:51 +0000 (UTC)
Raw View
kanze@gabi-soft.fr wrote:
+ thp@cs.ucr.edu wrote in message news:<bkom4q$aqo$1@glue.ucr.edu>...
+
+> For those who prefer explicit dereferencing, C++ offers a plethora of
+> explicitly dereferenced pointer types.  But programmers in lots of
+> languages (Java, C#, Python, and others) get along very well without
+> explicit dereferencing, and some legitimately prefer implicit
+> dereferencing.
+
+ In this case, I think that the comparison between the languages is not
+ valid.  As far as I know, none of the languages with implicit
+ dereferencing have value types, and pointers are not first class objects
+ in any of them.  That makes a difference.  Implicit dereferencing in C++
+ would just be one more point of confusion (especially since we would
+ also still have explicit dereferencing).

I'm told that C# has both reference semantics (implicitly dereferenced
pointers) and explicitly dereferenced pointers.

+ C++ and Java are different languages.  With different idioms.  If you
+ really want Java, it's not too difficult to find.

Of course.

+>  In fact, that is also true of many C++ programmers, i.e., many C++
+> programmers use C++ references over pointers whenever possible.
+
+ That's to avoid having to check for NULL.  In the case of const
+ references, it is also to be able to bind a temporary.

And in some cases the programmer simply wants to improve readability
by getting rid of the clutter of the dereferencing operator.

+ In some cases,
+ it is also nice to know that the reference is never reseated -- it can
+ make reasoning about class invariants a lot simpler.

And in the reseatable case one can use const declarations.

+>  Unfortunately, C++ references are an incomplete solution for those
+> who prefer implicit dereferencing becase, by design, they cannot be
+> reseated --- these other languages suspend implicit dereferencing in
+> assignments and equality/nonequality comparisons.
+
+ That's precisely the main distinction between references and pointers.

And I'm suggesting a type where the difference ends right there.

+ If you want to reseat, you use a pointer.  If you want to prevent
+ reseating, you use a reference.

But if you want reseatability without the baggage of explicit
dereferencing, there is currently no option.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Fri, 26 Sep 2003 17:26:53 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bkqv18$4r$1@glue.ucr.edu...
> Bob Bell <belvis@pacbell.net> wrote:

> Under reference semantics, "a = b" causes a to refer to the same
> object as b (just as with pointers), and "a == b" is true if and only
> if a and b refer to the same object (just as with pointers).

And this is what you want to bring in C++?    If yes, in short I'd suggest:
forget it. :)  [no pun intended]

As I view tha Java way of handling stuff is just bad.
It masks away the difference between IsEqual and IsSame. Seing what is
fundamental on both design and implementation level.

And throws orthogonality out of the window.

If comeone does nothing but Java he probably can live with that mess, just
learning that some stuff behaves this way, other behaves that way, you must
know if something is builtin type or a class type.

But in design of C++ orthogonality was a key element. Bjarne kept strong
constraints to kepp it, and the communit can build on its existance.    So
breaking it would confuse extremely many programmers, especially the better
ones.

So if we had auto_ref that would work similar to auto_ptr, working as
replacement of an object, then = and == would still work on the value.  And
you'd have .reseat() to change the referent.

At least I can't imagine any other design could gain wide acceptance.

Paul


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Fri, 26 Sep 2003 17:29:46 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bkqv18$4r$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> [...]
> + I'm a little confused. It sounds like you want to type "." instead of
> + "->".
> +
> + As far as I can see it would be pretty easy to give you what you want
> + if you're willing to settle for "->" instead of ".".
> +
> + But you seem to be claiming that "->" vs. "." is a significant
> + bottleneck in understanding and learning for people coming from
> + Java/C#/Python. That sounds very hard to believe. It's syntax, and
> + can't possibly be more of a problem than e.g., the template syntax
> + that would be required to use such a hypothetical smart pointer.
>
> Under reference semantics, "a = b" causes a to refer to the same
> object as b (just as with pointers), and "a == b" is true if and only
> if a and b refer to the same object (just as with pointers).  The
> transition from reference semantics to value semantics is goes beyond
> replacing "." with "->"; "a" must be replace by "*a" in ALL contexts
> other than assignment and equality/nonequality comparisions.

Sorry, I wasn't explicit enough. If you use a smart pointer type<T>
that provides an implicit conversion to T&, then

"a = b" causes a to refer to the same object as b
"a == b" is true if and only if a and b refer to the same object
"a" can be used to refer to the object; you don't have to use "*a"

So I repeat: you get what you want, except that you must use "->" to
refer to object members instead of "."

What am I missing? As it stands, I don't really see much of a problem
here.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 26 Sep 2003 17:31:19 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bkrs70$7f3$1@glue.ucr.edu...
+
+> If a is of type ref<T>, we'd want "cout << a" to print out a's
+> referent.
+
+ Errr, I would think if you have *no* op << working with ref<T> but have one
+ taking T const& and ref<T> has implicit conversion to T const& it should
+ just work as you expect.

Right.

+ Certainly there are cases where T and ref<T> behaves differently if T had
+ implicit concersions itself.

That would be so under a one-implicit-conversion rule.

+> + C# I dunno. Java has only a single kind of handles, so there you have
+> + nothing to confuse. In C++ you have distinct pointer and ref. To avoid
+> + confusion you had to remove one of those.   People would ot like that.
+ ;-)
+>
+> Huh?  C++ already has two types of handles, one of which (in effect)
+> features implicit dereferencing.
+
+ No way.  In C++ reference is not an object. It's not a handle at all. It's
+ nothing merely an alias to some object.  You can't d anyting with the
+ (really nonexistant) reference, in all operations you deal with the object.

What's an alias if it isn't a handle?

+> The rub is that the implicitly
+> dereferenced handle is not reseatable.
+
+ What is the direct consequence of its nature. :)

That's why I'm suggesting another one with a slightly different nature.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sat, 4 Oct 2003 01:44:47 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bldutm$4da$1@glue.ucr.edu>...
> "Balog Pal" <pasa@lib.hu> wrote:
> I would assume that Java programmers preserve orthogonality by viewing
> expressible values as having identity, e.g., that "i=3" assigns the
> identity of the constant 3 to the variable i.  Where's the danger in
> that perspective?

How about the fact that "3" _is not_ an entity with its own identity?

> + But as sson as you step out of those restrictions (say, migrating to C++,
> + where they never existed),  you'll soon shoot yourself in the foot.    I
> + mean your students, who are not aware that in java they learned identity and
> + state is the same anyway  [if state is finalised on creation it really is]
> + and even find it silly to think otherwise.
>
> To me, the notion that each value has its own identity seems natural
> enough.

So in the following statements

   int i = 3;
   int j = 3;

Do i and j somehow contain or refer to the same entity? That makes no
sense to me, and certainly isn't what makes sense in C++.

> +> I'm not suggesting anything radically new in this  regard.
> +
> + Even if it's not "radically" new, the suggestion would bring in a mixed
> + type, a chimaira. It will not be intuitive to anyone using C++, IOW it would
> + counfuse the hell out of anyone  reading the code.    Pretty soon that would
> + include your students as well.
>
> The semantics of the type scheme I proposed is very simple and easily
> stated.  It is accepted without major confusion in several recent
> programming langauges including C#, which I'm told also has explicitly
> dereferenced handles (a.k.a. "pointers").

It may work in other languages, but they aren't C++. I just don't see
how you can make pointers or references do what you want, without
making them not be pointers or references anymore. Maybe you should
give us a concrete proposal that shows how this would work. Show how
it will not change existing semantics (i.e., not break existing code),
yet provide the behavior you want.

> +> + If comeone does nothing but Java he probably can live with that mess, just
> +> + learning that some stuff behaves this way, other behaves that way, you must
> +> + know if something is builtin type or a class type.
> +>
> +> Once again: C++ pointers and C++ references behave in way to which you
> +> are objecting.
> +
> + Nope.  If you still feel they are, please elaborate what you mean here to
> + clear the rest of misunderstanding.
>
> Pointers are explicitly dereferenced and references are implicitly
> dereferenced.  Having both in C++ doesn't cause unmanageable
> confusion.

That's because they're not the same thing. No one expects them to
behave the same way. Pointers have value, can be copied around,
reseated, compared, etc. References don't have value, can't be copied,
can't be reseated, can't be compared, etc. Your confusion seems to
stem from a mistaken belief that pointers and references are two
variations on the same theme; they are not.

> + And back to your main problem with teaching C++: you should just not rush to
> + introduce pointers.
>
> How do you propose representing say an abstract syntax tree without
> pointers?  Of course, it can be done the same way a Fortran programmer
> would do it: by using array indices instead of addresses.  But that
> introdces yet another level of tedium.

You would start beginners with abstract syntax trees?

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sat, 4 Oct 2003 09:09:07 +0000 (UTC)
Raw View
On Sat, 04 Oct 2003 01:44:47 +0000, Bob Bell wrote:

> How about the fact that "3" _is not_ an entity with its own identity?

How do you know that by observing effects of the program (without looking
at the implementation)?

The clue is that - as long as they are immutable - it's impossible to
distinguish whether they have identities. So we pretend they do, and the
rules are consistent, even if the implementation represents integers
differently than most of other objects.

There are other cases where Java primitive types have weird semantics:
they can't be interconverted with "object", they can't be synchronized on,
and the usage of operators is special. But they have regular reference
passing semantics.

>    int i = 3;
>    int j = 3;
>
> Do i and j somehow contain or refer to the same entity? That makes no
> sense to me, and certainly isn't what makes sense in C++.

It makes sense to Java, Lisp, Python, Ruby, Smalltalk, Prolog, SML,
Haskell etc. (well, in many languages the answer is that it doesn't matter
whether they refer to the same entity). You are right that it doesn't make
sense in C++ because C++ variables contain objects instead of pointing to
them. This is a fundamentally different point of view of value passing and
variables, you can't judge one side thinking in terms of the other side.
Sorry for off-topic.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 5 Oct 2003 18:54:42 +0000 (UTC)
Raw View
qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.04.09.03.51.326256@knm.org.pl>...
> On Sat, 04 Oct 2003 01:44:47 +0000, Bob Bell wrote:
>
> > How about the fact that "3" _is not_ an entity with its own identity?
>
> How do you know that by observing effects of the program (without looking
> at the implementation)?

I come at it the other way around: by observing the effects of the
program, I cannot establish that "3" has an identity. However, by
observing the effects of the program, I _can_ establish that an entity
object has identity. Therefore I conclude that "3" doesn't have
identity, while the object does.

Keep in mind that things like "identity" are concepts that we make up
to allow us to reason about the behavior of the program. Program
objects don't have identity in the same way that physical objects do,
but the model is close enough that we pretend they're the same.

Reasoning based on "'3' has identity" doesn't get very far in C++.

> The clue is that - as long as they are immutable - it's impossible to
> distinguish whether they have identities. So we pretend they do, and the
> rules are consistent, even if the implementation represents integers
> differently than most of other objects.
>
> There are other cases where Java primitive types have weird semantics:
> they can't be interconverted with "object", they can't be synchronized on,
> and the usage of operators is special. But they have regular reference
> passing semantics.

When I conclude that "3" is a value without identity, the rules are
even more consistent, because I don't expect literal values to behave
like objects with identity.

I don't understand what value you gain by pretending that "3" is an
entity with identity. Can you distinguish different "3"'s? Can you do
something with one "3" that you don't do with another? Can you take
"3"'s address or create a reference to it?

> >    int i = 3;
> >    int j = 3;
> >
> > Do i and j somehow contain or refer to the same entity? That makes no
> > sense to me, and certainly isn't what makes sense in C++.
>
> It makes sense to Java, Lisp, Python, Ruby, Smalltalk, Prolog, SML,
> Haskell etc. (well, in many languages the answer is that it doesn't matter
> whether they refer to the same entity). You are right that it doesn't make
> sense in C++ because C++ variables contain objects instead of pointing to
> them. This is a fundamentally different point of view of value passing and
> variables, you can't judge one side thinking in terms of the other side.
> Sorry for off-topic.

I'm not judging what Java, Lisp, Python, etc. programmers think, I'm
just talking about how C++ behaves. If a Java programmer wants to use
C++, pretending that "3" has identity will sooner or later lead to
trouble. Java programmer using C++ must learn to use C++ as C++, not
Java with slightly different syntax. IMHO, one of the bigger mistakes
Java made was making the syntax so similar with such different
semantics. It creates no end of problems for programmers migrating
between the two and being lulled into thinking the languages are
similar.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 5 Oct 2003 18:54:44 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<bldutm$4da$1@glue.ucr.edu>...
[...]
+> To me, the notion that each value has its own identity seems natural
+> enough.
+
+ So in the following statements
+
+   int i = 3;
+   int j = 3;
+
+ Do i and j somehow contain or refer to the same entity?

They refer to the same integer value.

+ That makes no sense to me, and certainly isn't what makes sense in
+ C++.

Perhaps you'd prefer the verb "contain" or "hold" instead of "refer
to", but operationally that's a distinction without a difference.

[...]
+> The semantics of the type scheme I proposed is very simple and easily
+> stated.  It is accepted without major confusion in several recent
+> programming langauges including C#, which I'm told also has explicitly
+> dereferenced handles (a.k.a. "pointers").
+
+ It may work in other languages, but they aren't C++.

Of course.

+ I just don't see
+ how you can make pointers or references do what you want, without
+ making them not be pointers or references anymore.

Right!  And, I'm not proposing to modify the semantics of pointers or
references in any way.

+ Maybe you should
+ give us a concrete proposal that shows how this would work. Show how
+ it will not change existing semantics (i.e., not break existing code),
+ yet provide the behavior you want.

I'm proposing a new library type scheme, ref<T>, whose semantics is
exactly that of pointer-to-T but with the following exception: in all
contexts except the operands of =, ==, and !=, an expression of type
ref<T> undergoes an implicit-dereferencing conversion, e.g.,

   ref<int> a(3);
   ref<int> b(4);
   std::cout << a+b;

prints 7.

[...]
+> Pointers are explicitly dereferenced and references are implicitly
+> dereferenced.  Having both in C++ doesn't cause unmanageable
+> confusion.
+
+ That's because they're not the same thing.

Of course.  And, ref<T> would be different from each of them as well.

+ No one expects them to behave the same way.

Of course.

+ Pointers have value, can be copied around, reseated, compared, etc.

Agreed.

+ References don't have value, can't be copied, can't be reseated, can't be
+ compared, etc.

The crippling of C++ references was an arbitrary design decision.

   References were introduced primarily to support operator overloading.
   Doug McIlroy recalls that once I was explaining some problems with
   a precursor to the crrent operator overloading scheme to him.  He
   used the word "reference" with the startling effect that I muttered
   "Thank you," and left his office to reappear the next day with the
   current scheme essentially complete.  Doug had reminded me of Algol68.
   ...
   It is not possible to change what a reference refers to after
   initialization.  That is, once a C++ reference is initialized it
   cannot be made to refer to a different object later; it cannot be
   re-bound.  I had in the past been bitten by Algol68 references where
   r1=r2 can either assign through r1 to the object referred to or assign
   a new reference value to r1 (re-binding r1) dependigon te tye of r2.
   I wanted to avoid such problems in C++.
                                                    D&E, pages 85 and 86

Reseatable references have existed in languages before and since, and
are in no way incompatible with pointers or other features of C++.

+ Your confusion seems to
+ stem from a mistaken belief that pointers and references are two
+ variations on the same theme; they are not.

Modulo some arbitrary restrictions of references that were imposed for
safety reasons, pointers and references differ primarily in the fact
that one is implicitly dereferenced and the other is explicitly
dereferenced.

+> How do you propose representing say an abstract syntax tree without
+> pointers?  Of course, it can be done the same way a Fortran programmer
+> would do it: by using array indices instead of addresses.  But that
+> introdces yet another level of tedium.
+
+ You would start beginners with abstract syntax trees?

We're talking about incoming graduate students and third-year transfer
students who have been raised on Java.  The point is to facilitate the
writing of Java programs in C++ while they are master bit
manipulation, value semantics, generic programming.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Sun, 5 Oct 2003 20:02:45 +0000 (UTC)
Raw View
On Sun, 05 Oct 2003 18:54:42 +0000, Bob Bell wrote:

> I don't understand what value you gain by pretending that "3" is an
> entity with identity.

That "=" always does the same thing (changing the variable to point to
another object) instead of sometimes changing the pointer, sometimes the
value.

> Can you distinguish different "3"'s?

There happens to exist one object with the value of 3, so there are no
different 3's to distinguish. I know this because "==" always compares
object identity and it's guaranteed that 3 == 3.

> Can you take "3"'s address or create a reference to it?

3 itself is the reference. Java doesn't have references to references.

> If a Java programmer wants to use C++, pretending that "3" has identity
> will sooner or later lead to trouble.

Agreed, because C++ allows to create a pointer to an object which contains
an int and is mutable. I'm pointing out that the Java model is internally
consistent considering "=" and "==". The inconsistent bit is that int is
not a subtype of object.

Translated to C++: all variables and object fields are pointers, "=" is
"=" on pointers, "==" is "==" on pointers, 3 is the address of a unique
object containing this number, "+" takes two pointers to integers and
returns a pointer to integer (a unique object with the desired value),
"." is C++'s "->", "new" is "new"...

So the parts which look like C++ but behave differently are mostly
numeric literals and arithmetic operators, and that all types are
implicitly pointers - it would be silly to make them look different
just because of this :-)  "." could look like "->" instead but then
the "." symbol would be mostly unused, so instead "->" is unused.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 5 Oct 2003 20:50:42 +0000 (UTC)
Raw View
James Kanze <kanze@alex.gabi-soft.fr> wrote:
+ thp@cs.ucr.edu writes:
+
+ |>  > If you want to reseat, you use a pointer.  If you want to prevent
+ |>  > reseating, you use a reference.
+
+ |>  But if you want reseatability without the baggage of explicit
+ |>  dereferencing, there is currently no option.
+
+ But I don't really see where "explicit dereferencing" is baggage.  Why
+ is it more bothersome to write -> than to write . ?

Because it violates orthogonality.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 5 Oct 2003 20:56:10 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.04.09.03.51.326256@knm.org.pl>...
+> On Sat, 04 Oct 2003 01:44:47 +0000, Bob Bell wrote:
+>
+> > How about the fact that "3" _is not_ an entity with its own identity?
+>
+> How do you know that by observing effects of the program (without looking
+> at the implementation)?
+
+ I come at it the other way around: by observing the effects of the
+ program, I cannot establish that "3" has an identity. However, by
+ observing the effects of the program, I _can_ establish that an entity
+ object has identity. Therefore I conclude that "3" doesn't have
+ identity, while the object does.
+
+ Keep in mind that things like "identity" are concepts that we make up
+ to allow us to reason about the behavior of the program. Program
+ objects don't have identity in the same way that physical objects do,
+ but the model is close enough that we pretend they're the same.
+
+ Reasoning based on "'3' has identity" doesn't get very far in C++.

To many C/C++ programmers, identity == address, but in C++ there are
objects that have no address, specifically struct-or-class objects
returned by value from a function.

By taking the view that expressible values have identity, it becomes
apparent that Java's treatment of builtin types is reasonably
compatible with the way that it handles user-defined types.  To avoid
confusion, we can, of course, find some other word than "identity" to
describe the content of a reference: denotation, handle, token, alias
(in the pointer sense rather than the name sense), significance, etc.

+> The clue is that - as long as they are immutable - it's impossible to
+> distinguish whether they have identities. So we pretend they do, and the
+> rules are consistent, even if the implementation represents integers
+> differently than most of other objects.
+>
+> There are other cases where Java primitive types have weird semantics:
+> they can't be interconverted with "object", they can't be synchronized on,
+> and the usage of operators is special. But they have regular reference
+> passing semantics.
+
+ When I conclude that "3" is a value without identity, the rules are
+ even more consistent, because I don't expect literal values to behave
+ like objects with identity.
+
+ I don't understand what value you gain by pretending that "3" is an
+ entity with identity. Can you distinguish different "3"'s? Can you do
+ something with one "3" that you don't do with another? Can you take
+ "3"'s address or create a reference to it?

The common mathematical paradigm is that the number three, like all
other mathematical entities, exists and is unique and variables can
refer to it.  Consider

  int   x = 3;
  int&  r = x;

Here x refers to the integer three, and r refers to the integer
variable x.

+> >    int i = 3;
+> >    int j = 3;
+> >
+> > Do i and j somehow contain or refer to the same entity? That makes no
+> > sense to me, and certainly isn't what makes sense in C++.
+>
+> It makes sense to Java, Lisp, Python, Ruby, Smalltalk, Prolog, SML,
+> Haskell etc. (well, in many languages the answer is that it doesn't matter
+> whether they refer to the same entity). You are right that it doesn't make
+> sense in C++ because C++ variables contain objects instead of pointing to
+> them. This is a fundamentally different point of view of value passing and
+> variables, you can't judge one side thinking in terms of the other side.
+> Sorry for off-topic.
+
+ I'm not judging what Java, Lisp, Python, etc. programmers think, I'm
+ just talking about how C++ behaves.

The proposal is to add a library-based type scheme to facilitate the
transition of such programmers to C++ by providing types that
correspond to the reference semantics they are used to.

+ If a Java programmer wants to use C++, pretending that "3" has
+ identity will sooner or later lead to trouble.

Only if that programmer insists on also equating identity with
address.  One should use distinct words for these distinct concepts.

+ Java programmer using C++ must learn to use C++ as C++, not
+ Java with slightly different syntax. IMHO, one of the bigger mistakes
+ Java made was making the syntax so similar with such different
+ semantics. It creates no end of problems for programmers migrating
+ between the two and being lulled into thinking the languages are
+ similar.

It's not simply a matter of syntactic similarity.  Python programmers
come from a language that has quite different syntax from C++, but
they're equally perplexed at the lack of handles that are reseatable
and implicitly dereferenced.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 6 Oct 2003 04:48:29 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bk75n8$dbb$1@glue.ucr.edu...
+ Bj?rn Sachsenberg <eloso@gmx.de> wrote:
+
+>Thanks.  Unfortunately, the smart pointers I've found so far
+>automatically delete but don't automatically dereference -- e.g., per
+>the Boost web page:
+
+ That's a deliberate choice.

Agreed.  The point is that I'm proposing something different from
the current smart pointers.

+ Add an operator TYPE & returning *this to have most of that behavior.

That would be my preferred way of doing things, but there are a number
of technical reasons why that approach doesn't work so well.

+ In generic libraries designers tend to avoid
+ implicit conversions -- in the past it was a frequent debate whether its
+ handy or evil.

Arbitrary use of implicit conversion tends to provoke astonishment, a
bad thing in programming.  I'm proposing a library type ref<T> that
has easily stated semantics (familiar to programmers who've used any
of the more modern languages such as Java, C#, Python, etc.).  I would
hope that anyone who includes ref.h would have read and understood the
one sentence description of the semantics of ref<T>.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Mon, 6 Oct 2003 04:52:28 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bldutm$4da$1@glue.ucr.edu...

> + consider this:
> +
> + void Foo(Whatever a, Whatever b)
> + {
> +    a = b;
> +
> +    b += 1;     b.Increment(); // do anything that changes the state of b
> + here
> +
> +    // ** what here
> + }

You didn;t consider the meat of this example did you?
BTW it's the same case James Kanze pointed out on the other group with
dimension. Please try to understand what is the problem with the approach,
and how it leads to errors in current java.  As soon as you have mutable
objects.
Then consider C++ generally have mutable objects, and a lot of them.  A
plenty of idioms suggest modofocation in place, using the combned assignment
ops, etc. And not create and return a new object -- unless there's no other
way.

> I would assume that Java programmers preserve orthogonality by viewing
> expressible values as having identity, e.g., that "i=3" assigns the
> identity of the constant 3 to the variable i.  Where's the danger in
> that perspective?

No danger until everything is constant.  But suppose you have a way to
overwrite the value of that 3 somehow, while all the referents remain.  :)

> + Certainly those same students will be hit by the problem sometime, as
> + nothing in java actually prevents changing the state of an object,
>
> Why should something in Java "prevent changing the state of an
> object"?

'cos you can forget all those handles java gives you are actually pointers
and not references only until objects are immutable.   And only in that case
distinction of value and dentity is indifferent, as they map closely anyway.

With mutable objects you must renenber what poiters point where, and what
did you share actually.   Just try it, create a string class for java that
works similar to std::string. (use named functions to replace overloaded
operators.)   And give it to java students to use -- you'll see they will
find a plenty of their strings unexpectedly having unexpected value.

> The semantics of the type scheme I proposed is very simple and easily
> stated.  It is accepted without major confusion in several recent
> programming langauges including C#, which I'm told also has explicitly
> dereferenced handles (a.k.a. "pointers").

C# is a dumb copy of java as a language.  What is stripped the JVM, and
other environmental parts.

And a feature that works in some language is not enough reason to state it
will work anywhere else.  Just like boots are pretty good to climb mountains
but miserable to swim in water. You shall check how that would fit in this
environment.

And it fits badly.  Badly enough to make your proposal dropped without too
much thnking IMO. (no pun intenbded, just realistic forecast).

What you can do is to write your own 'smart ref' to the level you can in the
current language -- and live with the rest of it.

I would say you're entirely on a wrong track with the aim,  I would give
those java immigrants explicit lessions on differences and not trying to
cover them instead.

> Pointers are explicitly dereferenced and references are implicitly
> dereferenced.  Having both in C++ doesn't cause unmanageable
> confusion.

As C++ used another approach to tame the chaos. Here you need not restrict
to immutable objects, but 1/ references are nonreseatable (to the level a
reference works as a true alias) and 2/ you have const refs.    While
pointers you can change around, but everyone is aware of the problems
handling pointer issues, like pointed object's lifetime, pointer validity,
null-pointers, etc.
Most of the time you deal with objects (some being aliased by refs), and
when you stumble on a pointer, you are careful.

Whoever is not careful with those pointers may not create confusion, but
will create a core dump pretty soon. :)

> +> What's so all that orthogonal about the need to dereference?  If the
> +> ability to achieve indirection without the need to dereference breaks
> +> orthogonality, then C++'s reference have already destroyed that
> +> othogonality.
> +
> + It would if references would behave the way pointers do, but they don't.
In
> + C++ the reference behaves exactly as the original object, as a true
alias
>
^^^^^^^^^^^^
> A what?

int i;
int& ri = i; // i used here is the "original" object, ri is an alias.

but just after the line can you make a difference?

Suppose you have
= ========== a.h
int a;
int& b = a;
= ========== b.h
int b;
int& a = b;
= ==========

int main()
{
#include "q.h"
/// print out "a" or "b" here
return 0;
}
= ==========
you know q.h is copy of either a.h or b.h

write whatever code that is supposed to tell you which one. :)
[use anything but hand-made templates ot preprocessor redefining a or b.]
Or write code that produce different compile-time messages to make
distinction possible

I believe there's no way to tell the difference.

> + starting right after the creation.
>
> So you agree that references have state?

No.  Ref merely creates another _identifier_ to refer ot the object, not
another object with state.   [Note that the identifier is something that
only the compiler works with, it disappears during the compilation. ]

> + the reference has absolutely no behavior of its own,
>
> It gets initialized, and it gets dereferenced.

>From the executing program's view, neither.    At least I don't call using
'i' in the above example being dereferenced.  Nor initialised where the
compiler allocates some storage location to it (on stack, in a data segment,
a register, etc) and binds name 'i' to that location.

> + you can't even make a distinction whether you deal with a ref or
> + a genuine object.
>
> When the references is being initalized the "genuine object does not
> change state".

Definitely.  As the state of an object is defined by its 'contents'. And not
by the albel attached to it.

> + And back to your main problem with teaching C++: you should just not
rush to
> + introduce pointers.
>
> How do you propose representing say an abstract syntax tree without
> pointers?

I don't know what exatly is called that, but probably it can be implementes
using containers -- some list or tree.  [not necessarity with one found in
std::]

Note two things:
1. I didn't say you need not teach or use pointers, merely hou should not
rash with them.  Let students first work with natural objects, and use
containers.   Introduce the concept of pointers later, and postpone some
stuff until after you introduced them if necessary.

2. I claimed *application* programming can go on (almost) without hitting a
pointer.  Library programming is a different animal.   But that's more
advanced stuff, and only those already gained solid knowledge should start
it.   That certainly includes correctly using the fundamental elements of
C++ without spoilers like that java-resembling-pointer.

> + One can sit down and write programs (on the application
> + level) in C++ for months without hitting the need of a single pointer.
>
> And Fortran programmers avoid pointers entirely.

And lisp and others. :)

> + Teach all the other stuff, then when the time is here drop in the
concept of
> + pointers, and all the related stuff.
>
> The point is that I'm not teaching C++.  I'm teaching ten-week courses
> where most students know C++, and the students who don't already know
> C++ have to do the homework anyway and learn C++ as they go.

Errr, I couldn't really figure out what you actually teach then.

Paul


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Mon, 6 Oct 2003 04:53:22 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<blq09d$5ii$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk") wrote in message news:<pan.2003.10.04.09.03.51.326256@knm.org.pl>...
> +> On Sat, 04 Oct 2003 01:44:47 +0000, Bob Bell wrote:
> +>
> +> > How about the fact that "3" _is not_ an entity with its own identity?
> +>
> +> How do you know that by observing effects of the program (without looking
> +> at the implementation)?
> +
> + I come at it the other way around: by observing the effects of the
> + program, I cannot establish that "3" has an identity. However, by
> + observing the effects of the program, I _can_ establish that an entity
> + object has identity. Therefore I conclude that "3" doesn't have
> + identity, while the object does.
> +
> + Keep in mind that things like "identity" are concepts that we make up
> + to allow us to reason about the behavior of the program. Program
> + objects don't have identity in the same way that physical objects do,
> + but the model is close enough that we pretend they're the same.
> +
> + Reasoning based on "'3' has identity" doesn't get very far in C++.
>
> To many C/C++ programmers, identity == address, but in C++ there are
> objects that have no address, specifically struct-or-class objects
> returned by value from a function.

Those programmers are wrong. Here's another example why:

Foo*  ptr = new Foo();

delete ptr;

ptr = new Foo();

It's possible that the second Foo could be allocated at the same
address as the first one, but clearly they're different objects with
separate identities.

Herb Sutter talks about identity issues in some detail in More
Exceptional C++ (I think that's the one; I don't have my copy handy to
confirm).

[snip]

> + I don't understand what value you gain by pretending that "3" is an
> + entity with identity. Can you distinguish different "3"'s? Can you do
> + something with one "3" that you don't do with another? Can you take
> + "3"'s address or create a reference to it?
>
> The common mathematical paradigm is that the number three, like all
> other mathematical entities, exists and is unique and variables can
> refer to it.  Consider
>
>   int   x = 3;
>   int&  r = x;
>
> Here x refers to the integer three, and r refers to the integer
> variable x.

No, x _contains_ the _value_ 3. It's an important distinction, because
the way you state it, the relationship between x and 3 should be the
same as the relationship between r and x. This clearly isn't the case,
because the relationship between x and r lets me do things like this:

int x = 3;
int& r = x;

x = 10;

int y = r;

y now has 10 in it. There's no analogous behavior with x and 3,
because there's no "3" object that I can access/modify to change what
x contains.

[snip]

> The proposal is to add a library-based type scheme to facilitate the
> transition of such programmers to C++ by providing types that
> correspond to the reference semantics they are used to.

Beyond making C++ easier for non-C++ programmers, what benefit is
there?

> + If a Java programmer wants to use C++, pretending that "3" has
> + identity will sooner or later lead to trouble.
>
> Only if that programmer insists on also equating identity with
> address.  One should use distinct words for these distinct concepts.

Any C++ programmer (whether they were Java programmers or not)
equating address and identity is going to have problems sooner or
later anyway. Address != identity.

> + Java programmer using C++ must learn to use C++ as C++, not
> + Java with slightly different syntax. IMHO, one of the bigger mistakes
> + Java made was making the syntax so similar with such different
> + semantics. It creates no end of problems for programmers migrating
> + between the two and being lulled into thinking the languages are
> + similar.
>
> It's not simply a matter of syntactic similarity.  Python programmers
> come from a language that has quite different syntax from C++, but
> they're equally perplexed at the lack of handles that are reseatable
> and implicitly dereferenced.

The syntactic similarity of Java and C++ implies a semantic similarity
which isn't there, which leads to problems. I think the reason we
don't hear as many complaints coming from Python programmers is that
the syntactic differences between C++ and Python creates an
expectation of different semantics.

It seems we regularly see proposals to add Java semantics to C++; I
can't remember the last time I saw a proposal to add Python semantics.

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 6 Oct 2003 10:04:55 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bldutm$4da$1@glue.ucr.edu...
+
+> + consider this:
+> +
+> + void Foo(Whatever a, Whatever b)
+> + {
+> +    a = b;
+> +
+> +    b += 1;     b.Increment(); // do anything that changes the state of b
+> + here
+> +
+> +    // ** what here
+> + }
+
+ You didn;t consider the meat of this example did you?
+ BTW it's the same case James Kanze pointed out on the other group with
+ dimension. Please try to understand what is the problem with the approach,
+ and how it leads to errors in current java.  As soon as you have mutable
+ objects.

Perhaps I missed your point, which IIUC is that in Java variables of
built-in types have value semantics, while variables of class types
have reference semantics, and the two semantics coincide on immutable
objects but not on objects (since reference semantics involves an
added level of indirection).  I agree.

[...]
+ With mutable objects you must renenber what poiters point where, and what
+ did you share actually.

Agreed.  Except in single-assignment langauges, we always have the
possibility of aliasing.  And in dealing with indirection (whether
implicitly or explicly dereferenced) one has to be mindful of what
points where.

+ Just try it, create a string class for java that
+ works similar to std::string. (use named functions to replace overloaded
+ operators.)   And give it to java students to use -- you'll see they will
+ find a plenty of their strings unexpectedly having unexpected value.

Those students claim to be used to reference semantics and to find it
natural.  And, they don't find C++ refreshingly free of possibilities
for aliasing.

[...]
+ As C++ used another approach to tame the chaos. Here you need not restrict
+ to immutable objects, but 1/ references are nonreseatable (to the level a
+ reference works as a true alias) and 2/ you have const refs.
                     ^^^^^^^^^^^^
[...]
+ Ref merely creates another _identifier_ to refer ot the object, not
+ another object with state.   [Note that the identifier is something that
+ only the compiler works with, it disappears during the compilation. ]

I don't know what a "true alias" is.  Dictionaries say that aliases
are alternative names.  The standard defines a name to be a use of an
identifier and defines an identifier to be a character string composed
of letters, digits and underscores, etc.  So consider int& f(){return
*new int;}.  Obviously, f doesn't return an identifier.

Some people say that the slogan "references are aliases" uses "alias"
in the technical/metaphorical sense that it's applied pointers that
point to the same object.  But these same people reject the notion
that "reference" is a variant of the concept of "pointer", because
"references aren't objects".

So, what's an alias when it's neither a name nor a variant of a
pointer?

Things that have state are normally called "objects", and a reference
undergoes some change of state when it is initialized.  So, except in
the somewhat rare cases where referents can be inferred at compile
time, references have state that has to be represented somehow at run
time.  In that regard they are similar to const pointers.  But, for
whatever reason, the Standard does not include references among the
things it calls "objects".

Where the Standard plays Humpty Dumpty with terminology, we must
carefully distinguish between the Standard meaning and the standard
meaning. ;-)

[...]
+ 1. I didn't say you need not teach or use pointers, merely hou should not
+ rash with them.  Let students first work with natural objects, and use
+ containers.   Introduce the concept of pointers later, and postpone some
+ stuff until after you introduced them if necessary.
+
+ 2. I claimed *application* programming can go on (almost) without hitting a
+ pointer.  Library programming is a different animal.   But that's more
+ advanced stuff, and only those already gained solid knowledge should start
+ it.   That certainly includes correctly using the fundamental elements of
+ C++ without spoilers like that java-resembling-pointer.
[...]
+ Errr, I couldn't really figure out what you actually teach then.

Data structures, algorithms, compilers, operating systems, programming
languages, etc.  Pointers and references are everywhere.  The saying
goes: "There's no problem that can't be solved by adding another level
of indirection."

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 7 Oct 2003 00:45:51 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<blq09d$5ii$1@glue.ucr.edu>...
[...]
+> The common mathematical paradigm is that the number three, like all
+> other mathematical entities, exists and is unique and variables can
+> refer to it.  Consider
+>
+>   int   x = 3;
+>   int&  r = x;
+>
+> Here x refers to the integer three, and r refers to the integer
+> variable x.
+
+ No, x _contains_ the _value_ 3.

That's a figure of speech that comes from implementation
considerations.  But, if x never varies there may be no register or
memory location to "contain" the value of x.  Similarly, it may be
that r is represented via a memory location that contains a bit
pattern representing x.

+ It's an important distinction, because
+ the way you state it, the relationship between x and 3 should be the
+ same as the relationship between r and x.

For software-engineering reasons, some languages restrict what can be
done with variables that refer to other variables, and languages vary
in how the assignment operator interacts with such variables.

+ This clearly isn't the case,
+ because the relationship between x and r lets me do things like this:
+
+ int x = 3;
+ int& r = x;
+
+ x = 10;
+
+ int y = r;
+
+ y now has 10 in it. There's no analogous behavior with x and 3,
+ because there's no "3" object that I can access/modify to change what
+ x contains.

Of course not, unlike r and x, the integer three doesn't refer to
something else.  The expression "3" isn't an lvalue and cannot appear
on the left of an assignment.

[...]
+ Beyond making C++ easier for non-C++ programmers, what benefit is
+ there?

Some people find that coding with implicitly dereferenced handles
leads to more readable code.  But readability is in the eye of the
reader.

[...]
+> It's not simply a matter of syntactic similarity.  Python programmers
+> come from a language that has quite different syntax from C++, but
+> they're equally perplexed at the lack of handles that are reseatable
+> and implicitly dereferenced.
[...]
+ It seems we regularly see proposals to add Java semantics to C++; I
+ can't remember the last time I saw a proposal to add Python semantics.

Surely you've seen proposals to add GC, which Python has.  And now
you're seeing a proposal to add a library type that implements
reference semantics, which (IIUC) Python has.  IMHO, there's nothing
Java specific about this proposal except the prevalence of Java
trained students entering courses that use C++.

Tom Payne


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: belvis@pacbell.net (Bob Bell)
Date: Tue, 7 Oct 2003 21:10:36 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<blr63a$f5f$1@glue.ucr.edu>...
> Bob Bell <belvis@pacbell.net> wrote:
> + thp@cs.ucr.edu wrote in message news:<blq09d$5ii$1@glue.ucr.edu>...
> [...]
> +> The common mathematical paradigm is that the number three, like all
> +> other mathematical entities, exists and is unique and variables can
> +> refer to it.  Consider
> +>
> +>   int   x = 3;
> +>   int&  r = x;
> +>
> +> Here x refers to the integer three, and r refers to the integer
> +> variable x.
> +
> + No, x _contains_ the _value_ 3.
>
> That's a figure of speech that comes from implementation
> considerations.  But, if x never varies there may be no register or
> memory location to "contain" the value of x.  Similarly, it may be
> that r is represented via a memory location that contains a bit
> pattern representing x.

You wrote

>   int   x = 3;
>   int&  r = x;
>
> Here x refers to the integer three, and r refers to the integer
> variable x.

At best, it's misleading to use the same term ("refers") to describe
what happens on these two lines of code. What happens is _not_ the
same; thinking it is the same will lead to problems and
inconsistencies.

> + It's an important distinction, because
> + the way you state it, the relationship between x and 3 should be the
> + same as the relationship between r and x.
>
> For software-engineering reasons, some languages restrict what can be
> done with variables that refer to other variables, and languages vary
> in how the assignment operator interacts with such variables.

I must be missing something. I can't relate this to the discussion at
hand.

> + This clearly isn't the case,
> + because the relationship between x and r lets me do things like this:
> +
> + int x = 3;
> + int& r = x;
> +
> + x = 10;
> +
> + int y = r;
> +
> + y now has 10 in it. There's no analogous behavior with x and 3,
> + because there's no "3" object that I can access/modify to change what
> + x contains.
>
> Of course not, unlike r and x, the integer three doesn't refer to
> something else.  The expression "3" isn't an lvalue and cannot appear
> on the left of an assignment.

So do you agree there is no "3" object?

> [...]
> + Beyond making C++ easier for non-C++ programmers, what benefit is
> + there?
>
> Some people find that coding with implicitly dereferenced handles
> leads to more readable code.  But readability is in the eye of the
> reader.

That's what I mean by "making C++ easier for non-C++ programmers". How
many of these people are C++ programmers, as opposed to (for example)
Java programmers who want to learn C++?

> [...]
> +> It's not simply a matter of syntactic similarity.  Python programmers
> +> come from a language that has quite different syntax from C++, but
> +> they're equally perplexed at the lack of handles that are reseatable
> +> and implicitly dereferenced.
> [...]
> + It seems we regularly see proposals to add Java semantics to C++; I
> + can't remember the last time I saw a proposal to add Python semantics.
>
> Surely you've seen proposals to add GC, which Python has.  And now
> you're seeing a proposal to add a library type that implements
> reference semantics, which (IIUC) Python has.  IMHO, there's nothing
> Java specific about this proposal except the prevalence of Java
> trained students entering courses that use C++.

Of course I've seen those proposals. What I'm saying is that it's rare
to see a post along the lines of "Python has XYZ, we should add XYZ to
C++." We often see posts like "Java has XYZ, we should add XYZ to
C++."

IMHO, it's the syntactic similarity that leads to those posts. For
example, the posts I'm talking about often go something like this: "I
was trying to do XYZ in C++ because that's what works in Java. Imagine
my surprise to find out I couldn't get it to work! We should add XYZ
to C++."

Bob

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Wed, 8 Oct 2003 00:43:02 +0000 (UTC)
Raw View
"Bob Bell" <belvis@pacbell.net> wrote in message
news:c87c1cfb.0310071155.2be548c5@posting.google.com...
> thp@cs.ucr.edu wrote in message news:<blr63a$f5f$1@glue.ucr.edu>...

> You wrote
>
> >   int   x = 3;
> >   int&  r = x;
> >
> > Here x refers to the integer three, and r refers to the integer
> > variable x.
>
> At best, it's misleading to use the same term ("refers") to describe
> what happens on these two lines of code. What happens is _not_ the
> same; thinking it is the same will lead to problems and
> inconsistencies.

I would describe the above as:

> >   int   x = 3;

The compiler creates an object (region of storage) type 'int' somewhere, and
associate the name (identfier) 'x' with that region for further reference.
It also initializes that storage with a representation for that type of
value 3.

> >   int&  r = x;

The compiler associates another name 'r' with the same region allocated in
the prior step.

So after those two lines we end up with a single int, and 2 labels to access
it, both labels are equivalent from the practical point of use.

r is not a "pointer to variable x that is handily dereferened" but simply
equivalent with x.

Certainly in some situations the compiler must communicate it to a point far
away -- and having no magic way it will likely pass the address of x, that
is really similar to the use of a const pointer.   But that is merely an
implementation detail and should better not mislead the nature of C++
references.

> > Some people find that coding with implicitly dereferenced handles
> > leads to more readable code.  But readability is in the eye of the
> > reader.

And I agree with that in an environment where all you have is those handles.
Attach dereferencing to everything is ugly and redundant.  Ugly, because
redundant.

But as soon redundancy is lifted  --  say by introducing other stuff an
important piece of information is getting lost.

Suppose we had a type that does increment its object's value automatically
anytime you mention it.  So you need no longetr put that ++.  Will using
such objects really make code readable?    IMHO all it does is introducing
confusion.    As using an imperative language we're used to state a name and
an operation to carry out on it.  No operation stated, none shall happen.
And nothing but explicitly ordered is expected to happen.  [Implicit
conversions may seem to violate that -- IMHO not necessarily if used in a
sane way, but the main argument against them is on the same line.]

So, readability due to such automatism may really be good in special cases,
where you use nothing but types like that; short learning programs, and a
selected target audience.

IMHO we had a ton of proposals that would serve much more programmers --
those doing real work, and who actually took time to learn and use this
language, and are even easy to implement, and still getting rejected.

> Of course I've seen those proposals. What I'm saying is that it's rare
> to see a post along the lines of "Python has XYZ, we should add XYZ to
> C++." We often see posts like "Java has XYZ, we should add XYZ to
> C++."

Yep. I'd glad to see some things. labeled break of the extra-light features.
reflection and some strengthened RTTI support on the heavy side.

> IMHO, it's the syntactic similarity that leads to those posts. For
> example, the posts I'm talking about often go something like this: "I
> was trying to do XYZ in C++ because that's what works in Java. Imagine
> my surprise to find out I couldn't get it to work! We should add XYZ
> to C++."

Yes, and that works the other way around too.  There are migration books
explaining common mistakes users of some language do.
It pretty much varies whether some like mistake is just annoyance or leads
to disaster.

I recall people migrating from C to C++.  Writing pretty bad C++ code.
Even though semantics are similar here  the wisdom says C++ is another
language with its distinct approach.   One shall learn that in the firts
place, syntax comes only after that.

Merging or blending languages may be good to help machines, converters, code
generators, but IMO it's a bad approach for humans.    It is tempting to
provide some shortcut, some reservatum, but in a long run I think it hurts
more than helps.  One should better unlearn anything of the particular
languages he knows, and restrict to only the abstract programming
terms/elements.  And learn the way of the new manguage, to express those
abstract thoughts in that language.  NOT translating an implementation made
in some other language to this one.

Maybe it's infeasible on short courses -- but then I'd say the whole
teaching programming is infeasible.   [Actually I observe it really is
around here in universities. But that's another long story.]

Paul


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 8 Oct 2003 01:38:43 +0000 (UTC)
Raw View
On Mon, 6 Oct 2003 10:04:55 +0000 (UTC), thp@cs.ucr.edu wrote:

> So consider int& f(){return
> *new int;}.  Obviously, f doesn't return an identifier.

Listen to the language lawyers.  The return type of f is a reference
type, but it does not return a reference.  The expression f() is an
lvalue.  Thank you.  I finally understand why *ptr is an lvalue, but
is not a reference.

John

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 8 Oct 2003 04:24:08 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
+ thp@cs.ucr.edu wrote in message news:<blr63a$f5f$1@glue.ucr.edu>...
+> Bob Bell <belvis@pacbell.net> wrote:
+> + thp@cs.ucr.edu wrote in message news:<blq09d$5ii$1@glue.ucr.edu>...
+> [...]
+> +> The common mathematical paradigm is that the number three, like all
+> +> other mathematical entities, exists and is unique and variables can
+> +> refer to it.  Consider
+> +>
+> +>   int   x = 3;
+> +>   int&  r = x;
+> +>
+> +> Here x refers to the integer three, and r refers to the integer
+> +> variable x.
+> +
+> + No, x _contains_ the _value_ 3.
+>
+> That's a figure of speech that comes from implementation
+> considerations.  But, if x never varies there may be no register or
+> memory location to "contain" the value of x.  Similarly, it may be
+> that r is represented via a memory location that contains a bit
+> pattern representing x.
+
+ You wrote
+
+>   int   x = 3;
+>   int&  r = x;
+>
+> Here x refers to the integer three, and r refers to the integer
+> variable x.
+
+ At best, it's misleading to use the same term ("refers") to describe
+ what happens on these two lines of code. What happens is _not_ the
+ same; thinking it is the same will lead to problems and
+ inconsistencies.

So choose some other verb than "refer".

In terms of implementation some cell representing x contains a bit
pattern that represents 3, while another cell representing r contains
a bit pattern that represents x.  (And, yes, I'm perfectly aware that
in certain cases the cell representing r can be optimized away.  But
the same is true of the cell for x.)

+> + It's an important distinction, because
+> + the way you state it, the relationship between x and 3 should be the
+> + same as the relationship between r and x.
+>
+> For software-engineering reasons, some languages restrict what can be
+> done with variables that refer to other variables, and languages vary
+> in how the assignment operator interacts with such variables.
+
+ I must be missing something. I can't relate this to the discussion at
+ hand.

So let's focus on the differences: when x occurs on the left side of
the assignment operator it stops referring to 3 and suddenly
represents itself.  In that respect it is similar to a Java reference.
The same is not true of r, which refers to x in all contexts.

+> + This clearly isn't the case,
+> + because the relationship between x and r lets me do things like this:
+> +
+> + int x = 3;
+> + int& r = x;
+> +
+> + x = 10;
+> +
+> + int y = r;
+> +
+> + y now has 10 in it. There's no analogous behavior with x and 3,
+> + because there's no "3" object that I can access/modify to change what
+> + x contains.
+>
+> Of course not, unlike r and x, the integer three doesn't refer to
+> something else.  The expression "3" isn't an lvalue and cannot appear
+> on the left of an assignment.
+
+ So do you agree there is no "3" object?

Yes.  The common paradigm for an object is that it is a segment of
memory that contains a bit pattern representing something else.  In
that way, r refers to x, and x refers to 3.  But 3 doesn't refer to
something else.  It doesn't have an address but it does have an
identity.

There are (or have been) languages where one could increment 3 or any
other integer.  I had an especially bizarre Fortran bug, where 3 (or
some similarly small integer) had gotten passed to an increment()
function, so that stuff I wrote on logical unit 3 appeared on logical
unit 4.  E.g., stuff that I wrote to the terminal came out on the line
printer.

+> [...]
+> + Beyond making C++ easier for non-C++ programmers, what benefit is
+> + there?
+>
+> Some people find that coding with implicitly dereferenced handles
+> leads to more readable code.  But readability is in the eye of the
+> reader.
+
+ That's what I mean by "making C++ easier for non-C++ programmers". How
+ many of these people are C++ programmers, as opposed to (for example)
+ Java programmers who want to learn C++?

The people I have in mind are multilingual, fluent in Java, C++,
Python and other languages.

+> [...]
+> +> It's not simply a matter of syntactic similarity.  Python programmers
+> +> come from a language that has quite different syntax from C++, but
+> +> they're equally perplexed at the lack of handles that are reseatable
+> +> and implicitly dereferenced.
+> [...]
+> + It seems we regularly see proposals to add Java semantics to C++; I
+> + can't remember the last time I saw a proposal to add Python semantics.
+>
+> Surely you've seen proposals to add GC, which Python has.  And now
+> you're seeing a proposal to add a library type that implements
+> reference semantics, which (IIUC) Python has.  IMHO, there's nothing
+> Java specific about this proposal except the prevalence of Java
+> trained students entering courses that use C++.
+
+ Of course I've seen those proposals. What I'm saying is that it's rare
+ to see a post along the lines of "Python has XYZ, we should add XYZ to
+ C++." We often see posts like "Java has XYZ, we should add XYZ to
+ C++."
+
+ IMHO, it's the syntactic similarity that leads to those posts. For
+ example, the posts I'm talking about often go something like this: "I
+ was trying to do XYZ in C++ because that's what works in Java. Imagine
+ my surprise to find out I couldn't get it to work! We should add XYZ
+ to C++."

Depending on what they ask for, their requests may be reasonable:
  - standard libraries for threading and graphics, etc.
  - GC
  - reseatable references
  - portable object code
  - the ability to link modules compiled under different compilers
    for the same architecture.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Wed, 8 Oct 2003 07:19:55 +0000 (UTC)
Raw View
On Wed, 08 Oct 2003 00:43:02 +0000, Balog Pal wrote:

> So after those two lines we end up with a single int, and 2 labels to access
> it, both labels are equivalent from the practical point of use.
>
> r is not a "pointer to variable x that is handily dereferened" but simply
> equivalent with x.

This is a popular myth. Well, in this case they are equivalent because the
initialization expression of the reference is so simple that it's easy to
infer at compile time the pointed to variable, but it's a wrong way to
think about references because it doesn't work in the general case. OTOH
the automatically dereferenced pointer view works always.

Using your view some people think that with
   int &r = a[i];
accessing r will evaluate a[i] each time. You can't say that r is another
name for a[i]; you must say that it's another name for the object which
a[i] referred to at that point of time, in other words - it's an
automatically dereferenced pointer to that object.

> Certainly in some situations the compiler must communicate it to a point far
> away -- and having no magic way it will likely pass the address of x, that
> is really similar to the use of a const pointer.

I would say differently. Certainly in some situations the compiler doesn't
have to communicate the address which is known statically, and as an
optimization in these cases it can omit the physical creation of the
reference. But this is an implementation detail, in general it requires
as much information as a const pointer whose address is never taken.
Under these circumstances it can optimize away the storage of regular
pointers as well - the program can't notice.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 29 Sep 2003 05:10:10 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bkqv18$4r$1@glue.ucr.edu...
+> Bob Bell <belvis@pacbell.net> wrote:
+
+> Under reference semantics, "a = b" causes a to refer to the same
+> object as b (just as with pointers), and "a == b" is true if and only
+> if a and b refer to the same object (just as with pointers).
+
+ And this is what you want to bring in C++?

Yes.

+ If yes, in short I'd suggest: forget it. :)  [no pun intended]

Why?

+ As I view tha Java way of handling stuff is just bad.

Why?

+ It masks away the difference between IsEqual and IsSame.

In C++, two pointers or refernces are equal if and only if they have
the same referents.  I'm not suggesting anything radically new in this
regard.

+ Seing what is fundamental on both design and implementation level.

Huh?

+ And throws orthogonality out of the window.

Huh?  As I said above, the type I'm suggesting is not new in this
regard.

+ If comeone does nothing but Java he probably can live with that mess, just
+ learning that some stuff behaves this way, other behaves that way, you must
+ know if something is builtin type or a class type.

Once again: C++ pointers and C++ references behave in way to which you
are objecting.

+ But in design of C++ orthogonality was a key element. Bjarne kept strong
+ constraints to kepp it, and the communit can build on its existance.    So
+ breaking it would confuse extremely many programmers, especially the better
+ ones.

What's so all that orthogonal about the need to dereference?  If the
ability to achieve indirection without the need to dereference breaks
orthogonality, then C++'s reference have already destroyed that
othogonality.

+ So if we had auto_ref that would work similar to auto_ptr, working as
+ replacement of an object, then = and == would still work on the value.  And
+ you'd have .reseat() to change the referent.
+
+ At least I can't imagine any other design could gain wide acceptance.

You may be right, but it's a pity.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Mon, 29 Sep 2003 05:14:43 +0000 (UTC)
Raw View
thp@cs.ucr.edu writes:

|>  > If you want to reseat, you use a pointer.  If you want to prevent
|>  > reseating, you use a reference.

|>  But if you want reseatability without the baggage of explicit
|>  dereferencing, there is currently no option.

But I don't really see where "explicit dereferencing" is baggage.  Why
is it more bothersome to write -> than to write . ?

--=20
James Kanze                             mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                 Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  +33 1 41 89 80 93

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Mon, 29 Sep 2003 15:42:26 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bl36a8$8au$2@glue.ucr.edu...

> + It masks away the difference between IsEqual and IsSame.

That is the root of all the problems, and also of the misunderstanding
between us.

> In C++, two pointers or refernces are equal if and only if they have
> the same referents.  I'm not suggesting anything radically new in this
> regard.

On the conceptual level, we say two objects are "same" if their identity
equals. We say they are "equal" if their meaning (value, or anything the
object thinks as representative of its state) equals.    Those are very
distinct concepts, and a programmer shall be aware of them.    [being same
implies being equal, but not the other way around.]

In C++ IsSame() compares the address of the two objects. IsEqual() use == to
compare the value.    assignment (=)  makes the left object Equal to the
right without messing with their Same-ness.

consider this:

void Foo(Whatever a, Whatever b)
{
    a = b;

    b += 1;     b.Increment(); // do anything that changes the state of b
here

    // ** what here
}

In C++ at ** we will have the original value of b in a, and the changed one
in b. No matter what type we use.  That I call being orthogonal.

In java, = will set value, if we happen to use a builtin type, and identity
if we have a class type.  at the end, a will have the same value as b if
Whatever is class, and have the old value is it was builtin.   Those types,
and  =  do not work in an orthogonal way.

The only reason you do not get in really big mess right away in java is the
mass of restrictions on interface of builtin and class types.   And that
most class types are designed to be immutable.

But as sson as you step out of those restrictions (say, migrating to C++,
where they never existed),  you'll soon shoot yourself in the foot.    I
mean your students, who are not aware that in java they learned identity and
state is the same anyway  [if state is finalised on creation it really is]
and even find it silly to think otherwise.

Certainly those same students will be hit by the problem sometime, as
nothing in java actually prevents changing the state of an object, and being
unaware of the problem it brings they will implement such classes for sure.
But that will happen way after the classes or lectures, so why would the
institution care?  O,O


My suggestion for you is not to create an "easy pass" for the students that
hides problems from sight for even longer, but to teach them the concept.
If they find it silly well, you must deal with that some way.   As it is not
silly but fundamental.

As it is fundamental to grasp the concept of 'pointer'.  At least for anyone
who will start to use one.    I -- just as Walter -- always found it's a
natural thing (coming from assembly direction as well ;)  but later learned
people have serious problems with that (mostly pascalers moving to C at the
time).   fortunately there are excellent documents, faqs, etc.

Then one who is aware something is a pointer to something, he will naturally
think with its properties, and explicit need to ask dereferencing, when
that's in need.

And confusing the pointer with the pointee is a mistake.

> Huh?  As I said above, the type I'm suggesting is not new in this
> regard.

You said:

> In C++, two pointers or refernces are equal if and only if they have
> the same referents.


That is not true. (Maybe I should say it's not reasonable to state).

Ponters are _equal_ if they have the same value, okey. What means their
pointee is _same_.

For a reference there's no such thing is defined in C++ as being equal, as
references are not objects. They're mere aliases to objects.  You can't
compare references. You can't really do anything with a reference besides
creating.  In all operations you'll deal with the referred object.  if you
try to == two refs you'll see result of comparisions of the objects. That
will be true for any pair of _equal_ objects, despite their _same_-ness.

A a, b;
A& ra = a;
A& rb = b;

ra == rb; // same as a == b
ra = rb; // same as a = b !!!  not reseating

> I'm not suggesting anything radically new in this  regard.

Even if it's not "radically" new, the suggestion would bring in a mixed
type, a chimaira. It will not be intuitive to anyone using C++, IOW it would
counfuse the hell out of anyone  reading the code.    Pretty soon that would
include your students as well.

> + If comeone does nothing but Java he probably can live with that mess,
just
> + learning that some stuff behaves this way, other behaves that way, you
must
> + know if something is builtin type or a class type.
>
> Once again: C++ pointers and C++ references behave in way to which you
> are objecting.

Nope.  If you still feel they are, please elaborate what you mean here to
clear the rest of misunderstanding.

> What's so all that orthogonal about the need to dereference?  If the
> ability to achieve indirection without the need to dereference breaks
> orthogonality, then C++'s reference have already destroyed that
> othogonality.

It would if references would behave the way pointers do, but they don't.  In
C++ the reference behaves exactly as the original object, as a true alias
starting right after the creation.  the reference has absolutely no behavior
of its own, you can't even make a distinction whether you deal with a ref or
a genuine object.    [well, the compiler sometimes know a difference, as for
the genuine object the static type can't be different from the dynamic type,
but that's irrelevant to this discussion]


And back to your main problem with teaching C++: you should just not rush to
introduce pointers.  One can sit down and write programs (on the application
level) in C++ for months without hitting the need of a single pointer.
Teach all the other stuff, then when the time is here drop in the concept of
pointers, and all the related stuff.

Paul


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 29 Sep 2003 17:04:30 +0000 (UTC)
Raw View
Bob Bell <belvis@pacbell.net> wrote:
[...]
+> Under reference semantics, "a = b" causes a to refer to the same
+> object as b (just as with pointers), and "a == b" is true if and only
+> if a and b refer to the same object (just as with pointers).  The
+> transition from reference semantics to value semantics is goes beyond
+> replacing "." with "->"; "a" must be replace by "*a" in ALL contexts
+> other than assignment and equality/nonequality comparisions.
+
+ Sorry, I wasn't explicit enough. If you use a smart pointer type<T>
+ that provides an implicit conversion to T&, then
+
+ "a = b" causes a to refer to the same object as b
+ "a == b" is true if and only if a and b refer to the same object
+ "a" can be used to refer to the object; you don't have to use "*a"
+
+ So I repeat: you get what you want, except that you must use "->" to
+ refer to object members instead of "."
+
+ What am I missing? As it stands, I don't really see much of a problem
+ here.

Consider:

#include <iostream>
#include <string>

template<class T> class ref {
  T* p;
public:
  ref<T>(T x) : p(&x) {}
  operator T&() { return *p; }
};

int main() {
  ref<std::string> a = std::string("Hello");
  std::cout << a << std::endl;
}

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: david.thompson1@worldnet.att.net (Dave Thompson)
Date: Mon, 29 Sep 2003 17:07:53 +0000 (UTC)
Raw View
On Wed, 24 Sep 2003 15:27:47 +0000 (UTC), kanze@gabi-soft.fr wrote:

> thp@cs.ucr.edu wrote in message news:<bkom4q$aqo$1@glue.ucr.edu>...
>
> > For those who prefer explicit dereferencing, C++ offers a plethora of
> > explicitly dereferenced pointer types.  But programmers in lots of
> > languages (Java, C#, Python, and others) get along very well without
> > explicit dereferencing, and some legitimately prefer implicit
> > dereferencing.
>
> In this case, I think that the comparison between the languages is not
> valid.  As far as I know, none of the languages with implicit
> dereferencing have value types, and pointers are not first class objects
> in any of them.  That makes a difference.  Implicit dereferencing in C++
> would just be one more point of confusion (especially since we would
> also still have explicit dereferencing).
>
Many languages have by-reference arguments/formals/parameters to
routines, which are always implicitly dereferenced, but cannot be
reseated nor in general manipulated as references at all, (often only)
in addition to value types. If I assume the discussion to be only
about things whose referenceness is at least sometimes visible but are
also sometimes implicitly dereferenced, thus allowing/requiring the
programmer to consider both concepts with regard to one identifier:

- algol 68 had "magic" dereferencing -- just enough to make a
statement (like an assignment) legal.  This proved rather confusing.

- Ada has (explicit and rather rich) "access" types; access-to-record
is implicitly dereferenced when you select a "component" (field,
member) of its target; access-to-array is implicitly derefenced when
you subscript it, and access-to-subprogram when you call it with
arguments; and various access types are when you use attributes that
don't apply for access types.  For these cases you also may, and for
other cases like scalars and parameterless calls must, explicitly
derefence with the rather silly notation of a trailing ".all".

- (modern i.e. >=90 standard) Fortran has POINTERs which are really
more a storage class than a type, and (like F90 assumed-shape
dummy/formal arguments) can point to noncontiguous array slices.  Any
use of a POINTER variable is actually to its target unless you use a
special syntax to reseat it (=> rather than = for assignment) except:
if a record/struct type, somewhat confusingly called a "derived type"
in Fortran, contains a POINTER member, assigning the *record* assigns
(reseats) the pointer; if you call a subprogram that declares its
formal/dummy as a POINTER the pointer itself is passed (sort-of) by
reference, and can be reseated in the called routine, but otherwise
the target is passed (sort-of) by reference.

PL/I also has CONTROLLED variables which are always derefenced except
for special statements and intrinsics, so I don't count them as
ambiguous.  And for that matter BASED, which have separate names for
the pointer itself and the dereferenced target.

<rest snipped>

- David.Thompson1 at worldnet.att.net

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Mon, 29 Sep 2003 17:08:08 +0000 (UTC)
Raw View
thp@cs.ucr.edu writes:

|>  kanze@gabi-soft.fr wrote:
|>  > thp@cs.ucr.edu wrote in message news:<bkqv18$4r$1@glue.ucr.edu>...

|>  >> Bob Bell <belvis@pacbell.net> wrote:
|>  >> [...]
|>  >> > I'm a little confused. It sounds like you want to type "."
|>  >> > instead of "->".

|>  >> > As far as I can see it would be pretty easy to give you what
|>  >> > you want if you're willing to settle for "->" instead of ".".

|>  >> > But you seem to be claiming that "->" vs. "." is a significant
|>  >> > bottleneck in understanding and learning for people coming from
|>  >> > Java/C#/Python. That sounds very hard to believe. It's syntax,
|>  >> > and can't possibly be more of a problem than e.g., the template
|>  >> > syntax that would be required to use such a hypothetical smart
|>  >> > pointer.

|>  >> Under reference semantics, "a =3D b" causes a to refer to the same
|>  >> object as b (just as with pointers), and "a =3D=3D b" is true if a=
nd
|>  >> only if a and b refer to the same object (just as with pointers).
|>  >> The transition from reference semantics to value semantics is
|>  >> goes beyond replacing "." with "->"; "a" must be replace by "*a"
|>  >> in ALL contexts other than assignment and equality/nonequality
|>  >> comparisions.

|>  > Such as? =20

|>  cout << a;   // where a has type ref<string>

OK.  Point taken.  The Java-like solution would be something like
"a->print( cout )", however.  I suspect teaching them to add a * is a
lot less difficult than teaching them to use the iostream mechanism,
however:-).

|>  > The only interest I can see in this proposal is to facilitate C++
|>  > for Java programmers.

|>  Also for programmers who'd like to minimize the distraction of
|>  explicit dereferencing.

The only thing is, if you are programming in a Java-like style, there
won't be much, if any, explicit dereferencing except for the use of ->.

|>  > Off hand, I can only think of four operators in Java that are
|>  > valid for a reference type: =3D, =3D=3D, !=3D and .. In C++, these =
map
|>  > directly to =3D, =3D=3D, !=3D and ->.

|>  > If you need a *, you are doing something that you couldn't do in
|>  > Java anyway, so referring to Java is no good.

|>  One would like to use stream I/O.

As I said above, that's going to be a lot more difficult to teach than
is necessity of adding a *.

--=20
James Kanze                             mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                 Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  >33 1 41 89 80 93

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 2 Oct 2003 22:13:46 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
+ <thp@cs.ucr.edu> wrote in message news:bl36a8$8au$2@glue.ucr.edu...
+
+> + It masks away the difference between IsEqual and IsSame.
+
+ That is the root of all the problems, and also of the misunderstanding
+ between us.
+
+> In C++, two pointers or refernces are equal if and only if they have
+> the same referents.  I'm not suggesting anything radically new in this
+> regard.
+
+ On the conceptual level, we say two objects are "same" if their identity
+ equals. We say they are "equal" if their meaning (value, or anything the
+ object thinks as representative of its state) equals.    Those are very
+ distinct concepts, and a programmer shall be aware of them.    [being same
+ implies being equal, but not the other way around.]
+
+ In C++ IsSame() compares the address of the two objects. IsEqual() use == to
+ compare the value.    assignment (=)  makes the left object Equal to the
+ right without messing with their Same-ness.
+
+ consider this:
+
+ void Foo(Whatever a, Whatever b)
+ {
+    a = b;
+
+    b += 1;     b.Increment(); // do anything that changes the state of b
+ here
+
+    // ** what here
+ }
+
+ In C++ at ** we will have the original value of b in a, and the changed one
+ in b. No matter what type we use.  That I call being orthogonal.
+
+ In java, = will set value, if we happen to use a builtin type, and identity
+ if we have a class type.  at the end, a will have the same value as b if
+ Whatever is class, and have the old value is it was builtin.   Those types,
+ and  =  do not work in an orthogonal way.
+
+ The only reason you do not get in really big mess right away in java is the
+ mass of restrictions on interface of builtin and class types.   And that
+ most class types are designed to be immutable.

I would assume that Java programmers preserve orthogonality by viewing
expressible values as having identity, e.g., that "i=3" assigns the
identity of the constant 3 to the variable i.  Where's the danger in
that perspective?

+ But as sson as you step out of those restrictions (say, migrating to C++,
+ where they never existed),  you'll soon shoot yourself in the foot.    I
+ mean your students, who are not aware that in java they learned identity and
+ state is the same anyway  [if state is finalised on creation it really is]
+ and even find it silly to think otherwise.

To me, the notion that each value has its own identity seems natural
enough.

+ Certainly those same students will be hit by the problem sometime, as
+ nothing in java actually prevents changing the state of an object,

Why should something in Java "prevent changing the state of an
object"?

+ and being unaware of the problem it brings

Huh?  What problem?

+ they will implement such classes for sure.

Of course they will.

[...]
+ You said:
+
+> In C++, two pointers or refernces are equal if and only if they have
+> the same referents.
+
+ That is not true. (Maybe I should say it's not reasonable to state).

Oops.  Agreed.  I misspoke in including "references" above.

[...]
+> I'm not suggesting anything radically new in this  regard.
+
+ Even if it's not "radically" new, the suggestion would bring in a mixed
+ type, a chimaira. It will not be intuitive to anyone using C++, IOW it would
+ counfuse the hell out of anyone  reading the code.    Pretty soon that would
+ include your students as well.

The semantics of the type scheme I proposed is very simple and easily
stated.  It is accepted without major confusion in several recent
programming langauges including C#, which I'm told also has explicitly
dereferenced handles (a.k.a. "pointers").

+> + If comeone does nothing but Java he probably can live with that mess, just
+> + learning that some stuff behaves this way, other behaves that way, you must
+> + know if something is builtin type or a class type.
+>
+> Once again: C++ pointers and C++ references behave in way to which you
+> are objecting.
+
+ Nope.  If you still feel they are, please elaborate what you mean here to
+ clear the rest of misunderstanding.

Pointers are explicitly dereferenced and references are implicitly
dereferenced.  Having both in C++ doesn't cause unmanageable
confusion.

+> What's so all that orthogonal about the need to dereference?  If the
+> ability to achieve indirection without the need to dereference breaks
+> orthogonality, then C++'s reference have already destroyed that
+> othogonality.
+
+ It would if references would behave the way pointers do, but they don't.  In
+ C++ the reference behaves exactly as the original object, as a true alias
                                                               ^^^^^^^^^^^^
A what?

+ starting right after the creation.

So you agree that references have state?

+ the reference has absolutely no behavior of its own,

It gets initialized, and it gets dereferenced.

+ you can't even make a distinction whether you deal with a ref or
+ a genuine object.

When the references is being initalized the "genuine object does not
change state".

+ And back to your main problem with teaching C++: you should just not rush to
+ introduce pointers.

How do you propose representing say an abstract syntax tree without
pointers?  Of course, it can be done the same way a Fortran programmer
would do it: by using array indices instead of addresses.  But that
introdces yet another level of tedium.

+ One can sit down and write programs (on the application
+ level) in C++ for months without hitting the need of a single pointer.

And Fortran programmers avoid pointers entirely.

+ Teach all the other stuff, then when the time is here drop in the concept of
+ pointers, and all the related stuff.

The point is that I'm not teaching C++.  I'm teaching ten-week courses
where most students know C++, and the students who don't already know
C++ have to do the homework anyway and learn C++ as they go.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: eloso@gmx.de (=?ISO-8859-1?Q?Bj=F6rn_Sachsenberg?=)
Date: Mon, 15 Sep 2003 17:10:31 +0000 (UTC)
Raw View
thp@cs.ucr.edu wrote in message news:<bjpsj0$o0j$1@glue.ucr.edu>...
> For several reasons, it would be convenient to have a fancy pointer
> type that behaves like Java's references, e.g.:
>

There already exist various implementations on these. They are called
"smart pointers". Google for it and you'll find tons of information,
articles and implementations. For example the c++ boost library
(www.boost.org) supports them.

eloso

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 20 Sep 2003 16:48:34 +0000 (UTC)
Raw View
Bj=F6rn Sachsenberg <eloso@gmx.de> wrote:
+ thp@cs.ucr.edu wrote in message news:<bjpsj0$o0j$1@glue.ucr.edu>...
+> For several reasons, it would be convenient to have a fancy pointer
+> type that behaves like Java's references, e.g.:
+>
+=20
+ There already exist various implementations on these. They are called
+ "smart pointers". Google for it and you'll find tons of information,
+ articles and implementations. For example the c++ boost library
+ (www.boost.org) supports them.

Thanks.  Unfortunately, the smart pointers I've found so far
automatically delete but don't automatically dereference -- e.g., per
the Boost web page:

   Smart pointers are objects which store pointers to dynamically
   allocated (heap) objects. They behave much like built-in C++
   pointers except that they automatically delete the object pointed
   to at the appropriate time.

What I want is implicit ref<T>-to-T& conversion, i.e. "automatic
dereferencing", of objects of type ref<T>, except when they occur as
operands of =3D, =3D=3D, and !=3D.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: bouncer@dev.null (Wil Evers)
Date: Tue, 23 Sep 2003 04:48:04 +0000 (UTC)
Raw View
In article <bk75n8$dbb$1@glue.ucr.edu>, thp@cs.ucr.edu wrote:

> What I want is implicit ref<T>-to-T& conversion, i.e. "automatic
> dereferencing", of objects of type ref<T>, except when they occur as
> operands of =, ==, and !=.

I don't think such a thing can be implemented in today's standard C++.

You can have an 'operator T&()' in your ref<T> class template; the problem
is it won't be considered when the dot notation is used on an object of the
ref<T> type to access the members of the object it refers to - which is
what the Java crowd would expect.

For that to work, we need the capability to overload the dot operator.
Stroustrup's D&E discusses some of the issues involved.  Briefly, we would
need some mechanism to distinguish access to members of the ref<T> object
itself from access to members of the object it refers to.

I know a Java programmer who accidentally ended up in a C++ project, and
routinely wrote...

  T& t = *p;  // (p is a real or smart pointer to T)

...so he could use the '.' instead of the '->'.  Personally, I think this is
a bad idea; it blurs the distinction between a pointer to an object and the
object itself, which is often essential to understand what's going on in a
C++ program.

- Wil

--
Wil Evers, DOOSYS R&D, Utrecht, Holland
[Wil underscore Evers at doosys dot com]

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Tue, 23 Sep 2003 04:48:23 +0000 (UTC)
Raw View
<thp@cs.ucr.edu> wrote in message news:bk75n8$dbb$1@glue.ucr.edu...
Bj   rn Sachsenberg <eloso@gmx.de> wrote:

>Thanks.  Unfortunately, the smart pointers I've found so far
>automatically delete but don't automatically dereference -- e.g., per
>the Boost web page:

That's a deliberate choice. Add an operator TYPE & returning *this to have
most of that behavior.   In generic libraries designers tend to avoid
implicit conversions -- in the past it was a frequent debate whether its
handy or evil.

But C++ programmers look at those opjects as smart _pointers_ not as
substitute to objects, so auto-edreferencing is not a wanted behavior, and
would be liklely confusing. Why would you want to avoid that * after all.

(OTOH implicit conversion to the raw pointer type is reasonable.)

Paul



---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 23 Sep 2003 16:24:23 +0000 (UTC)
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
[...]
+ In generic libraries designers tend to avoid implicit conversions -- in
+ the past it was a frequent debate whether its handy or evil.

Agreed.

+ But C++ programmers look at those opjects as smart _pointers_ not as
+ substitute to objects,

Agreed.

+ so auto-edreferencing is not a wanted behavior,

I and others want it.

+ and would be liklely confusing.  Why would you want to avoid that *
+ after all.

Auto-dereferencing appears not to confuse Java, C#, and Python
programmers.  I'm told that C# supports both implicit and explicit
dereferencing.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 23 Sep 2003 18:54:18 +0000 (UTC)
Raw View
Wil Evers <bouncer@dev.null> wrote:
+ In article <bk75n8$dbb$1@glue.ucr.edu>, thp@cs.ucr.edu wrote:
+
+> What I want is implicit ref<T>-to-T& conversion, i.e. "automatic
+> dereferencing", of objects of type ref<T>, except when they occur as
+> operands of =, ==, and !=.

+ I don't think such a thing can be implemented in today's standard C++.

Agreed.

+ You can have an 'operator T&()' in your ref<T> class template; the problem
+ is it won't be considered when the dot notation is used on an object of the
+ ref<T> type to access the members of the object it refers to - which is
+ what the Java crowd would expect.

Right.

+ For that to work, we need the capability to overload the dot operator.
+ Stroustrup's D&E discusses some of the issues involved.  Briefly, we would
+ need some mechanism to distinguish access to members of the ref<T> object
+ itself from access to members of the object it refers to.

Even if we had that, the device still wouldn't work in lots of other
situations, e.g.:

  ref<string> x = "Hello";
  cout << x;

+ I know a Java programmer who accidentally ended up in a C++ project, and
+ routinely wrote...
+
+  T& t = *p;  // (p is a real or smart pointer to T)
+
+ ...so he could use the '.' instead of the '->'.  Personally, I think this is
+ a bad idea; it blurs the distinction between a pointer to an object and the
+ object itself, which is often essential to understand what's going on in a
+ C++ program.

For those who prefer explicit dereferencing, C++ offers a plethora of
explicitly dereferenced pointer types.  But programmers in lots of
languages (Java, C#, Python, and others) get along very well without
explicit dereferencing, and some legitimately prefer implicit
dereferencing.  In fact, that is also true of many C++ programmers,
i.e., many C++ programmers use C++ references over pointers whenever
possible.  Unfortunately, C++ references are an incomplete solution
for those who prefer implicit dereferencing becase, by design, they
cannot be reseated --- these other languages suspend implicit
dereferencing in assignments and equality/nonequality comparisons.

The obvious question is: "Why bother?"  In fact, the more pointed
questions is: "Why open the door to yet another programming paradigm
in C++, namely the Java paradigm, which is based largely on automatic
garbage collection and automatic dereferencing, a.k.a., "reference
semantics".  (C++ already has automatic garbage collection available
as a non-standard library option.  Unfortunately, ref<T> cannot be
implemented except via some compiler supported extensions.)

It's widely claimed that the Java paradigm is more easily learned by
beginners and supports far more rapid development of certain classes
of programs.  Whether that is true or not, I'm faced with colleagues
who believe it and a generation of students who learned this paradigm
in high schools, local community colleges, and undergraduate curricula
around the world.  I need to rapidly assimilate them into C++-based
courses and research projects, and that process would be much easier
if they didn't need to make such a serious shift in programming
paradigms.

Tom Payne

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dheld@codelogicconsulting.com ("David B. Held")
Date: Tue, 23 Sep 2003 18:55:20 +0000 (UTC)
Raw View
""Balog Pal"" <pasa@lib.hu> wrote in message
news:3f6f9a9a@andromeda.datanet.hu...
> [...]
> (OTOH implicit conversion to the raw pointer type is reasonable.)

???  And give away ownership without so much as a wink and a nod?

Dave


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 12 Sep 2003 09:11:04 +0000 (UTC)
Raw View
For several reasons, it would be convenient to have a fancy pointer
type that behaves like Java's references, e.g.:

   - It would make the transition to C++ easier for Java programmers
     especially if it were used in combination with garbage
     collection.

   - It would allow syntactically correct C++ code that is more
     readable by novices, i.e., closer to pseudo-code.

   - It would eliminate some of the tedium of dereferencing.

I once tried to do this as a template class ref<T> having a pointer as
its only data member and a conversion operator that returned a
reference to the thing pointed to.  Obviously =, ==, and != had to be
overloaded to conform to Java semantics.  But, for various reasons,
that didn't work.  (That was a few years ago and I don't recall the
details.)

That leaves the questions:

   - Can this be made to work under the current standard?

   - If not, would such a capability be a good idea for the new
     standard?

Tom Payne


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]