Connecting Tech Pros Worldwide Forums | Help | Site Map

Template function and const array of chars

Milan Cvetkovic
Guest
 
Posts: n/a
#1: Mar 22 '06
Hi,

Recently I came accross a weird bug in my code which turned to be my
missunderstanding of arrays in C++. It all boils down to the small example:


template<class ITER>
const char* gggg (ITER value)
{
return value;
}

int main (int /*argc*/, char* /*argv*/[])
{
const char array[] = "ABCD";
const char* p1 = gggg(array);
const char* p2 = gggg(array+0);
if (p1 == p2)
return 0;
else
return 1;
}

This program will report different results when compiled with different
compiler. In particular, g++-2.95.2 returns 1 (pointers are not equal)
and g++-4.1 returns 0 (pointers are equal).

Is this a compiler bug in 2.95.2, or the C++ spec allows the compiler do
this funny stuff.

Thanks, Milan.

Tomás
Guest
 
Posts: n/a
#2: Mar 22 '06

re: Template function and const array of chars


template<class T>
const char* TakeByValueAndConvertToCharPointer (T object)
{
return object;
}

int main()
{
char const array[] = "ABCD";

/*
Right now, we have an array in
memory that looks like as follows:

-------------------------------
| 'A' | 'B' | 'C' | 'D' | 0 |
-------------------------------

*/

const char* p1 = gggg(array);

//In the above line, you've just passed an array by value.
//If memory serves me right, that's dodgy.

const char* p2 = gggg(array+0);

//In the above line, it looks like "array" will decay to
//an expression of type "const char*", and then zero will
//be added to it.

if (p1 == p2)
return 0;
else
return 1;
}

-Tomás
Milan Cvetkovic
Guest
 
Posts: n/a
#3: Mar 22 '06

re: Template function and const array of chars


Tom" <NULL@NULL.NULL> wrote:[color=blue]
> const char* p1 = gggg(array);
>
> //In the above line, you've just passed an array by value.
> //If memory serves me right, that's dodgy.[/color]

I don't know what exactly you mean by "dodgy".
Isn't this usage same as when you write:

printf ("This is a string\n");

The function gggg is instantiated with <const char*> as a parameter, in
both invocations. The value of parameter passed depends on:
- compiler used; and
- the invocation (arrray or array+0)

Milan.
[color=blue]
> template<class T>
> const char* gggg (T object)
> {
> return object;
> }
>
> int main()
> {
> char const array[] = "ABCD";
>
> /*
> Right now, we have an array in
> memory that looks like as follows:
>
> -------------------------------
> | 'A' | 'B' | 'C' | 'D' | 0 |
> -------------------------------
>
> */
>
> const char* p1 = gggg(array);
>
> //In the above line, you've just passed an array by value.
> //If memory serves me right, that's dodgy.
>
> const char* p2 = gggg(array+0);
>
> //In the above line, it looks like "array" will decay to
> //an expression of type "const char*", and then zero will
> //be added to it.
>
> if (p1 == p2)
> return 0;
> else
> return 1;
> }
>
> -Tomás[/color]
Thomas Tutone
Guest
 
Posts: n/a
#4: Mar 22 '06

re: Template function and const array of chars


Tomás wrote:
[color=blue]
> template<class T>
> const char* TakeByValueAndConvertToCharPointer (T object)
> {
> return object;
> }
>
> int main()
> {
> char const array[] = "ABCD";
>
> /*
> Right now, we have an array in
> memory that looks like as follows:
>
> -------------------------------
> | 'A' | 'B' | 'C' | 'D' | 0 |
> -------------------------------
>
> */
>
> const char* p1 = gggg(array);
>
> //In the above line, you've just passed an array by value.[/color]

No, arrays can't be passed by value directly - one would have to wrap
it in a class to do so. Just the decayed pointer will be passed.

[snip]
[color=blue]
>
> const char* p2 = gggg(array+0);
>
> //In the above line, it looks like "array" will decay to
> //an expression of type "const char*", and then zero will
> //be added to it.
>
> if (p1 == p2)
> return 0;
> else
> return 1;
> }[/color]

Sorry to be dense, but I'm missing your point. Based on your analysis,
should the program return 0 or 1? That was the OP's question.

Best regards,

Tom

Martin Vejnar
Guest
 
Posts: n/a
#5: Mar 22 '06

re: Template function and const array of chars


Milan Cvetkovic wrote:[color=blue]
> template<class ITER>
> const char* gggg (ITER value)
> {
> return value;
> }
>
> int main (int /*argc*/, char* /*argv*/[])
> {
> const char array[] = "ABCD";
> const char* p1 = gggg(array);
> const char* p2 = gggg(array+0);
> if (p1 == p2)
> return 0;
> else
> return 1;
> }
>
> This program will report different results when compiled with different
> compiler. In particular, g++-2.95.2 returns 1 (pointers are not equal)
> and g++-4.1 returns 0 (pointers are equal).
>
> Is this a compiler bug in 2.95.2, or the C++ spec allows the compiler do
> this funny stuff.[/color]

As far as I can tell, both calls refer to the same function 'gggg<const
char *>(const char *)' and supply it with the same arguments. 'p1' and
'p2' should be equal.

On VS8.0, 'main' returns 0.

I'd say it's a compiler bug; the old g++ may have problems deducing
correct template arguments.

--
Martin
AnalogFile
Guest
 
Posts: n/a
#6: Mar 22 '06

re: Template function and const array of chars


Milan Cvetkovic wrote:[color=blue]
> Hi,
>
> Recently I came accross a weird bug in my code which turned to be my
> missunderstanding of arrays in C++. It all boils down to the small example:
>
>
> template<class ITER>
> const char* gggg (ITER value)
> {
> return value;
> }
>
> int main (int /*argc*/, char* /*argv*/[])
> {
> const char array[] = "ABCD";
> const char* p1 = gggg(array);
> const char* p2 = gggg(array+0);
> if (p1 == p2)
> return 0;
> else
> return 1;
> }
>
> This program will report different results when compiled with different
> compiler. In particular, g++-2.95.2 returns 1 (pointers are not equal)
> and g++-4.1 returns 0 (pointers are equal).
>
> Is this a compiler bug in 2.95.2, or the C++ spec allows the compiler do
> this funny stuff.[/color]

I guess G++-2.95.2 failed to comply with 14.8.2.1/2 and instantiated the
first call with the wrong type.

I guess you can test this by forcing an error and looking at the
compiler diagnostics. For example try

template<class ITER>
const char* gggg (ITER value)
{
value = 1;
return value;
}

since there's no cast it should give an error and tell you what type
ITER it's trying to instantiate.

Closed Thread