views:

467

answers:

9

In VC++ when I need to specify an array bound for a class member variable I do it this way:

 class Class {

 private:
     static const int numberOfColors = 16;
     COLORREF colors[numberOfColors];
 };

(please don't tell me about using std::vector here)

This way I have a constant that can be used as an array bound and later in the class code to specify loop-statement constraints and at the same time it is not visible anywhere else.

The question is whether this usage of static const int member variables only allowed by VC++ or is it typically allowed by other widespread compilers?

+1  A: 

I've stopped bothering about the portability of that years ago. There are perhaps still compilers which don't support it, but I haven't met any of them recently.

AProgrammer
+13  A: 

That behavior is valid according to the C++ Standard. Any recent compiler should support it.

A. L. Flanagan
+4  A: 

This has been standard C++ for more than a decade now. It's even supported by VC -- what more could you want? (@Neil: What about SunCC? :^>)

sbi
+5  A: 

I believe that Visual Studio 2005 and beyond supports it. The XCode C++ compiler as well (this is gcc actually).

If you want to be safe you could always use the old enum hack that I learned from Effective C++. It goes like this:

class Class {

 private:
     enum {
        numberOfColors = 16
     };
     COLORREF colors[numberOfColors];
 };

Hope this helps.

StackedCrooked
Even VS 2k3 supports it.
sharptooth
The enum 'hack' shouldn't be necessary if you're dealing with C++ code, but if you want the declaration to work in C or in VC++6, this is better than the more common method of using #define in my opinion.
Michael Burr
+1  A: 

I'm pretty sure that this will also work with gcc and Solaris, but I can't verify this at the moment.

In the future you could extend the idea like this:

template<int size>
class Class {
private:
    COLORREF colors[size];
};

and use it like this:

Class<5> c;

so that you are not limited to exactly one buffer size in your application.

quamrana
You are using a magic number, which is what the question was trying to avoid.
anon
@Neil: However, the magic number 5 above could be replaced by a `static const int` from a class that 'c' might find itself a member of.
quamrana
A: 

It is possible to answer questions like this by referencing the ISO C++ speicifcation but the spec is hard for people to get and harder to read. I think the simplest answer hinges on two things:

  • Microsoft Visual Studio 2005 and up is a relatively conformant C++ implementation. If it allows you to do something, chances are its standard.
  • Download something like Code::Blocks to get a GCC compiler to try stuff out. If it works in MS and GCC, chances really are, its standard.
Chris Becke
The spec is very easy to get (for $30): http://stackoverflow.com/questions/81656/where-do-i-find-the-current-x-standard/83763#83763 Reading the spec is a different story, but serious C++ prgrammers should probably still refer to it from time to time: http://stackoverflow.com/questions/1123455/should-every-c-programmer-read-the-iso-standard-to-become-professional
Michael Burr
+11  A: 

This is valid C++ and most (all?) reasonably modern compilers support it. If you are using boost, you can get portable support for this feature in the form of BOOST_STATIC_CONSTANT macro:

class Class {
 private:
     BOOST_STATIC_CONSTANT(int, numberOfColors = 16);
     COLORREF colors[numberOfColors];
 };

The macro is expanded to static const int numberOfColors = 16 if the compiler supports this, otherwise it resorts to enum { numberOfColors=16 };.

Bojan Resnik
+2  A: 

Besides other answers you can use following function do determine number of elements in statically alocated arrays:

template<typename T, size_t length>
size_t arrayLength(T (&a)[length])
{
    return length;
}
n0rd
+2  A: 

Yes, it's 100% legal and should be portable. The C++ standard says this in 5.19 - Constant expressions" (emphasis mine):

In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case-expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

constant-expression:
    conditional-expression

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions.

That said, it appears that VC6 doesn't support it. See StackedCrooked's answer for a good workaround. In fact, I generally prefer the enum method StackedCrooked mentions for this type of thing.

As an FYI, the "static const" technique works in VC9, GCC 3.4.5 (MinGW), Comeau and Digital Mars.

And don't forget that if you use a "`static const'" member, you'll need a definition for it in addition to the declaration strictly speaking. However, virtually all compilers will let you get away with skipping the definition in this case.

Michael Burr