Topic: Type information thrown away?


Author: Daniel Frey <d.frey@gmx.de>
Date: Sat, 14 Sep 2002 17:13:25 CST
Raw View
On Fri, 02 Aug 2002 19:44:08 +0200, Randy Maddox wrote:

> I too am completely confused.  The MSVC++ compiler is useless on this
> code because it won't even compile it.  To add to the confusion, the
> error message, which occurs on the initializer list for the base::string
> ctor, says "invalid initialization - std::string is not a member or base
> of base::string".
>
> Curiouser and curiouser.

Just for the records and to end any left-over confusion: The GCC-folks analysed
it and it seems it is a compiler bug. See GNATS #7477 (and possibly
#3518). This makes EDG-based compilers and the VC++ 7 correct on this
issue. Thanks to all that helped me with this so far...

Regards, Daniel

---
[ 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: Daniel Frey <daniel.frey@aixigo.de>
Date: 5 Aug 2002 16:20:05 GMT
Raw View
Randy Maddox wrote:
>
> kanze@gabi-soft.de (James Kanze) wrote in message news:<d6651fb6.0208010621.50c7eb70@posting.google.com>...
> > rmaddox@isicns.com (Randy Maddox) wrote in message
> > news:<8c8b368d.0207310533.266ba238@posting.google.com>...
> > > Daniel Frey <daniel.frey@aixigo.de> wrote in message
> > > news:<3D467440.F3E2EF7@aixigo.de>...
> >
> >
> > Where does he construct a base::string with a const char*?
>
> In both cases where a base::string is constructed the initialization
> value used is "Hello, world!".  Clause 2.13.4, paragraph 1, states
> that the type of a string literal is "array of n const char", and by

OK.

> definition that array will decay to const char * when passed in a
> function call.

What definition? I cannot see this in 2.13.4 or is there any other
clause you are refering to?

> I agree completely that this is the crux of the matter.  Whatever the
> compiler is going to do, it seems that it should do the same in both
> cases.  The only difference I can see is that the explicitly created
> base::string is non-const, while the temporary created in the call to
> f() is const.  However, it does not seem like that should make any
> difference.

I think that clause 13.3.3.1.4 says that there should be no difference:
"Conceptually, this conversion sequence corresponds to copy-initializing
a temporary of the underlying type with the argument expression. Any
difference in top-level cv-qualification is sub-sumed by the
initialization itself and does not constitute a conversion."

IMHO this (plus the clauses James named) makes the difference I observed
illegal. Both objects should be initialized with 'T = const char[14]'.

> I too am completely confused.  The MSVC++ compiler is useless on this
> code because it won't even compile it.  To add to the confusion, the
> error message, which occurs on the initializer list for the
> base::string ctor, says "invalid initialization - std::string is not a
> member or base of base::string".

Maybe we should call the VisualC++ WeirdC++ in the future ;)

For the records: I threw James' modified version into the online Comeau.
It compiled fine, so I guess this compiler (like the Intel-compiler) has
no problem with it. (Is the Comeau EDG-based, too?)

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo   -Rahe-Stra   e 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ 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: Michiel.Salters@cmg.nl (Michiel Salters)
Date: 5 Aug 2002 16:20:08 GMT
Raw View
Daniel Frey <d.frey@gmx.de> wrote in message news:<3d497086$0$1619$9b622d9e@news.freenet.de>...
> On Thu, 01 Aug 2002 17:10:07 +0200, James Kanze wrote:
>
> > rmaddox@isicns.com (Randy Maddox) wrote in message
> > news:<8c8b368d.0207310533.266ba238@posting.google.com>...
> >> Daniel Frey <daniel.frey@aixigo.de> wrote in message
> >> news:<3D467440.F3E2EF7@aixigo.de>...
>
> >> > When I compile and start this program, the output looks like this:
>
> >> > GCC 2.95.2:
>
> >> > A13 c
> >> > Hello, world!
> >> > PCc
> >> > Hel
>
> >> > GCC 3.1:
>
> >> > A14 c
> >> > Hello, world!
> >> > PKc
> >> > Hel
> >
>
> The Intel compiler (v6) produces:
>
> A14 c
> Hello, world!
> A14 c
> Hello, world!

MSVC7 produces:

char [14]
Hello, world!
char [14]
Hello, world!

Which still doesn't prove anything, of course.

Regards,
--
Michiel Salters

---
[ 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: rmaddox@isicns.com (Randy Maddox)
Date: Fri, 2 Aug 2002 17:44:08 GMT
Raw View
kanze@gabi-soft.de (James Kanze) wrote in message news:<d6651fb6.0208010621.50c7eb70@posting.google.com>...
> rmaddox@isicns.com (Randy Maddox) wrote in message
> news:<8c8b368d.0207310533.266ba238@posting.google.com>...
> > Daniel Frey <daniel.frey@aixigo.de> wrote in message
> > news:<3D467440.F3E2EF7@aixigo.de>...
>
>
> Where does he construct a base::string with a const char*?

In both cases where a base::string is constructed the initialization
value used is "Hello, world!".  Clause 2.13.4, paragraph 1, states
that the type of a string literal is "array of n const char", and by
definition that array will decay to const char * when passed in a
function call.

>
> More to the point, why does constructing the declared string give
> different results than constructing the temporary one?  Or more
> correctly, why does constructing a temporary base::string to pass to the
> copy constructor of base::string in the first expression give different
> results than constructing a temporary base::string to bind to a const
> reference in the second expression?
>

I agree completely that this is the crux of the matter.  Whatever the
compiler is going to do, it seems that it should do the same in both
cases.  The only difference I can see is that the explicitly created
base::string is non-const, while the temporary created in the call to
f() is const.  However, it does not seem like that should make any
difference.

I too am completely confused.  The MSVC++ compiler is useless on this
code because it won't even compile it.  To add to the confusion, the
error message, which occurs on the initializer list for the
base::string ctor, says "invalid initialization - std::string is not a
member or base of base::string".

Curiouser and curiouser.

Randy.

---
[ 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.de (James Kanze)
Date: Sat, 3 Aug 2002 00:05:08 GMT
Raw View
Daniel Frey <d.frey@gmx.de> wrote in message
news:<3d497086$0$1619$9b622d9e@news.freenet.de>...
> On Thu, 01 Aug 2002 17:10:07 +0200, James Kanze wrote:

> > rmaddox@isicns.com (Randy Maddox) wrote in message
> > news:<8c8b368d.0207310533.266ba238@posting.google.com>...
> >> Daniel Frey <daniel.frey@aixigo.de> wrote in message
> >> news:<3D467440.F3E2EF7@aixigo.de>...

> >> > When I compile and start this program, the output looks like this:

> >> > GCC 2.95.2:

> >> > A13 c
> >> > Hello, world!
> >> > PCc
> >> > Hel

> >> > GCC 3.1:

> >> > A14 c
> >> > Hello, world!
> >> > PKc
> >> > Hel

> The Intel compiler (v6) produces:

> A14 c
> Hello, world!
> A14 c
> Hello, world!

> Which is what I would expect.

That's what I would expect, too.  But the standard is complex enough
that one never knows:-).

> > I don't see an array to pointer conversion taking place implicitely and
> > automatically, but I could have missed that in all of the text.  (Maybe
> > something related to template type deduction -- perhaps once overload
> > resolution has selected the template constructor "base::string::string(
> > char const (&)[ 13 ] )", it converts the parameter type to "char const
> > (&*)".  This isn't what I see in ?14.8.2/3, but I may have missed
> > something.)  Whatever the results should be, however, it does seem that
> > the two cases should be the same.

> > I'd feel more confident of my analysis if two independantly written
> > compilers didn't both say something different, but I sure would like
> > to know where I went wrong.

> The result of the Intel compiler gives hope :)

Especially as it is based on the EDG front-end, which has the reputation
as being the most conformant.

> At least it seems that it is legal to pass char[14] for both objects
> constructed. The remaining question is, whether the standard allows
> the type's length information to be lost. If so, I'd call it a defect,
> as I don't see any reason to allow the compiler to throw away the
> information.

The only way the length could get lost is by conversion to char const*.

> If the user code converts it to 'char*' - so be it, but the language
> itself should not do that.  If the standard actually states that the
> ICC is correct and the GCC/SunCC are wrong, it would also help to have
> some references when submitting a bug-report to the GCC folks...

Well, I spit out a lot in my previous posting.  IMHO, the fact that the
two cases are different can only be an error.  Why not send them a bug
report with a reference to this thread.  Or simply be direct: say this
is the actual output, and this is what it should be.  Some of the
developpers read this newsgroup, and they will presumably know what is
going on.  (If not, and they ask, refer them to the thread.  But insist
that they quote text in the standard to back them up if they say it is
correct.)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: Daniel Frey <d.frey@gmx.de>
Date: Sat, 3 Aug 2002 19:04:25 GMT
Raw View
On Sat, 03 Aug 2002 02:05:08 +0200, James Kanze wrote:

> Well, I spit out a lot in my previous posting.  IMHO, the fact that the
> two cases are different can only be an error.  Why not send them a bug
> report with a reference to this thread.  Or simply be direct: say this
> is the actual output, and this is what it should be.  Some of the
> developpers read this newsgroup, and they will presumably know what is
> going on.  (If not, and they ask, refer them to the thread.  But insist
> that they quote text in the standard to back them up if they say it is
> correct.)

ACK. Let's see if their comments are friendlier as for the last bug I found
(GNATS #7065).

Regards, Daniel

---
[ 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: rmaddox@isicns.com (Randy Maddox)
Date: Wed, 31 Jul 2002 17:56:33 GMT
Raw View
Daniel Frey <daniel.frey@aixigo.de> wrote in message news:<3D467440.F3E2EF7@aixigo.de>...
> Hi,
>
> consider the following code:
>
> #include <string>
> #include <iostream>
> #include <typeinfo>
>
> namespace base
> {
>    struct string : public ::std::string
>    {
>       template< typename T >
>       string( const T& s )
>             : ::std::string( s, sizeof( s ) / sizeof( *s ) - 1 )
>       {
>          std::cout << typeid( T ).name() << std::endl;
>       }
>    };
> }
>
> void f( const base::string& s )
> {
>    std::cout << s << std::endl;
> }
>
> int main()
> {
>    base::string s = "Hello, world!";
>    std::cout << s << std::endl;
>
>    f( "Hello, world!" );
> }
>
> When I compile and start this program, the output looks like this:
>
> GCC 2.95.2:
>
> A13 c
> Hello, world!
> PCc
> Hel
>
> GCC 3.1:
>
> A14 c
> Hello, world!
> PKc
> Hel
>
> It seems that for the parameter of f(), the type information is cut down
> to a const char*, the length of the array is lost. Is this what the
> standard prescribes? Or is it just a bug in the GCC? If it's the
> standard: Was it intended? Shouldn't it be changed to that I have a
> change to get as much information as possible?
>
> Regards, Daniel
>

The code is behaving correctly.  Look at your initialization of
std::string:

>       template< typename T >
>       string( const T& s )
>             : ::std::string( s, sizeof( s ) / sizeof( *s ) - 1 )

Here T is const char *, where sizeof(const char *) is 4,
sizeof(*(const char *)) is the same as sizeof(char), which is one, so
the whole initialization expression becomes:

   std::string(s, 4 / 1 - 1)    - or -    std::string(s, 3)

And your code is spitting out 3 characters.  What else should it do?

Randy.

---
[ 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: Daniel Frey <daniel.frey@aixigo.de>
Date: Thu, 1 Aug 2002 10:09:12 CST
Raw View
Randy Maddox wrote:
>

A note to Randy: I replied personally by accident, the reply should have
gone here. Anyway...

> The code is behaving correctly.  Look at your initialization of
> std::string:
>
> >       template< typename T >
> >       string( const T& s )
> >             : ::std::string( s, sizeof( s ) / sizeof( *s ) - 1 )
>
> Here T is const char *, where sizeof(const char *) is 4,
> sizeof(*(const char *)) is the same as sizeof(char), which is one, so
> the whole initialization expression becomes:
>
>    std::string(s, 4 / 1 - 1)    - or -    std::string(s, 3)
>
> And your code is spitting out 3 characters.  What else should it do?

I understand that only 3 characters are spitted out if T is char*. But
my question is, why T is char* and not char[14]. The type of a string
literal is 'const char*'? Well, then why doesn't the output of the code
looks like this:

PCc
Hel
PCc
Hel

instead of:

A13 c
Hello, world!
PCc
Hel

When I call 'base::string s = "Hello, world!";', T is not char*, it is
char[14]. This is a useful information that prevents a scan of the
string to find out it's length. But if used as a parameter in f(), the
type is reduced to char*. Why this asymmetry? Why is the length
information available in the first constructed base::string, but not in
the second? I have already managed to write a class which can take both
a char[N] and a char*, where the char* is scanned for it's length while
the char[N] needn't do so. But it's mostly useless if the type's length
information is simply thrown away be the compiler for most of the cases
it would be useful.

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo   -Rahe-Stra   e 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ 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.de (James Kanze)
Date: Thu, 1 Aug 2002 15:10:07 GMT
Raw View
rmaddox@isicns.com (Randy Maddox) wrote in message
news:<8c8b368d.0207310533.266ba238@posting.google.com>...
> Daniel Frey <daniel.frey@aixigo.de> wrote in message
> news:<3D467440.F3E2EF7@aixigo.de>...

> > consider the following code:

> > #include <string>
> > #include <iostream>
> > #include <typeinfo>

> > namespace base
> > {
> >    struct string : public ::std::string
> >    {
> >       template< typename T >
> >       string( const T& s )
> >             : ::std::string( s, sizeof( s ) / sizeof( *s ) - 1 )
> >       {
> >          std::cout << typeid( T ).name() << std::endl;
> >       }
> >    };
> > }

> > void f( const base::string& s )
> > {
> >    std::cout << s << std::endl;
> > }

> > int main()
> > {
> >    base::string s = "Hello, world!";
> >    std::cout << s << std::endl;
> >
> >    f( "Hello, world!" );
> > }

> > When I compile and start this program, the output looks like this:

> > GCC 2.95.2:

> > A13 c
> > Hello, world!
> > PCc
> > Hel

> > GCC 3.1:

> > A14 c
> > Hello, world!
> > PKc
> > Hel

> > It seems that for the parameter of f(), the type information is cut
> > down to a const char*, the length of the array is lost. Is this what
> > the standard prescribes? Or is it just a bug in the GCC? If it's the
> > standard: Was it intended? Shouldn't it be changed to that I have a
> > change to get as much information as possible?

> The code is behaving correctly.  Look at your initialization of
> std::string:

> >       template< typename T >
> >       string( const T& s )
> >             : ::std::string( s, sizeof( s ) / sizeof( *s ) - 1 )

> Here T is const char *,

Where does he construct a base::string with a const char*?

More to the point, why does constructing the declared string give
different results than constructing the temporary one?  Or more
correctly, why does constructing a temporary base::string to pass to the
copy constructor of base::string in the first expression give different
results than constructing a temporary base::string to bind to a const
reference in the second expression?

I'm curious, because Sun CC 5.1 gives the same results, and I can't
explain them either.  The only difference I see is that the first case
is one of "copy-initialization of class by user-defined conversion"
(   13.3.1.4), and the second "initialization by conversion function for
direct reference binding" (   13.3.1.6).  Except that the second seems to
only cater to the case where the initializaton expression has class
type (which it doesn't here).  If we apply the rules for reference
initialization (   8.5.3/5), we end up in the final case: "Otherwise, a
temporary of type cv1 T1 [base::string const] is created and initialized
from the initializer expression using the rules for a non-reference copy
initialization (8.5)."  But non-reference copy initialization is exactly
what is occuring in the first case; we end up in    8.5/14, in the third
sub-case of the fourth case, which sends us to    13.3.1.4 -- exactly the
same as the first case.

I don't see an array to pointer conversion taking place implicitely and
automatically, but I could have missed that in all of the text.  (Maybe
something related to template type deduction -- perhaps once overload
resolution has selected the template constructor "base::string::string(
char const (&)[ 13 ] )", it converts the parameter type to "char const
(&*)".  This isn't what I see in    14.8.2/3, but I may have missed
something.)  Whatever the results should be, however, it does seem that
the two cases should be the same.

I'd feel more confident of my analysis if two independantly written
compilers didn't both say something different, but I sure would like to
know where I went wrong.

FWIW, I would have written his function as follows:

    namespace base
        class string : public std::string
        {
        public:
            template< size_t N >
            string( char const (&a)[ N ] )
                :   std::string( a, a + N )
            {
            }
        } ;

Curiously enough, with all three of my compilers (g++ 2.95.2, g++ 3.1
and Sun CC 5.1), I get an error on the call to f,

from g++ 2.95.2:
    conversion from `const char *' to non-scalar type `base::string'
    requested

from g++ 3.1:
    could not convert `"Hello, world!"' to `const base::string&'

from Sun CC 5.1:
    Error: Formal argument s of type const base::string& in call to
    f(const base::string&) is being passed const char[14].

So I'm now thoroughly confused.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: Daniel Frey <d.frey@gmx.de>
Date: Thu, 1 Aug 2002 18:00:19 GMT
Raw View
On Thu, 01 Aug 2002 17:10:07 +0200, James Kanze wrote:

> rmaddox@isicns.com (Randy Maddox) wrote in message
> news:<8c8b368d.0207310533.266ba238@posting.google.com>...
>> Daniel Frey <daniel.frey@aixigo.de> wrote in message
>> news:<3D467440.F3E2EF7@aixigo.de>...
>=20
>> > When I compile and start this program, the output looks like this:
>=20
>> > GCC 2.95.2:
>=20
>> > A13 c
>> > Hello, world!
>> > PCc
>> > Hel
>=20
>> > GCC 3.1:
>=20
>> > A14 c
>> > Hello, world!
>> > PKc
>> > Hel
>

The Intel compiler (v6) produces:

A14_c
Hello, world!
A14_c
Hello, world!

Which is what I would expect.

> I don't see an array to pointer conversion taking place implicitely and
> automatically, but I could have missed that in all of the text.  (Maybe
> something related to template type deduction -- perhaps once overload
> resolution has selected the template constructor "base::string::string(
> char const (&)[ 13 ] )", it converts the parameter type to "char const
> (&*)".  This isn't what I see in =A714.8.2/3, but I may have missed
> something.)  Whatever the results should be, however, it does seem that
> the two cases should be the same.
>=20
> I'd feel more confident of my analysis if two independantly written
> compilers didn't both say something different, but I sure would like to
> know where I went wrong.

The result of the Intel compiler gives hope :) At least it seems that it
is legal to pass char[14] for both objects constructed. The remaining
question is, whether the standard allows the type's length information to
be lost. If so, I'd call it a defect, as I don't see any reason to allow
the compiler to throw away the information. If the user code converts it
to 'char*' - so be it, but the language itself should not do that. If the
standard actually states that the ICC is correct and the GCC/SunCC are
wrong, it would also help to have some references when submitting a
bug-report to the GCC folks...

(Note: I don't have the standard :)

Regards, Daniel

---
[ 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: Daniel Frey <daniel.frey@aixigo.de>
Date: Tue, 30 Jul 2002 15:57:43 GMT
Raw View
Hi,

consider the following code:

#include <string>
#include <iostream>
#include <typeinfo>

namespace base
{
   struct string : public ::std::string
   {
      template< typename T >
      string( const T& s )
            : ::std::string( s, sizeof( s ) / sizeof( *s ) - 1 )
      {
         std::cout << typeid( T ).name() << std::endl;
      }
   };
}

void f( const base::string& s )=20
{
   std::cout << s << std::endl;
}

int main()
{
   base::string s =3D "Hello, world!";
   std::cout << s << std::endl;
  =20
   f( "Hello, world!" );
}

When I compile and start this program, the output looks like this:

GCC 2.95.2:

A13_c
Hello, world!
PCc
Hel

GCC 3.1:

A14_c
Hello, world!
PKc
Hel

It seems that for the parameter of f(), the type information is cut down
to a const char*, the length of the array is lost. Is this what the
standard prescribes? Or is it just a bug in the GCC? If it's the
standard: Was it intended? Shouldn't it be changed to that I have a
change to get as much information as possible?

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ 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                       ]