6

Should we define a static const member outside of the class definition even if it is initialised inside the class?

#include<iostream>  
using namespace std;  
class abc  
{  
    static const int period=5;  
    int arr[period];  
  public:  
    void display()   
    {   
        cout<<period<<endl;  
    }  
};

const int abc::period;   

int main()   
{   
    abc a;  
    a.display();   
    return 0;  
}

After commenting // const int abc::period;, both versions of the code run fine on gcc 4.3.4. So I want to ask why do both versions work and which one is standard compliant?

1 Answer 1

8

You are defining the static memberperiod by writing const int abc::period;. You are allowed to provide an in class initializer for static const member of a class but that's not definition, but that's merely a declaration.

9.4.2/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 (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.

Your code compiles even without the definition because you are not taking the address of the static member. Bjarne Stroustrup mentions in the C++-FAQ here that You can take the address of a static member if (and only if) it has an out-of-class definition

8
  • 1
    @David : I tried to search for the word use in the Standard. Unfortunately couldn't find the relevant text at the time of this post. Commented May 24, 2011 at 7:33
  • 1
    :) I tried also some time ago, and didn't find any single clear definition in C++03 that I can post, but use as an lvalue where an lvalue to rvalue conversion is no immediately performed is a slightly better approximation. For a case where this definition applies and taking the address doesn't: (cond?static_const:XXX), with cond being a condition, static_const being a, well, static constant in a class. If XXX is an rvalue it does not constitute use. static_const is an rvalue but immediately converted to lvalue. If XXX is an lvalue, then that constitutes use. No address taken. Commented May 24, 2011 at 7:48
  • 1
    Example: struct test { static const int s = 1; }; int main( int argc, char** ) { const int y = ( argc < test::s? argc : test::s); } The first use of test::s does not constitute use: argc < test::s, the constant is an lvalue, but a immediate conversion to rvalue (it's value), is performed. On the other hand, the ...: test::s ) does constitute use. The ternary expression can be understood as (pseudo code): const int* __p; if ( argc<test::s ) __p = &argc; else __p = &test::s; *__p;. Commented May 24, 2011 at 7:55
  • 1
    If the expression is changed to ( argc < test::s? argc : test+0 ), then in both subexpressions, there is an immediate conversion to rvalue, and they don't constitute use. The equivalent pseudo code would be: int __i; if ( argc < test::s ) __i = argc; else __i = test+0; __i; Commented May 24, 2011 at 7:57
  • 1
    @David : Nicely summarized! :-) Commented May 24, 2011 at 7:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.