public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: C++ static integer class constants...
       [not found] <87oe5pb5dp.fsf@totally-fudged-out-message-id>
@ 2005-10-17 19:17 ` Florian Weimer
  2005-10-18  6:19   ` John Ratliff
  2005-10-18  6:19   ` John Ratliff
  0 siblings, 2 replies; 29+ messages in thread
From: Florian Weimer @ 2005-10-17 19:17 UTC (permalink / raw)
  To: John Ratliff; +Cc: gcc-help

* John Ratliff:

> On comp.lang.c++, Victor Bazarov says my example program is well-formed
> standard C++ according to the ISO C++ standard.
>
> "Since their address is never taken, the 'foo::A' and 'foo::B' are, in
> fact, compile-time constant expressions that do not require storage.
> The objects, therefore, don't need to be defined outside of the class
> definition.

This analysis argues from the implementation, not from the standard.

The standard requires that you provide a definition if you use the
constant in a place which does not *require* a constant expression.
In other words,

  int foo[Class::static_const_member];

is fine without a definition, but

  int bar = Class::static_const_member;

is not.

It's strange and smells like a mistake in the standard.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-17 19:17 ` C++ static integer class constants Florian Weimer
@ 2005-10-18  6:19   ` John Ratliff
  2005-10-18  6:19   ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-18  6:19 UTC (permalink / raw)
  To: 'MSX to GCC'

> * John Ratliff:
> 
> > On comp.lang.c++, Victor Bazarov says my example program is well-formed
> > standard C++ according to the ISO C++ standard.
> >
> > "Since their address is never taken, the 'foo::A' and 'foo::B' are, in
> > fact, compile-time constant expressions that do not require storage.
> > The objects, therefore, don't need to be defined outside of the class
> > definition.
> 
> This analysis argues from the implementation, not from the standard.
> 
> The standard requires that you provide a definition if you use the
> constant in a place which does not *require* a constant expression.
> In other words,
> 
>   int foo[Class::static_const_member];
> 
> is fine without a definition, but
> 
>   int bar = Class::static_const_member;
> 
> is not.
> 
> It's strange and smells like a mistake in the standard.

In response to my message on comp.lang.c++, Greg Comeau replies

"That's what it says but isn't what it meant.  What it meant is what Victor
said, and hence it was acknowledged as a defect since requiring the
definition in all cases was not the intent when member constants were
allowed."

So, it seems that it is a mistake in the standard. For anyone who doesn't
know him, Greg Comeau is a member of the C++ standards committee.

I think g++ is trying to do the correct thing (according to the intent of
the committee), even in 3.3, but has one problem area. I am going to leave
out my definitions for now since it will compile on both 3.3 and 3.4 now
that I've removed the ternary expression.

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-17 19:17 ` C++ static integer class constants Florian Weimer
  2005-10-18  6:19   ` John Ratliff
@ 2005-10-18  6:19   ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-18  6:19 UTC (permalink / raw)
  To: 'MSX to GCC'

> * John Ratliff:
> 
> > On comp.lang.c++, Victor Bazarov says my example program is well-formed
> > standard C++ according to the ISO C++ standard.
> >
> > "Since their address is never taken, the 'foo::A' and 'foo::B' are, in
> > fact, compile-time constant expressions that do not require storage.
> > The objects, therefore, don't need to be defined outside of the class
> > definition.
> 
> This analysis argues from the implementation, not from the standard.
> 
> The standard requires that you provide a definition if you use the
> constant in a place which does not *require* a constant expression.
> In other words,
> 
>   int foo[Class::static_const_member];
> 
> is fine without a definition, but
> 
>   int bar = Class::static_const_member;
> 
> is not.
> 
> It's strange and smells like a mistake in the standard.

In response to my message on comp.lang.c++, Greg Comeau replies

"That's what it says but isn't what it meant.  What it meant is what Victor
said, and hence it was acknowledged as a defect since requiring the
definition in all cases was not the intent when member constants were
allowed."

So, it seems that it is a mistake in the standard. For anyone who doesn't
know him, Greg Comeau is a member of the C++ standards committee.

I think g++ is trying to do the correct thing (according to the intent of
the committee), even in 3.3, but has one problem area. I am going to leave
out my definitions for now since it will compile on both 3.3 and 3.4 now
that I've removed the ternary expression.

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
       [not found] <0IOJ0024ULK8BF@emroute1.cind.ornl.gov>
@ 2005-10-18 12:26 ` Ernest L. Williams Jr.
  0 siblings, 0 replies; 29+ messages in thread
From: Ernest L. Williams Jr. @ 2005-10-18 12:26 UTC (permalink / raw)
  To: John Ratliff; +Cc: 'MSX to GCC'

On Tue, 2005-10-18 at 01:19 -0500, John Ratliff wrote:
> > * John Ratliff:
> > 
> > > On comp.lang.c++, Victor Bazarov says my example program is well-formed
> > > standard C++ according to the ISO C++ standard.
> > >
> > > "Since their address is never taken, the 'foo::A' and 'foo::B' are, in
> > > fact, compile-time constant expressions that do not require storage.
> > > The objects, therefore, don't need to be defined outside of the class
> > > definition.
> > 
> > This analysis argues from the implementation, not from the standard.
> > 
> > The standard requires that you provide a definition if you use the
> > constant in a place which does not *require* a constant expression.
> > In other words,
> > 
> >   int foo[Class::static_const_member];
> > 
> > is fine without a definition, but
> > 
> >   int bar = Class::static_const_member;
> > 
> > is not.
> > 
> > It's strange and smells like a mistake in the standard.
> 
> In response to my message on comp.lang.c++, Greg Comeau replies
> 
> "That's what it says but isn't what it meant.  What it meant is what Victor
> said, and hence it was acknowledged as a defect since requiring the
> definition in all cases was not the intent when member constants were
> allowed."
> 
> So, it seems that it is a mistake in the standard. For anyone who doesn't
> know him, Greg Comeau is a member of the C++ standards committee.
> 
> I think g++ is trying to do the correct thing (according to the intent of
> the committee), even in 3.3, but has one problem area. I am going to leave
> out my definitions for now since it will compile on both 3.3 and 3.4 now
> that I've removed the ternary expression.

This is very important and should be sent to the GCC developers' mailing
list so that they can toss this around a bit.  Do you subscribe there as
well?

Thanks,
Ernesto




> 
> --John Ratliff
> 
> 
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-17 18:07     ` corey taylor
@ 2005-10-17 20:04       ` John Ratliff
  2005-10-17 20:04       ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-17 20:04 UTC (permalink / raw)
  To: 'MSX to GCC'

Okay. I no longer think g++ 3.3 is wrong according to the standard, but I
still think it is a bug. Not because it violates the standard, but because
it is inconsistent with itself.

Take the following example program:

#include <iostream>

class foo {
public:
    static const unsigned int SRAM_SIZE = 0x2000;
    
    static const int CHECKSUM_OFFSET = 0x8;
    static const int CHECKSUM_OFFSET2 = 0x1FF8;

    foo();
    unsigned char getChecksum(bool redundant = false) const;
    
private:
    char sram[SRAM_SIZE];
};

const int foo::CHECKSUM_OFFSET;
const int foo::CHECKSUM_OFFSET2;

foo::foo() {
    sram[CHECKSUM_OFFSET] = 1;
    sram[CHECKSUM_OFFSET2] = 2;
}

unsigned char foo::getChecksum(bool redundant) const {
    int offset = (redundant ? CHECKSUM_OFFSET2 : CHECKSUM_OFFSET);
    
    return sram[offset];
}

int main(int, char **) {
    foo f;
    unsigned char c1 = f.getChecksum();
    unsigned char c2 = f.getChecksum(true);
    
    std::cout << "c1 = " << static_cast<int>(c1) << '\n';
    std::cout << "c2 = " << static_cast<int>(c2) << '\n';
    
    return 0;
}

This program will is a conforming program according to the standard and
works just fine in g++ 3.3.

But, if you replace the getChecksum method with

return sram[redundant ? CHECKSUM_OFFSET2 : CHECKSUM_OFFSET];

then you can safely remove the namespace scope definition. It is not
technically a conforming program then according to the standard, but g++
optimizes it here to be a compile-time constant which didn't need external
linkage. The program would be wrong, but g++'s behavior with regard to
optimization is inconsistent with itself. If it's going to optimize, it
should optimize whether you store the constant in a temporary like offset
using the ternary operator or not. You can also replace getChecksum with

unsigned char foo::getChecksum(bool redundant) const {
  int offset = CHECKSUM_OFFSET;
  if (redundant) offset = CHECKSUM_OFFSET2;
  return sram[offset];
}

and g++ will optimize it into a compile-time constant not requiring external
linkage. Something about the combination of the int offset and the ternary
operator assignment g++ 3.3 doesn't handle the way it handles everything
else.

Since the 3.3 series has been closed, I won't be filing a bug report, and
maybe the gcc team wouldn't even consider this a bug, but the inconsistency
is present, standards conformance notwithstanding.

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-17 18:07     ` corey taylor
  2005-10-17 20:04       ` John Ratliff
@ 2005-10-17 20:04       ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-17 20:04 UTC (permalink / raw)
  To: 'MSX to GCC'

Okay. I no longer think g++ 3.3 is wrong according to the standard, but I
still think it is a bug. Not because it violates the standard, but because
it is inconsistent with itself.

Take the following example program:

#include <iostream>

class foo {
public:
    static const unsigned int SRAM_SIZE = 0x2000;
    
    static const int CHECKSUM_OFFSET = 0x8;
    static const int CHECKSUM_OFFSET2 = 0x1FF8;

    foo();
    unsigned char getChecksum(bool redundant = false) const;
    
private:
    char sram[SRAM_SIZE];
};

const int foo::CHECKSUM_OFFSET;
const int foo::CHECKSUM_OFFSET2;

foo::foo() {
    sram[CHECKSUM_OFFSET] = 1;
    sram[CHECKSUM_OFFSET2] = 2;
}

unsigned char foo::getChecksum(bool redundant) const {
    int offset = (redundant ? CHECKSUM_OFFSET2 : CHECKSUM_OFFSET);
    
    return sram[offset];
}

int main(int, char **) {
    foo f;
    unsigned char c1 = f.getChecksum();
    unsigned char c2 = f.getChecksum(true);
    
    std::cout << "c1 = " << static_cast<int>(c1) << '\n';
    std::cout << "c2 = " << static_cast<int>(c2) << '\n';
    
    return 0;
}

This program will is a conforming program according to the standard and
works just fine in g++ 3.3.

But, if you replace the getChecksum method with

return sram[redundant ? CHECKSUM_OFFSET2 : CHECKSUM_OFFSET];

then you can safely remove the namespace scope definition. It is not
technically a conforming program then according to the standard, but g++
optimizes it here to be a compile-time constant which didn't need external
linkage. The program would be wrong, but g++'s behavior with regard to
optimization is inconsistent with itself. If it's going to optimize, it
should optimize whether you store the constant in a temporary like offset
using the ternary operator or not. You can also replace getChecksum with

unsigned char foo::getChecksum(bool redundant) const {
  int offset = CHECKSUM_OFFSET;
  if (redundant) offset = CHECKSUM_OFFSET2;
  return sram[offset];
}

and g++ will optimize it into a compile-time constant not requiring external
linkage. Something about the combination of the int offset and the ternary
operator assignment g++ 3.3 doesn't handle the way it handles everything
else.

Since the 3.3 series has been closed, I won't be filing a bug report, and
maybe the gcc team wouldn't even consider this a bug, but the inconsistency
is present, standards conformance notwithstanding.

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
  2005-10-17  9:09 ` Nathan Sidwell
@ 2005-10-17 19:21   ` Florian Weimer
  0 siblings, 0 replies; 29+ messages in thread
From: Florian Weimer @ 2005-10-17 19:21 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: John Ratliff, gcc-help

* Nathan Sidwell:

> Is this a DR?

There is, but it says something different. 8-)

> This is (a) the first time I've heard of such a change, and (b) 
> not mentioned in C++ TC1.  Please provide a reference.

The change was made to 3.2(2), changing the definition of "potentially
evaluated" and hence "used".

I think its DR 82 and, in particular, 48.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
  2005-10-16 14:50 ` Alex J. Dam
@ 2005-10-17 19:13   ` Florian Weimer
  0 siblings, 0 replies; 29+ messages in thread
From: Florian Weimer @ 2005-10-17 19:13 UTC (permalink / raw)
  To: Alex J. Dam; +Cc: gcc-help

* Alex J. Dam:

> This is usually only needed when, e. g., you take the address of a
> constant:
>
> const int *x = &foo::X;

Not quite.  This is needed if you use the constant in a context which
does not *require* an integral constant.  However, GCC does not
provide a diagnostics for this case (and the C++ spec does not require
one).

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
       [not found]   ` <4353e481.0829b6d6.64bd.18a4SMTPIN_ADDED@mx.gmail.com>
@ 2005-10-17 18:07     ` corey taylor
  2005-10-17 20:04       ` John Ratliff
  2005-10-17 20:04       ` John Ratliff
  0 siblings, 2 replies; 29+ messages in thread
From: corey taylor @ 2005-10-17 18:07 UTC (permalink / raw)
  To: John Ratliff; +Cc: MSX to GCC

The 2003 specification basically agrees:

If a static data member is of const integral or const enumeration
type, its declaration in the class
definition can specify a constant-initializer which shall be an
integral constant expression (5.19). In that
case, the member can appear in integral constant expressions. The
member shall still be defined in a namespace
scope if it is used in the program and the namespace scope definition
shall not contain an initializer.

The explanation of "use" is obvious in that context as meaning used
outside of a constant integral expression.

corey

On 10/17/05, John Ratliff <webmaster@technoplaza.net> wrote:
> Well, this just gets more complicated everyday.
>
> The 9.4.2, par 4 section of the standard 1998 in any case (I don't have
> access to the 2003 version) says you must declare the variable. But then it
> goes on to say that if you do, you can't use the initializer. So g++ 3.3 is
> correct, and 3.4 is just a better optimizer.
>
> So, you can use named static constants as long as they only appear in the
> class-def, and I am supposed to define them if they are "used" in the
> program, though the definition of "used" is somewhat debatable.
>
> However, this is not what was intended, and is proposed for change.
>
> The DR on this:
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#48
>
> More on this:
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#454
>
> I already know bout the enum hack, but this is supposed to supplant and
> remove it.
>
> --John Ratliff
>
>
> > -----Original Message-----
> > From: John Love-Jensen [mailto:eljay@adobe.com]
> > Sent: Monday, October 17, 2005 7:03 AM
> > To: John Ratliff; MSX to GCC
> > Subject: Re: C++ static integer class constants...
> >
> > Hi John,
> >
> > To get the behavior you want without having to define the static class
> > constant in some translation unit, use an anonymous enum:
> >
> > class foo {
> > public:
> >   enum { X = 5, Y = 10, Z = 15 };
> > };
> >
> > >Is this correct behavior?
> >
> > I believe your example demonstrates the correct behavior.
> >
> > In that *IF* you specify the value of a static const int in the
> > declaration, that both you *MUST* define the static const int in
> > one-and-only-one translation unit, and you *MUST NOT* specify the
> > initialization value in that definition.
> >
> > HTH,
> > --Eljay
> >
>
>
>
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-17 12:05 ` John Love-Jensen
  2005-10-17 17:50   ` John Ratliff
@ 2005-10-17 17:50   ` John Ratliff
       [not found]   ` <4353e481.0829b6d6.64bd.18a4SMTPIN_ADDED@mx.gmail.com>
  2 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-17 17:50 UTC (permalink / raw)
  To: 'MSX to GCC'

Well, this just gets more complicated everyday.

The 9.4.2, par 4 section of the standard 1998 in any case (I don't have
access to the 2003 version) says you must declare the variable. But then it
goes on to say that if you do, you can't use the initializer. So g++ 3.3 is
correct, and 3.4 is just a better optimizer.

So, you can use named static constants as long as they only appear in the
class-def, and I am supposed to define them if they are "used" in the
program, though the definition of "used" is somewhat debatable.

However, this is not what was intended, and is proposed for change.

The DR on this: 
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#48

More on this:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#454

I already know bout the enum hack, but this is supposed to supplant and
remove it.

--John Ratliff


> -----Original Message-----
> From: John Love-Jensen [mailto:eljay@adobe.com]
> Sent: Monday, October 17, 2005 7:03 AM
> To: John Ratliff; MSX to GCC
> Subject: Re: C++ static integer class constants...
> 
> Hi John,
> 
> To get the behavior you want without having to define the static class 
> constant in some translation unit, use an anonymous enum:
> 
> class foo {
> public:
>   enum { X = 5, Y = 10, Z = 15 };
> };
> 
> >Is this correct behavior?
> 
> I believe your example demonstrates the correct behavior.
> 
> In that *IF* you specify the value of a static const int in the 
> declaration, that both you *MUST* define the static const int in 
> one-and-only-one translation unit, and you *MUST NOT* specify the 
> initialization value in that definition.
> 
> HTH,
> --Eljay
> 



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-17 12:05 ` John Love-Jensen
@ 2005-10-17 17:50   ` John Ratliff
  2005-10-17 17:50   ` John Ratliff
       [not found]   ` <4353e481.0829b6d6.64bd.18a4SMTPIN_ADDED@mx.gmail.com>
  2 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-17 17:50 UTC (permalink / raw)
  To: 'MSX to GCC'

Well, this just gets more complicated everyday.

The 9.4.2, par 4 section of the standard 1998 in any case (I don't have
access to the 2003 version) says you must declare the variable. But then it
goes on to say that if you do, you can't use the initializer. So g++ 3.3 is
correct, and 3.4 is just a better optimizer.

So, you can use named static constants as long as they only appear in the
class-def, and I am supposed to define them if they are "used" in the
program, though the definition of "used" is somewhat debatable.

However, this is not what was intended, and is proposed for change.

The DR on this: 
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#48

More on this:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#454

I already know bout the enum hack, but this is supposed to supplant and
remove it.

--John Ratliff


> -----Original Message-----
> From: John Love-Jensen [mailto:eljay@adobe.com]
> Sent: Monday, October 17, 2005 7:03 AM
> To: John Ratliff; MSX to GCC
> Subject: Re: C++ static integer class constants...
> 
> Hi John,
> 
> To get the behavior you want without having to define the static class 
> constant in some translation unit, use an anonymous enum:
> 
> class foo {
> public:
>   enum { X = 5, Y = 10, Z = 15 };
> };
> 
> >Is this correct behavior?
> 
> I believe your example demonstrates the correct behavior.
> 
> In that *IF* you specify the value of a static const int in the 
> declaration, that both you *MUST* define the static const int in 
> one-and-only-one translation unit, and you *MUST NOT* specify the 
> initialization value in that definition.
> 
> HTH,
> --Eljay
> 



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
       [not found] <200510160743.j9G7hVoa010304@inbound-smtp-1.corp.adobe.com>
@ 2005-10-17 12:05 ` John Love-Jensen
  2005-10-17 17:50   ` John Ratliff
                     ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: John Love-Jensen @ 2005-10-17 12:05 UTC (permalink / raw)
  To: John Ratliff, MSX to GCC

Hi John,

To get the behavior you want without having to define the static class
constant in some translation unit, use an anonymous enum:

class foo {
public:
  enum { X = 5, Y = 10, Z = 15 };
};

>Is this correct behavior?

I believe your example demonstrates the correct behavior.

In that *IF* you specify the value of a static const int in the declaration,
that both you *MUST* define the static const int in one-and-only-one
translation unit, and you *MUST NOT* specify the initialization value in
that definition.

HTH,
--Eljay


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
       [not found] <20051016195314.7EFB824AEF5@lax-gw02.mroute.net>
@ 2005-10-17  9:09 ` Nathan Sidwell
  2005-10-17 19:21   ` Florian Weimer
  0 siblings, 1 reply; 29+ messages in thread
From: Nathan Sidwell @ 2005-10-17  9:09 UTC (permalink / raw)
  To: John Ratliff; +Cc: gcc-help

John Ratliff wrote:

> On comp.lang.c++, Victor Bazarov says my example program is well-formed
> standard C++ according to the ISO C++ standard.


> "Since their address is never taken, the 'foo::A' and 'foo::B' are, in
> fact, compile-time constant expressions that do not require storage.
> The objects, therefore, don't need to be defined outside of the class
> definition.  g++ 3.3.3 is probably too old.  It's even too old and non-
> compliant in this particular case even with 1998 version of the C++
> Standard.  The standard was amended to allow const statics to be only
> defined in the class definition if their address is not taken _even_
> if they are "used" outside the class.  [I am too lazy, though, to look
> it up in the Standard...]" -- Victor Bazarov (comp.lang.c++)

Is this a DR?  This is (a) the first time I've heard of such a change, and (b) 
not mentioned in C++ TC1.  Please provide a reference.

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
       [not found] <20051016200125.C061F13137C@arvo.suso.org>
@ 2005-10-16 21:36 ` John Ratliff
  2005-10-16 21:36 ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 21:36 UTC (permalink / raw)
  To: gcc-help

> I am going to upgrade to g++ 3.4, but I think it is a g++ 3.3.3 and 3.3.5
> bug. I should go see if 3.3.6 fixed this.

Apparently, my other Linux box was already using 3.3.6, so I guess they
didn't fix it before the 3.4 series.

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
       [not found] <20051016200125.C061F13137C@arvo.suso.org>
  2005-10-16 21:36 ` John Ratliff
@ 2005-10-16 21:36 ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 21:36 UTC (permalink / raw)
  To: gcc-help

> I am going to upgrade to g++ 3.4, but I think it is a g++ 3.3.3 and 3.3.5
> bug. I should go see if 3.3.6 fixed this.

Apparently, my other Linux box was already using 3.3.6, so I guess they
didn't fix it before the 3.4 series.

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 19:29       ` Alex J. Dam
@ 2005-10-16 19:53         ` John Ratliff
  2005-10-16 19:53         ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 19:53 UTC (permalink / raw)
  To: gcc-help

> On Sun, Oct 16, 2005 at 02:02:09PM -0500, John Ratliff wrote:
> > This seems like a definite bug. The fact that it works in 3.4.2 and not
> in
> > 3.3.3 seems like a probable bug to me, but I will ask this question in a
> > standard C++ newsgroup so that someone intimately familiar with the
> standard
> > can give me a definitive answer, but I still think g++ 3.3 is wrong and
> g++
> > 3.4 is right.
> >
> > If I were taking the address of the constant, sure, it would have to
> have
> > storage space and I wouldn't expect it any other way.
> >
> 
> I agree in that this is a weird behaviour, but I don't think it's
> exactly a bug, unless it is mandatory for a compiler to try
> everything possible before taking the address of a constant.  Maybe
> GCC 3.3 simply couldn't find a way to use the constants directly.

On comp.lang.c++, Victor Bazarov says my example program is well-formed
standard C++ according to the ISO C++ standard.

"Since their address is never taken, the 'foo::A' and 'foo::B' are, in
fact, compile-time constant expressions that do not require storage.
The objects, therefore, don't need to be defined outside of the class
definition.  g++ 3.3.3 is probably too old.  It's even too old and non-
compliant in this particular case even with 1998 version of the C++
Standard.  The standard was amended to allow const statics to be only
defined in the class definition if their address is not taken _even_
if they are "used" outside the class.  [I am too lazy, though, to look
it up in the Standard...]" -- Victor Bazarov (comp.lang.c++)

I am going to upgrade to g++ 3.4, but I think it is a g++ 3.3.3 and 3.3.5
bug. I should go see if 3.3.6 fixed this.

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 19:29       ` Alex J. Dam
  2005-10-16 19:53         ` John Ratliff
@ 2005-10-16 19:53         ` John Ratliff
  1 sibling, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 19:53 UTC (permalink / raw)
  To: gcc-help

> On Sun, Oct 16, 2005 at 02:02:09PM -0500, John Ratliff wrote:
> > This seems like a definite bug. The fact that it works in 3.4.2 and not
> in
> > 3.3.3 seems like a probable bug to me, but I will ask this question in a
> > standard C++ newsgroup so that someone intimately familiar with the
> standard
> > can give me a definitive answer, but I still think g++ 3.3 is wrong and
> g++
> > 3.4 is right.
> >
> > If I were taking the address of the constant, sure, it would have to
> have
> > storage space and I wouldn't expect it any other way.
> >
> 
> I agree in that this is a weird behaviour, but I don't think it's
> exactly a bug, unless it is mandatory for a compiler to try
> everything possible before taking the address of a constant.  Maybe
> GCC 3.3 simply couldn't find a way to use the constants directly.

On comp.lang.c++, Victor Bazarov says my example program is well-formed
standard C++ according to the ISO C++ standard.

"Since their address is never taken, the 'foo::A' and 'foo::B' are, in
fact, compile-time constant expressions that do not require storage.
The objects, therefore, don't need to be defined outside of the class
definition.  g++ 3.3.3 is probably too old.  It's even too old and non-
compliant in this particular case even with 1998 version of the C++
Standard.  The standard was amended to allow const statics to be only
defined in the class definition if their address is not taken _even_
if they are "used" outside the class.  [I am too lazy, though, to look
it up in the Standard...]" -- Victor Bazarov (comp.lang.c++)

I am going to upgrade to g++ 3.4, but I think it is a g++ 3.3.3 and 3.3.5
bug. I should go see if 3.3.6 fixed this.

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 17:43   ` Alex J. Dam
       [not found]     ` <4352a3b2.42389977.3b5e.60fdSMTPIN_ADDED@mx.gmail.com>
  2005-10-16 19:45     ` John Ratliff
@ 2005-10-16 19:45     ` John Ratliff
  2 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 19:45 UTC (permalink / raw)
  To: gcc-help

I forgot to hit reply to all, but I wanted this to go to the list.

> After reading Ryan's post, I looked at the (draft) standard.  It says:
> 
> 4 If  a  static  data  member  is of const integral or const enumeration
>   type, its declaration in the class definition can specify a  constant-
>   initializer   which   shall   be   an   integral  constant  expression
>   (_expr.const_).  In that case, the member can appear in integral  con-
>   stant expressions within its scope.  The member shall still be defined
>   in a namespace scope if it is used in the program  and  the  namespace
>   scope definition shall not contain an initializer.
> 
> If I understand this correctly, even const static members need to have 
> a definition somewhere.  Maybe this is "needed" so that you may always 
> take the address of such const static members.
> 
> So the compiler is free to use the constant as if they were variables, 
> if it needs to.  Your code compiles OK if the line
> 
>         int offset = (redundant ? B : A);
> 
> is replaced by
> 
>         if(redundant)
>           offset = B;
>         else
>           offset = A;
> 
> I don't know why, but it does work here.

This seems like a definite bug. The fact that it works in 3.4.2 and not in
3.3.3 seems like a probable bug to me, but I will ask this question in a
standard C++ newsgroup so that someone intimately familiar with the standard
can give me a definitive answer, but I still think g++ 3.3 is wrong and g++
3.4 is right.

If I were taking the address of the constant, sure, it would have to have
storage space and I wouldn't expect it any other way.

I was looking at the assembly generated by each compiler. There is a
striking difference. Here is foo::method(bool redundant) in x86 assembly
generated by mingw/g++ 3.4.2. I have commented the relevant sections.

-----------------------------------------------
.globl __ZNK3foo6methodEb
	.def	__ZNK3foo6methodEb;	.scl	2;	.type	32;
.endef
__ZNK3foo6methodEb:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$40, %esp
	movl	12(%ebp), %eax
	movb	%al, -1(%ebp)    ; move redundant (%al) to stack
	cmpb	$0, -1(%ebp)     ; if redundant is false 
	je	L12              ; goto L12
	movl	$8184, -16(%ebp) ; move 8184 (0x1FF8) into -16(%ebp) (aka
offset)
	jmp	L13              ; goto L13
L12:
	movl	$8, -16(%ebp)    ; move 8 into offset
L13:
	movl	-16(%ebp), %eax  ; return std::pair blah blah blah
	movl	%eax, -8(%ebp)
	movl	8(%ebp), %eax
	addl	-8(%ebp), %eax
	incl	%eax
	movzbl	(%eax), %eax
	movb	%al, -11(%ebp)
	leal	-11(%ebp), %eax
	movl	%eax, 8(%esp)
	movl	8(%ebp), %edx
	movl	-8(%ebp), %eax
	movzbl	(%eax,%edx), %eax
	movb	%al, -12(%ebp)
	leal	-12(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	-10(%ebp), %eax
	movl	%eax, (%esp)
	call	__ZNSt4pairIhhEC1ERKhS2_
	movzwl	-10(%ebp), %eax
	leave
	ret
-----------------------------------------------

And here is g++ 3.3.3's assembly output. As you can see, it's not even
trying to use it as a constant. This is why storage space is required.

-----------------------------------------------
_ZNK3foo6methodEb:
.LFB1535:
	pushl	%ebp
.LCFI14:
	movl	%esp, %ebp
.LCFI15:
	subl	$24, %esp
.LCFI16:
	movl	16(%ebp), %eax
	movb	%al, -1(%ebp)    ; move al (redundant) to stack
	cmpb	$0, -1(%ebp)     ; is redundant false?
	je	.L6              ; then jump to .L6
	movl	_ZN3foo1BE, %eax ; move B (storage space required) to eax
	movl	%eax, -16(%ebp)  ; put eax on the stack
	jmp	.L7
.L6:
	movl	_ZN3foo1AE, %eax ; move A (storage space required) to eax
	movl	%eax, -16(%ebp)  ; and put eax on the stack
.L7:
	movl	-16(%ebp), %eax  ; ??? why is it moving it just to move it
back?
	movl	%eax, -8(%ebp)   ; whatever, the rest is return std::pair
blah blah
	subl	$4, %esp
	movl	12(%ebp), %eax
	addl	-8(%ebp), %eax
	incl	%eax
	movb	(%eax), %al
	movb	%al, -9(%ebp)
	leal	-9(%ebp), %eax
	pushl	%eax
	movl	12(%ebp), %edx
	movl	-8(%ebp), %eax
	movb	(%eax,%edx), %al
	movb	%al, -10(%ebp)
	leal	-10(%ebp), %eax
	pushl	%eax
	pushl	8(%ebp)
.LCFI17:
	call	_ZNSt4pairIhhEC1ERKhS2_
	addl	$16, %esp
	movl	8(%ebp), %eax
	leave
	ret	$4
-----------------------------------------------

If you replace the ternary operator with the if as you suggested, the
assembly looks more like the 3.4.2 version. This is why it compiles, and
makes it seem more and more like a bug. Clearly it's capable of doing what I
think it should do, but chooses not to when presented with the ternary
operator.

> 
> So you need to define those constants somewhere, but the compiler  may 
> use the initializer in the class scope, if it is able to do so.  For 
> some reason, GCC couldn't use the initializer in the first case, so it 
> is using the address of the constants.  Go figure.

The assembly output and changing from ternary to if proves it can use the
initializer, but chooses not to.

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 17:43   ` Alex J. Dam
       [not found]     ` <4352a3b2.42389977.3b5e.60fdSMTPIN_ADDED@mx.gmail.com>
@ 2005-10-16 19:45     ` John Ratliff
  2005-10-16 19:45     ` John Ratliff
  2 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 19:45 UTC (permalink / raw)
  To: gcc-help

I forgot to hit reply to all, but I wanted this to go to the list.

> After reading Ryan's post, I looked at the (draft) standard.  It says:
> 
> 4 If  a  static  data  member  is of const integral or const enumeration
>   type, its declaration in the class definition can specify a  constant-
>   initializer   which   shall   be   an   integral  constant  expression
>   (_expr.const_).  In that case, the member can appear in integral  con-
>   stant expressions within its scope.  The member shall still be defined
>   in a namespace scope if it is used in the program  and  the  namespace
>   scope definition shall not contain an initializer.
> 
> If I understand this correctly, even const static members need to have 
> a definition somewhere.  Maybe this is "needed" so that you may always 
> take the address of such const static members.
> 
> So the compiler is free to use the constant as if they were variables, 
> if it needs to.  Your code compiles OK if the line
> 
>         int offset = (redundant ? B : A);
> 
> is replaced by
> 
>         if(redundant)
>           offset = B;
>         else
>           offset = A;
> 
> I don't know why, but it does work here.

This seems like a definite bug. The fact that it works in 3.4.2 and not in
3.3.3 seems like a probable bug to me, but I will ask this question in a
standard C++ newsgroup so that someone intimately familiar with the standard
can give me a definitive answer, but I still think g++ 3.3 is wrong and g++
3.4 is right.

If I were taking the address of the constant, sure, it would have to have
storage space and I wouldn't expect it any other way.

I was looking at the assembly generated by each compiler. There is a
striking difference. Here is foo::method(bool redundant) in x86 assembly
generated by mingw/g++ 3.4.2. I have commented the relevant sections.

-----------------------------------------------
.globl __ZNK3foo6methodEb
	.def	__ZNK3foo6methodEb;	.scl	2;	.type	32;
.endef
__ZNK3foo6methodEb:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$40, %esp
	movl	12(%ebp), %eax
	movb	%al, -1(%ebp)    ; move redundant (%al) to stack
	cmpb	$0, -1(%ebp)     ; if redundant is false 
	je	L12              ; goto L12
	movl	$8184, -16(%ebp) ; move 8184 (0x1FF8) into -16(%ebp) (aka
offset)
	jmp	L13              ; goto L13
L12:
	movl	$8, -16(%ebp)    ; move 8 into offset
L13:
	movl	-16(%ebp), %eax  ; return std::pair blah blah blah
	movl	%eax, -8(%ebp)
	movl	8(%ebp), %eax
	addl	-8(%ebp), %eax
	incl	%eax
	movzbl	(%eax), %eax
	movb	%al, -11(%ebp)
	leal	-11(%ebp), %eax
	movl	%eax, 8(%esp)
	movl	8(%ebp), %edx
	movl	-8(%ebp), %eax
	movzbl	(%eax,%edx), %eax
	movb	%al, -12(%ebp)
	leal	-12(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	-10(%ebp), %eax
	movl	%eax, (%esp)
	call	__ZNSt4pairIhhEC1ERKhS2_
	movzwl	-10(%ebp), %eax
	leave
	ret
-----------------------------------------------

And here is g++ 3.3.3's assembly output. As you can see, it's not even
trying to use it as a constant. This is why storage space is required.

-----------------------------------------------
_ZNK3foo6methodEb:
.LFB1535:
	pushl	%ebp
.LCFI14:
	movl	%esp, %ebp
.LCFI15:
	subl	$24, %esp
.LCFI16:
	movl	16(%ebp), %eax
	movb	%al, -1(%ebp)    ; move al (redundant) to stack
	cmpb	$0, -1(%ebp)     ; is redundant false?
	je	.L6              ; then jump to .L6
	movl	_ZN3foo1BE, %eax ; move B (storage space required) to eax
	movl	%eax, -16(%ebp)  ; put eax on the stack
	jmp	.L7
.L6:
	movl	_ZN3foo1AE, %eax ; move A (storage space required) to eax
	movl	%eax, -16(%ebp)  ; and put eax on the stack
.L7:
	movl	-16(%ebp), %eax  ; ??? why is it moving it just to move it
back?
	movl	%eax, -8(%ebp)   ; whatever, the rest is return std::pair
blah blah
	subl	$4, %esp
	movl	12(%ebp), %eax
	addl	-8(%ebp), %eax
	incl	%eax
	movb	(%eax), %al
	movb	%al, -9(%ebp)
	leal	-9(%ebp), %eax
	pushl	%eax
	movl	12(%ebp), %edx
	movl	-8(%ebp), %eax
	movb	(%eax,%edx), %al
	movb	%al, -10(%ebp)
	leal	-10(%ebp), %eax
	pushl	%eax
	pushl	8(%ebp)
.LCFI17:
	call	_ZNSt4pairIhhEC1ERKhS2_
	addl	$16, %esp
	movl	8(%ebp), %eax
	leave
	ret	$4
-----------------------------------------------

If you replace the ternary operator with the if as you suggested, the
assembly looks more like the 3.4.2 version. This is why it compiles, and
makes it seem more and more like a bug. Clearly it's capable of doing what I
think it should do, but chooses not to when presented with the ternary
operator.

> 
> So you need to define those constants somewhere, but the compiler  may 
> use the initializer in the class scope, if it is able to do so.  For 
> some reason, GCC couldn't use the initializer in the first case, so it 
> is using the address of the constants.  Go figure.

The assembly output and changing from ternary to if proves it can use the
initializer, but chooses not to.

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
       [not found]     ` <4352a3b2.42389977.3b5e.60fdSMTPIN_ADDED@mx.gmail.com>
@ 2005-10-16 19:29       ` Alex J. Dam
  2005-10-16 19:53         ` John Ratliff
  2005-10-16 19:53         ` John Ratliff
  0 siblings, 2 replies; 29+ messages in thread
From: Alex J. Dam @ 2005-10-16 19:29 UTC (permalink / raw)
  To: John Ratliff; +Cc: gcc-help

Hello.

On Sun, Oct 16, 2005 at 02:02:09PM -0500, John Ratliff wrote:
> This seems like a definite bug. The fact that it works in 3.4.2 and not in
> 3.3.3 seems like a probable bug to me, but I will ask this question in a
> standard C++ newsgroup so that someone intimately familiar with the standard
> can give me a definitive answer, but I still think g++ 3.3 is wrong and g++
> 3.4 is right.
> 
> If I were taking the address of the constant, sure, it would have to have
> storage space and I wouldn't expect it any other way.
> 

I agree in that this is a weird behaviour, but I don't think it's
exactly a bug, unless it is mandatory for a compiler to try
everything possible before taking the address of a constant.  Maybe
GCC 3.3 simply couldn't find a way to use the constants directly.

-- 
Alex J. Dam

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
       [not found] ` <43528310.03f34613.6a05.0e40SMTPIN_ADDED@mx.gmail.com>
@ 2005-10-16 17:43   ` Alex J. Dam
       [not found]     ` <4352a3b2.42389977.3b5e.60fdSMTPIN_ADDED@mx.gmail.com>
                       ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: Alex J. Dam @ 2005-10-16 17:43 UTC (permalink / raw)
  To: gcc-help

On Sun, Oct 16, 2005 at 11:42:48AM -0500, John Ratliff wrote:
> I don't see anywhere that I'm taking the address of A or B. I don't see why
> they should need storage space here. Am I doing something wrong in my
> program?

After reading Ryan's post, I looked at the (draft) standard.  It says:

4 If  a  static  data  member  is of const integral or const enumeration
  type, its declaration in the class definition can specify a  constant-
  initializer   which   shall   be   an   integral  constant  expression
  (_expr.const_).  In that case, the member can appear in integral  con-
  stant expressions within its scope.  The member shall still be defined
  in a namespace scope if it is used in the program  and  the  namespace
  scope definition shall not contain an initializer.

If I understand this correctly, even const static members need to have
a definition somewhere.  Maybe this is "needed" so that you may always
take the address of such const static members.

So the compiler is free to use the constant as if they were variables,
if it needs to.  Your code compiles OK if the line

        int offset = (redundant ? B : A);

is replaced by

        if(redundant)
          offset = B;
        else
          offset = A;

I don't know why, but it does work here.

So you need to define those constants somewhere, but the compiler  may
use the initializer in the class scope, if it is able to do so.  For
some reason, GCC couldn't use the initializer in the first case, so it
is using the address of the constants.  Go figure.

-- 
Alex J. Dam

^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 15:26 Ryan Mansfield
                   ` (2 preceding siblings ...)
  2005-10-16 16:42 ` John Ratliff
@ 2005-10-16 16:42 ` John Ratliff
       [not found] ` <43528310.03f34613.6a05.0e40SMTPIN_ADDED@mx.gmail.com>
  4 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 16:42 UTC (permalink / raw)
  To: gcc-help

I am replying to the wrong message. Sorry, I was not subscribed until just
now and don't have the correct one to reply to. I'll quote it from the web
mailing archive.

>> On Sun, Oct 16, 2005 at 02:35:52AM -0500, John Ratliff wrote:
>> class foo {
>> public:
>>   static const int X = 5;
>>   static const int Y = 10;
>>   static const int Z = 15;
>> };
>> 
>> However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
>> but I think it's 3.3.5), the linker would complain about unresolved
>> symbols.

>I compiled a simple code using such constants here with no problems
>using GCC 3.3.4 and 3.4.3.

Sorry. I should know better than to post a useless example.

>> If I were to define the static variable in my implementation file, the
>> linker would find the variables and go on its merry way. In other words,
>> I could solve the problem by doing this:
>> 
>> const int foo::X;
>> const int foo::Y;
>> const int foo::Z;

>This is usually only needed when, e. g., you take the address of a
>constant:

>const int *x = &foo::X;

>Do you have a minimal sample which does not work?

I do now.

#include <iostream>
#include <utility>

class foo {
private:
    char sram[0x2000];
    
public:
    static const int A = 0x8;
    static const int B = 0x1FF8;
    
    foo() {
        sram[8] = 1;
        sram[9] = 2;
        sram[0x1FF8] = 3;
        sram[0x1FF9] = 4;
    }
    
    std::pair<unsigned char, unsigned char> method(bool redundant) const {
        int offset = (redundant ? B : A);
        
        return std::pair<unsigned char,
                         unsigned char>(sram[offset], sram[offset + 1]);
    }
};

int main(int, char **) {
    foo f;
    std::pair<unsigned char, unsigned char> p1(f.method(false));
    std::pair<unsigned char, unsigned char> p2(f.method(true));
    
    std::cout << "p1 = (" << (int)p1.first << "," 
        << (int)p1.second << ")\n";
    std::cout << "p2 = (" << (int)p2.first << ","
        << (int)p2.second << ")\n";
    
    return 0;
}

Compiles and links just fine under mingw/g++ 3.4.2 and not at all under
Linux g++/3.3.3. I compiled the test example under SourceForge's compile
farm linux host 2 (I think they run Fedora Core 4)

The non-working g++ gives this for g++ --version
----------------------------------------------------
g++ (GCC) 3.3.3 20040412 (Red Hat Linux 3.3.3-7)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------

When I do

$ g++ -W -Wall temp.cc 
/tmp/ccSsK02S.o(.gnu.linkonce.t._ZNK3foo6methodEb+0x13): In function
`foo::method(bool) const':
: undefined reference to `foo::B'
/tmp/ccSsK02S.o(.gnu.linkonce.t._ZNK3foo6methodEb+0x1d): In function
`foo::method(bool) const':
: undefined reference to `foo::A'
collect2: ld returned 1 exit status

----------------------------------------------------
$ g++ --version
g++.exe (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------

For my working mingw/g++.

I don't see anywhere that I'm taking the address of A or B. I don't see why
they should need storage space here. Am I doing something wrong in my
program?

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 15:26 Ryan Mansfield
  2005-10-16 16:16 ` John Ratliff
  2005-10-16 16:16 ` John Ratliff
@ 2005-10-16 16:42 ` John Ratliff
  2005-10-16 16:42 ` John Ratliff
       [not found] ` <43528310.03f34613.6a05.0e40SMTPIN_ADDED@mx.gmail.com>
  4 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 16:42 UTC (permalink / raw)
  To: gcc-help

I am replying to the wrong message. Sorry, I was not subscribed until just
now and don't have the correct one to reply to. I'll quote it from the web
mailing archive.

>> On Sun, Oct 16, 2005 at 02:35:52AM -0500, John Ratliff wrote:
>> class foo {
>> public:
>>   static const int X = 5;
>>   static const int Y = 10;
>>   static const int Z = 15;
>> };
>> 
>> However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
>> but I think it's 3.3.5), the linker would complain about unresolved
>> symbols.

>I compiled a simple code using such constants here with no problems
>using GCC 3.3.4 and 3.4.3.

Sorry. I should know better than to post a useless example.

>> If I were to define the static variable in my implementation file, the
>> linker would find the variables and go on its merry way. In other words,
>> I could solve the problem by doing this:
>> 
>> const int foo::X;
>> const int foo::Y;
>> const int foo::Z;

>This is usually only needed when, e. g., you take the address of a
>constant:

>const int *x = &foo::X;

>Do you have a minimal sample which does not work?

I do now.

#include <iostream>
#include <utility>

class foo {
private:
    char sram[0x2000];
    
public:
    static const int A = 0x8;
    static const int B = 0x1FF8;
    
    foo() {
        sram[8] = 1;
        sram[9] = 2;
        sram[0x1FF8] = 3;
        sram[0x1FF9] = 4;
    }
    
    std::pair<unsigned char, unsigned char> method(bool redundant) const {
        int offset = (redundant ? B : A);
        
        return std::pair<unsigned char,
                         unsigned char>(sram[offset], sram[offset + 1]);
    }
};

int main(int, char **) {
    foo f;
    std::pair<unsigned char, unsigned char> p1(f.method(false));
    std::pair<unsigned char, unsigned char> p2(f.method(true));
    
    std::cout << "p1 = (" << (int)p1.first << "," 
        << (int)p1.second << ")\n";
    std::cout << "p2 = (" << (int)p2.first << ","
        << (int)p2.second << ")\n";
    
    return 0;
}

Compiles and links just fine under mingw/g++ 3.4.2 and not at all under
Linux g++/3.3.3. I compiled the test example under SourceForge's compile
farm linux host 2 (I think they run Fedora Core 4)

The non-working g++ gives this for g++ --version
----------------------------------------------------
g++ (GCC) 3.3.3 20040412 (Red Hat Linux 3.3.3-7)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------

When I do

$ g++ -W -Wall temp.cc 
/tmp/ccSsK02S.o(.gnu.linkonce.t._ZNK3foo6methodEb+0x13): In function
`foo::method(bool) const':
: undefined reference to `foo::B'
/tmp/ccSsK02S.o(.gnu.linkonce.t._ZNK3foo6methodEb+0x1d): In function
`foo::method(bool) const':
: undefined reference to `foo::A'
collect2: ld returned 1 exit status

----------------------------------------------------
$ g++ --version
g++.exe (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------

For my working mingw/g++.

I don't see anywhere that I'm taking the address of A or B. I don't see why
they should need storage space here. Am I doing something wrong in my
program?

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 15:26 Ryan Mansfield
  2005-10-16 16:16 ` John Ratliff
@ 2005-10-16 16:16 ` John Ratliff
  2005-10-16 16:42 ` John Ratliff
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 16:16 UTC (permalink / raw)
  To: gcc-help

> A few days ago, I was writing a program that had some constants. They were
> all defined in a class and were static constant integers, something like
> 
> class foo {
> public:
>   static const int X = 5;
>   static const int Y = 10;
>   static const int Z = 15;
> };
> 
> When I would compile my program in Windows XP with mingw g++ 3.4.2, I
> would
> have no problems.
> 
> However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
> but I think it's 3.3.5), the linker would complain about unresolved
> symbols.
> 
> If I were to define the static variable in my implementation file, the
> linker would find the variables and go on its merry way. In other words, I
> could solve the problem by doing this:
> 
> const int foo::X;
> const int foo::Y;
> const int foo::Z;
> 
> I didn't even need to declare a value here. It took the value from the
> class-def.
> 
> Is this correct behavior? I thought static constant integers could be
> defined completely within the class, because they are simply type-safe
> constants that need no storage space. It seems like it might have been
> wrong
> since in Windows I had g++ 3.4.2 and in Linux I had g++ 3.3.5, but I
> wasn't
> sure.
> 
> In Bruce Eckel's "Thinking in C++", he states that "In older versions of
> C++, static const was not supported inside classes." I don't generally
> think
> of g++ 3.3.x as an old compiler, but maybe it is just old enough not to
> support this?
> 
> Thanks,
> 
> --John Ratliff
>

> -----Original Message-----
> From: Ryan Mansfield [mailto:RMansfield@qnx.com]
> Sent: Sunday, October 16, 2005 10:26 AM
> To: 'John Ratliff'; gcc-help@gcc.gnu.org
> Subject: RE: C++ static integer class constants...
> 
> Yes, it is required that static data members must be defined in exactly
> one
> translation unit.
> 
> Please see:
> 
> http://gcc.gnu.org/onlinedocs/gcc/Static-Definitions.html#Static-
> Definitions
> 
> http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.11
> 
> Regards,
> 
> Ryan Mansfield

I am asking if static CONSTANTS are different than static member variables.
My understanding of a static constant is that it is like a type-safe local
define. It solves the major problems of #define for creating constants. They
should not need storage space.

And if I am wrong, and they do, then why do they only need storage space for
g++ <= 3.3.5 and not g++ 3.4.2? Is it just an optimization? g++ 3.4.2 never
needed storage space declared, even when I passed -O0 to it. g++ 3.3.5 only
needed storage for 2 of my 8 constants regardless of whether -O0 or -O2 was
used.

This is an example from Bruce Eckel's Thinking in C++ Volume 1. Why does
this program not need to declare storage space for StringStack::size? Is
Bruce Eckel wrong?

-----------------------------------------------
//: C08:StringStack.cpp
// Using static const to create a 
// compile-time constant inside a class
#include <string>
#include <iostream>
using namespace std;

class StringStack {
  static const int size = 100;
  const string* stack[size];
  int index;
public:
  StringStack();
  void push(const string* s);
  const string* pop();
};

StringStack::StringStack() : index(0) {
  memset(stack, 0, size * sizeof(string*));
}

void StringStack::push(const string* s) {
  if(index < size)
    stack[index++] = s;
}

const string* StringStack::pop() {
  if(index > 0) {
    const string* rv = stack[--index];
    stack[index] = 0;
    return rv;
  }
  return 0;
}

string iceCream[] = {
  "pralines & cream",
  "fudge ripple",
  "jamocha almond fudge",
  "wild mountain blackberry",
  "raspberry sorbet",
  "lemon swirl",
  "rocky road",
  "deep chocolate fudge"
};

const int iCsz = 
  sizeof iceCream / sizeof *iceCream;

int main() {
  StringStack ss;
  for(int i = 0; i < iCsz; i++)
    ss.push(&iceCream[i]);
  const string* cp;
  while((cp = ss.pop()) != 0)
    cout << *cp << endl;
} ///:~
-----------------------------------------------



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
  2005-10-16 15:26 Ryan Mansfield
@ 2005-10-16 16:16 ` John Ratliff
  2005-10-16 16:16 ` John Ratliff
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16 16:16 UTC (permalink / raw)
  To: gcc-help

> A few days ago, I was writing a program that had some constants. They were
> all defined in a class and were static constant integers, something like
> 
> class foo {
> public:
>   static const int X = 5;
>   static const int Y = 10;
>   static const int Z = 15;
> };
> 
> When I would compile my program in Windows XP with mingw g++ 3.4.2, I
> would
> have no problems.
> 
> However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
> but I think it's 3.3.5), the linker would complain about unresolved
> symbols.
> 
> If I were to define the static variable in my implementation file, the
> linker would find the variables and go on its merry way. In other words, I
> could solve the problem by doing this:
> 
> const int foo::X;
> const int foo::Y;
> const int foo::Z;
> 
> I didn't even need to declare a value here. It took the value from the
> class-def.
> 
> Is this correct behavior? I thought static constant integers could be
> defined completely within the class, because they are simply type-safe
> constants that need no storage space. It seems like it might have been
> wrong
> since in Windows I had g++ 3.4.2 and in Linux I had g++ 3.3.5, but I
> wasn't
> sure.
> 
> In Bruce Eckel's "Thinking in C++", he states that "In older versions of
> C++, static const was not supported inside classes." I don't generally
> think
> of g++ 3.3.x as an old compiler, but maybe it is just old enough not to
> support this?
> 
> Thanks,
> 
> --John Ratliff
>

> -----Original Message-----
> From: Ryan Mansfield [mailto:RMansfield@qnx.com]
> Sent: Sunday, October 16, 2005 10:26 AM
> To: 'John Ratliff'; gcc-help@gcc.gnu.org
> Subject: RE: C++ static integer class constants...
> 
> Yes, it is required that static data members must be defined in exactly
> one
> translation unit.
> 
> Please see:
> 
> http://gcc.gnu.org/onlinedocs/gcc/Static-Definitions.html#Static-
> Definitions
> 
> http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.11
> 
> Regards,
> 
> Ryan Mansfield

I am asking if static CONSTANTS are different than static member variables.
My understanding of a static constant is that it is like a type-safe local
define. It solves the major problems of #define for creating constants. They
should not need storage space.

And if I am wrong, and they do, then why do they only need storage space for
g++ <= 3.3.5 and not g++ 3.4.2? Is it just an optimization? g++ 3.4.2 never
needed storage space declared, even when I passed -O0 to it. g++ 3.3.5 only
needed storage for 2 of my 8 constants regardless of whether -O0 or -O2 was
used.

This is an example from Bruce Eckel's Thinking in C++ Volume 1. Why does
this program not need to declare storage space for StringStack::size? Is
Bruce Eckel wrong?

-----------------------------------------------
//: C08:StringStack.cpp
// Using static const to create a 
// compile-time constant inside a class
#include <string>
#include <iostream>
using namespace std;

class StringStack {
  static const int size = 100;
  const string* stack[size];
  int index;
public:
  StringStack();
  void push(const string* s);
  const string* pop();
};

StringStack::StringStack() : index(0) {
  memset(stack, 0, size * sizeof(string*));
}

void StringStack::push(const string* s) {
  if(index < size)
    stack[index++] = s;
}

const string* StringStack::pop() {
  if(index > 0) {
    const string* rv = stack[--index];
    stack[index] = 0;
    return rv;
  }
  return 0;
}

string iceCream[] = {
  "pralines & cream",
  "fudge ripple",
  "jamocha almond fudge",
  "wild mountain blackberry",
  "raspberry sorbet",
  "lemon swirl",
  "rocky road",
  "deep chocolate fudge"
};

const int iCsz = 
  sizeof iceCream / sizeof *iceCream;

int main() {
  StringStack ss;
  for(int i = 0; i < iCsz; i++)
    ss.push(&iceCream[i]);
  const string* cp;
  while((cp = ss.pop()) != 0)
    cout << *cp << endl;
} ///:~
-----------------------------------------------



^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: C++ static integer class constants...
@ 2005-10-16 15:26 Ryan Mansfield
  2005-10-16 16:16 ` John Ratliff
                   ` (4 more replies)
  0 siblings, 5 replies; 29+ messages in thread
From: Ryan Mansfield @ 2005-10-16 15:26 UTC (permalink / raw)
  To: 'John Ratliff', gcc-help

Yes, it is required that static data members must be defined in exactly one
translation unit.

Please see:

http://gcc.gnu.org/onlinedocs/gcc/Static-Definitions.html#Static-Definitions

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.11

Regards,

Ryan Mansfield


-----Original Message-----
From: gcc-help-owner@gcc.gnu.org [mailto:gcc-help-owner@gcc.gnu.org] On
Behalf Of John Ratliff
Sent: Sunday, October 16, 2005 3:36 AM
To: gcc-help@gcc.gnu.org
Subject: C++ static integer class constants...

A few days ago, I was writing a program that had some constants. They were
all defined in a class and were static constant integers, something like

class foo {
public:
  static const int X = 5;
  static const int Y = 10;
  static const int Z = 15;
};

When I would compile my program in Windows XP with mingw g++ 3.4.2, I would
have no problems.

However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
but I think it's 3.3.5), the linker would complain about unresolved symbols.

If I were to define the static variable in my implementation file, the
linker would find the variables and go on its merry way. In other words, I
could solve the problem by doing this:

const int foo::X;
const int foo::Y;
const int foo::Z;

I didn't even need to declare a value here. It took the value from the
class-def.

Is this correct behavior? I thought static constant integers could be
defined completely within the class, because they are simply type-safe
constants that need no storage space. It seems like it might have been wrong
since in Windows I had g++ 3.4.2 and in Linux I had g++ 3.3.5, but I wasn't
sure.

In Bruce Eckel's "Thinking in C++", he states that "In older versions of
C++, static const was not supported inside classes." I don't generally think
of g++ 3.3.x as an old compiler, but maybe it is just old enough not to
support this?

Thanks,

--John Ratliff


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: C++ static integer class constants...
       [not found] <435202e6.3d759d8f.4550.fffff1e6SMTPIN_ADDED@mx.gmail.com>
@ 2005-10-16 14:50 ` Alex J. Dam
  2005-10-17 19:13   ` Florian Weimer
  0 siblings, 1 reply; 29+ messages in thread
From: Alex J. Dam @ 2005-10-16 14:50 UTC (permalink / raw)
  To: gcc-help

Hello.

On Sun, Oct 16, 2005 at 02:35:52AM -0500, John Ratliff wrote:
> class foo {
> public:
>   static const int X = 5;
>   static const int Y = 10;
>   static const int Z = 15;
> };
> 
> However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
> but I think it's 3.3.5), the linker would complain about unresolved
> symbols.

I compiled a simple code using such constants here with no problems
using GCC 3.3.4 and 3.4.3.

> If I were to define the static variable in my implementation file, the
> linker would find the variables and go on its merry way. In other words, I
> could solve the problem by doing this:
> 
> const int foo::X;
> const int foo::Y;
> const int foo::Z;

This is usually only needed when, e. g., you take the address of a
constant:

const int *x = &foo::X;

Do you have a minimal sample which does not work?

-- 
Alex. J. Dam

^ permalink raw reply	[flat|nested] 29+ messages in thread

* C++ static integer class constants...
@ 2005-10-16  7:35 John Ratliff
  0 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16  7:35 UTC (permalink / raw)
  To: gcc-help

A few days ago, I was writing a program that had some constants. They were
all defined in a class and were static constant integers, something like

class foo {
public:
  static const int X = 5;
  static const int Y = 10;
  static const int Z = 15;
};

When I would compile my program in Windows XP with mingw g++ 3.4.2, I would
have no problems.

However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
but I think it's 3.3.5), the linker would complain about unresolved symbols.

If I were to define the static variable in my implementation file, the
linker would find the variables and go on its merry way. In other words, I
could solve the problem by doing this:

const int foo::X;
const int foo::Y;
const int foo::Z;

I didn't even need to declare a value here. It took the value from the
class-def.

Is this correct behavior? I thought static constant integers could be
defined completely within the class, because they are simply type-safe
constants that need no storage space. It seems like it might have been wrong
since in Windows I had g++ 3.4.2 and in Linux I had g++ 3.3.5, but I wasn't
sure.

In Bruce Eckel's "Thinking in C++", he states that "In older versions of
C++, static const was not supported inside classes." I don't generally think
of g++ 3.3.x as an old compiler, but maybe it is just old enough not to
support this?

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

* C++ static integer class constants...
@ 2005-10-16  7:35 John Ratliff
  0 siblings, 0 replies; 29+ messages in thread
From: John Ratliff @ 2005-10-16  7:35 UTC (permalink / raw)
  To: gcc-help

A few days ago, I was writing a program that had some constants. They were
all defined in a class and were static constant integers, something like

class foo {
public:
  static const int X = 5;
  static const int Y = 10;
  static const int Z = 15;
};

When I would compile my program in Windows XP with mingw g++ 3.4.2, I would
have no problems.

However, when I went to Linux, where I have g++ 3.3.5 (or possibly 3.3.6,
but I think it's 3.3.5), the linker would complain about unresolved symbols.

If I were to define the static variable in my implementation file, the
linker would find the variables and go on its merry way. In other words, I
could solve the problem by doing this:

const int foo::X;
const int foo::Y;
const int foo::Z;

I didn't even need to declare a value here. It took the value from the
class-def.

Is this correct behavior? I thought static constant integers could be
defined completely within the class, because they are simply type-safe
constants that need no storage space. It seems like it might have been wrong
since in Windows I had g++ 3.4.2 and in Linux I had g++ 3.3.5, but I wasn't
sure.

In Bruce Eckel's "Thinking in C++", he states that "In older versions of
C++, static const was not supported inside classes." I don't generally think
of g++ 3.3.x as an old compiler, but maybe it is just old enough not to
support this?

Thanks,

--John Ratliff



^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2005-10-18 12:26 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <87oe5pb5dp.fsf@totally-fudged-out-message-id>
2005-10-17 19:17 ` C++ static integer class constants Florian Weimer
2005-10-18  6:19   ` John Ratliff
2005-10-18  6:19   ` John Ratliff
     [not found] <0IOJ0024ULK8BF@emroute1.cind.ornl.gov>
2005-10-18 12:26 ` Ernest L. Williams Jr.
     [not found] <200510160743.j9G7hVoa010304@inbound-smtp-1.corp.adobe.com>
2005-10-17 12:05 ` John Love-Jensen
2005-10-17 17:50   ` John Ratliff
2005-10-17 17:50   ` John Ratliff
     [not found]   ` <4353e481.0829b6d6.64bd.18a4SMTPIN_ADDED@mx.gmail.com>
2005-10-17 18:07     ` corey taylor
2005-10-17 20:04       ` John Ratliff
2005-10-17 20:04       ` John Ratliff
     [not found] <20051016195314.7EFB824AEF5@lax-gw02.mroute.net>
2005-10-17  9:09 ` Nathan Sidwell
2005-10-17 19:21   ` Florian Weimer
     [not found] <20051016200125.C061F13137C@arvo.suso.org>
2005-10-16 21:36 ` John Ratliff
2005-10-16 21:36 ` John Ratliff
2005-10-16 15:26 Ryan Mansfield
2005-10-16 16:16 ` John Ratliff
2005-10-16 16:16 ` John Ratliff
2005-10-16 16:42 ` John Ratliff
2005-10-16 16:42 ` John Ratliff
     [not found] ` <43528310.03f34613.6a05.0e40SMTPIN_ADDED@mx.gmail.com>
2005-10-16 17:43   ` Alex J. Dam
     [not found]     ` <4352a3b2.42389977.3b5e.60fdSMTPIN_ADDED@mx.gmail.com>
2005-10-16 19:29       ` Alex J. Dam
2005-10-16 19:53         ` John Ratliff
2005-10-16 19:53         ` John Ratliff
2005-10-16 19:45     ` John Ratliff
2005-10-16 19:45     ` John Ratliff
     [not found] <435202e6.3d759d8f.4550.fffff1e6SMTPIN_ADDED@mx.gmail.com>
2005-10-16 14:50 ` Alex J. Dam
2005-10-17 19:13   ` Florian Weimer
  -- strict thread matches above, loose matches on Subject: below --
2005-10-16  7:35 John Ratliff
2005-10-16  7:35 John Ratliff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).