Board index » cppbuilder » Re: Why does this work?

Re: Why does this work?


2005-11-02 11:38:12 PM
cppbuilder64
Alan Bellingham wrote:
Quote
:
Which leaves these:

value
object
variable

Well, it's not a value. So, that leaves the object/variable distinction:
That was a real quick decision! I have all the time said it is a value, a rvalue, a number that happens to be the address (of the first element in the array). It fits just fine with your reasoning above. And you brush it aside though it is one of the tree remaining possibilities.
Knut
 
 

Re:Re: Why does this work?

Chris Uzdavinis (TeamB) wrote:
Quote
Hmmm. An array "will decay", but pointer-to-array "won't decay", so I
don't understand why you say this. They seem unambiguously different
to me. What am I missing? :)
Could you try the following program on the conforming compiler of your
choice, and tell me what the results are? I may be wrong here, but
hope not!
#include <iostream>
#include <typeinfo>
void print(std::type_info const & ti)
{
std::cout << ti.name() << std::endl;
}
template< typename T>
void test( T & arg )
{
print(typeid(arg));
}
int main()
{
const char * s1 = "Hello";
const char s2[] = "World";
print(typeid(s1));
print(typeid(s2));
print(typeid(&s2));
test(s1);
test(s2);
test(&s2);
return 0;
}
I will try to look up the small print later this evening.
[Even if your compiler disagrees with me, I'm right darn it!]
--
AlisdairM(TeamB)
 

Re:Re: Why does this work?

Knut Olsen-Solberg < XXXX@XXXXX.COM >writes:
Quote
That was a real quick decision! I have all the time said it is a
value, a rvalue, a number that happens to be the address (of the
first element in the array). It fits just fine with your reasoning
above. And you brush it aside though it is one of the tree remaining
possibilities. Knut
Yes, you've been saying that, and everyone has been trying to show you
why that is not so.
An array *is* a variable. You *can* take its address. You *can*
create a non-const reference to it. It is *not* just a value, it is
*not* just an rvalue, and it's *not* just an address.
This is the last time I'm going to try to explain this. For certain
expressions, an array CAN BE CONVERTED INTO A POINTER (whose type is
pointer-to-T, where T is the element type of the array), but that
doesn't mean the array is actually just an address. (To conclude that
because X can be converted into Y means that X *is* Y is folly.
Similarlly, a char can be converted into an int, but that doesn't mean
that a char IS an int.) In many circumstances, the array decays to a
pointer, sometimes so easily that you might not realize that there is
ever a difference, but there is. Before the implicit converstion,
the types are entirely different.
--
Chris (TeamB);
 

{smallsort}

Re:Re: Why does this work?

Chris Uzdavinis (TeamB) wrote:
Quote
"Alisdair Meredith [TeamB]"
< XXXX@XXXXX.COM >writes:

>#include <iostream>
>#include <typeinfo>
>
>void print(std::type_info const & ti)
>{
>std::cout << ti.name() << std::endl;
>}
>
>template< typename T>
>void test( T & arg )
>{
>print(typeid(arg));
>}
>
>int main()
>{
>const char * s1 = "Hello";
>const char s2[] = "World";
>
>print(typeid(s1));
>print(typeid(s2));
>print(typeid(&s2));
>
>test(s1);
>test(s2);
>test(&s2);
>
>return 0;
>}
>

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"ComeauTest.c", line 26: error: no instance of function template
"test" matches the argument list
The argument types that you used are: (const char (*)[6])
test(&s2);
^

1 error detected in the compilation of "ComeauTest.c".


;)

However, if test is changed to (T const & arg) then it compiles, of
course. Here's the output (from Comeau 4.3.0.1) of that modified
version:

const char *
char [6]
const char (*)[6]
const char *
char [6]
const char (*)[6]

This is showing that references don't cause decay. I'm still confused
where you're going with this. :)
Doh!
Could you repeat the test with
template< typename T>
void test( T arg )
{
print(typeid(arg));
}
instead?
I believe all 3 calls to test should display the same value.
--
AlisdairM(TeamB)
 

Re:Re: Why does this work?

"Alisdair Meredith [TeamB]" < XXXX@XXXXX.COM >writes:
Quote
>#include <iostream>
>#include <typeinfo>
>
>void print(std::type_info const & ti)
>{
>std::cout << ti.name() << std::endl;
>}
>
>void pointer_decay(char const arg[])
>{
>print(typeid(arg));
>}
>
>int main()
>{
>const char s2[] = "World";
>print(typeid(&s2)); // explicit address-of
>pointer_decay(s2); // pointer decay
>}
>
>Output:
>
>const char (*)[6]
>const char *


Thereby demonstrating that pointer-to-array decays in the same way that
an array does, and therefore calls the same overloads <g>
Hmmm. An array "will decay", but pointer-to-array "won't decay", so I
don't understand why you say this. They seem unambiguously different
to me. What am I missing? :)
--
Chris (TeamB);
 

Re:Re: Why does this work?

Knut Olsen-Solberg wrote:
Quote
Alan Bellingham wrote:

>:
>Which leaves these:
>
>value
>object
>variable
>
>Well, it's not a value. So, that leaves the object/variable distinction:


That was a real quick decision! I have all the time said it is a value,
a rvalue, a number that happens to be the address (of the first element
in the array). It fits just fine with your reasoning above. And you
brush it aside though it is one of the tree remaining possibilities.
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array ofN T?or “array of unknown bound
of T?can be converted to an rvalue of type “pointer to T.?The result
is a pointer to the first element of the array.
Tom
 

Re:Re: Why does this work?

On Wed, 02 Nov 2005 17:09:31 +0000, Tom Widmer wrote:
Quote
4.2 Array-to-pointer conversion [conv.array]
*sigh* he has been ignoring this.
--
liz
 

Re:Re: Why does this work?

"Alisdair Meredith [TeamB]" < XXXX@XXXXX.COM >writes:
Quote
#include <iostream>
#include <typeinfo>

void print(std::type_info const & ti)
{
std::cout << ti.name() << std::endl;
}

template< typename T>
void test( T & arg )
{
print(typeid(arg));
}

int main()
{
const char * s1 = "Hello";
const char s2[] = "World";

print(typeid(s1));
print(typeid(s2));
print(typeid(&s2));

test(s1);
test(s2);
test(&s2);

return 0;
}

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++
"ComeauTest.c", line 26: error: no instance of function template "test" matches the
argument list
The argument types that you used are: (const char (*)[6])
test(&s2);
^
1 error detected in the compilation of "ComeauTest.c".
;)
However, if test is changed to (T const & arg) then it compiles, of
course. Here's the output (from Comeau 4.3.0.1) of that modified
version:
const char *
char [6]
const char (*)[6]
const char *
char [6]
const char (*)[6]
This is showing that references don't cause decay. I'm still confused
where you're going with this. :)
--
Chris (TeamB);
 

Re:Re: Why does this work?

Tom Widmer wrote:
Quote
Knut Olsen-Solberg wrote:

>Right. And the declaration double *ipt; is another variable, a pointer.
>
>The last line (char Str[10]) defines ten variables, all of type char.
>Who says we have to regard Str as the name of a compound type variable
>(array)?
>Here is probably the kernel of the discussion. Can't we live without
>thinking of the array as a (one) variable?


Definitely not in C++ (possibly in C). All that is special about an
array is there is an implicit conversion (the array-to-pointer
conversion) that returns a pointer to the first element of the array. In
all other ways it behaves like any other normal, non-copyable variable.
e.g.

char array[10];
sizeof(array); //10, not 4 as you might be expecting?
Here is a good point. For my reasoning to be right, sizeof would have to be programmed "in the same manner" as cout: It would sometimes have to do something different from what we actually asks for. And the reason would (as for cout) be that this is what we usually need/want.
We should leave char, and use double or int in our examples, to avoid the specialities with char. They only make things unnecessarily complicated. But I really don't have much more time for discussion. (To morrow I am going away for some days.) I am very grateful for all the contributions, and will study them and this matter more later. (I have to say I have studied this a lot already, but it is not easy.)
My point of view (Str being an address), originates from a Norwegian textbook, written by two acknowledged programmers. On monday I will discuss this with them, because I know from earlier conversations that they have studied this really thorough. So Thomas will have to forgive me if "you have now been told by a number of knowledgeable people" is no real argument to me.
Knut
 

Re:Re: Why does this work?

Knut Olsen-Solberg < XXXX@XXXXX.COM >wrote:
Quote
Alan Bellingham wrote:

>:
>Which leaves these:
>
>value
>object
>variable
>
>Well, it's not a value. So, that leaves the object/variable distinction:

That was a real quick decision! I have all the time said it is a value, a rvalue, a number that happens to be the address (of the first element in the array). It fits just fine with your reasoning above. And you brush it aside though it is one of the tree remaining possibilities.
You think it's an rvalue, but not an lvalue?
My apologies, I hadn't realised that that was where you were at. The
reason I dismissed the value possibility is that I know that an array is
an object, and therefore not an rvalue (except after lvalue-to-rvalue
conversion).
So, you wish me to show that something of array type _is_ an object?
---------------------------------------------------------------------------------------
8.3.4 Arrays [dcl.array]
1 In a declaration T D where D has the form
D1 [constant-expression/opt]
and the type of the identifier in the declaration T D1 is
“derived-declarator-type-list T,?then the type of the identifier of
D is an array type. T is called the array element type; this type
shall not be a reference type, the (possibly cv-qualified) type
void, a function type or an abstract class type. If the
constant-expression (5.19) is present, it shall be an integral
constant expression and its value shall be greater than zero. The
constant expression specifies the bound of (number of elements in)
the array. If the value of the constant expression is N, the array
has N elements numbered 0 to N-1, and the type of the identifier of
D is “derived-declarator-type-list array of N T.?An object of array
^^^|^^
note please -----------------------------------'
type contains a contiguously allocated nonempty set of N sub-objects
of type T. If the constant expression is omitted, the type of the
identifier of D is “derived-declarator-type-list array of unknown
bound of T,?an incomplete object type. The type
“derived-declarator-type-list array of N T?is a different type from
the type “derived-declarator-type-list array of unknown bound of T,?
see 3.9. Any type of the form “cv-qualifier-seq array ofN T?is
adjusted to “array of N cv-qualifier-seq T,?and similarly for
“array of unknown bound of T.?[Example:
typedef int A[5], AA[2][3];
typedef const A CA; // type is ‘‘array of 5 const int’’
typedef const AA CAA; // type is ‘‘array of 2 array of 3 const
int’’
—end example] [Note: an “array of N cv-qualifier-seq T?has
cv-qualified type; such an array has internal linkage unless
explicitly declared extern (7.1.5.1) and must be initialized as
specified in 8.5. ]
---------------------------------------------------------------------------------------
Here the standard refers to an object of array type. This is, I would
propose, incompatible with your requirement that an array may only be an
rvalue.
Given then that
char Str[10];
declares an object named Str, Str is a variable. And you may take the
address of a variable.
Alan Bellingham
--
ACCU Conference 2006 - 19-22 April, Randolph Hotel, Oxford, UK
 

Re:Re: Why does this work?

Knut Olsen-Solberg < XXXX@XXXXX.COM >wrote:
Quote
My point of view (Str being an address), originates from a Norwegian
textbook, written by two acknowledged programmers. On monday I will
discuss this with them, because I know from earlier conversations that
they have studied this really thorough. So Thomas will have to forgive
me if "you have now been told by a number of knowledgeable people" is no
real argument to me.
Indeed - that argument is known as "argument-through-authority" and is
only acceptable if you accept the people in question as being good
authorities.
It's possible that your point of view is due to a subtle
misunderstanding on your part, or sloppy phraseology by the authors
(it's very very difficult to produce perfect phraseology). Or they may
be the Norwegian Herbert Schildt equivalents (I truly hope not, and your
description of them implies not): good communicators, but technically
inadequate.
Oh, of those that have told you on this side - at least one, Alisdair
Meredith, is an _active_ member of WG21, the C++ Standards Committee. So
if he disagrees with you, he can change the language till he's right and
you're wrong *grin*
Alan Bellingham
--
ACCU Conference 2006 - 19-22 April, Randolph Hotel, Oxford, UK
 

Re:Re: Why does this work?

"Alisdair Meredith [TeamB]" < XXXX@XXXXX.COM >writes:
Quote
Doh!
Could you repeat the test with

template< typename T>
void test( T arg )
{
print(typeid(arg));
}

instead?

I believe all 3 calls to test should display the same value.
Ok, here's the output, making the requested change:
const char *
char [6]
const char (*)[6]
const char *
const char *
const char (*)[6]
<g>
(I'd be extremely surprised to see pointers change types when being
passed to a template, since templates want exact matches. I see the
array decay occurring, but that's because you "can't" pass an array by
value.)
--
Chris (TeamB);
 

Re:Re: Why does this work?

Chris Uzdavinis (TeamB) wrote:
Quote
"Alisdair Meredith [TeamB]" < XXXX@XXXXX.COM >writes:


>Doh!
>Could you repeat the test with
>
>template< typename T>
>void test( T arg )
>{
>print(typeid(arg));
>}
>
>instead?
>
>I believe all 3 calls to test should display the same value.



Ok, here's the output, making the requested change:

const char *
char [6]
const char (*)[6]
const char *
const char *
The important one is the line above - an array argument is deduced as a
pointer, from 14.8.2.1/2. But pointers to arrays are just pointers to
arrays, and are no different from any other pointer.
Tom
 

Re:Re: Why does this work?

Alan Bellingham < XXXX@XXXXX.COM >wrote:
Quote
As to my expertise - well, I feel honoured. But I'd bow before Herr
Maeder, Chris Uzdavanis or Alasdair Meredith.
Well, I've certainly found all of your posts here very helpful to my
understanding, and the specific mention of you and Thomas was probably
due to the posts I had most recently read. And of course, there are
many others who have also contributed here...
Thanks to all.
- Leo
 

Re:Re: Why does this work?

Chris Uzdavinis (TeamB) wrote:
Quote
That's how I understood it, but I thought Alistair was suggesting some
pointer types decay into something else. I'm not aware of any
situation where ptr-to-T changes to ptr-to-U implicitly except when T
and U have an inheritance relationship, or U is void. But that's not
what we think of with the term 'decay'.
You appear to be correct. Whatever it was that convinced me that const
char (*)[6] should decay to const char *, I can't find it any more.
And that raises interesting questions about the original example...
--
AlisdairM(TeamB)