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.