There's an exception to that rule for const static
members that:
- Are of integer or enumeration type (pointers, references, floats need not apply)
- Never have their address taken or get bound to a reference
For static constexpr
members, the type restriction is dropped (or, replaced with those of constexpr
), and there must be an initializer at the in-class declaration.
In either case, the declaration is not considered to be a definition, despite having an initializer, so the object doesn't get an address until it's declared (hence defined) outside the class. For members of a template, that may be done in every translation unit (TU), for members of a non-template class it must be done in only one TU.
Although your example does compile, the practice isn't generally scalable because such variables can't be passed to generic pass-by-reference functions, including perfect forwarding. The book's advice is good.
Standard reference: [class.static.data] §9.4.2/3.