In-class static const member initialization and LNK2005 RRS feed

  • Question

  • Hello everybody,

    Recently I ran into following issue with MSVC linker:

    C++ Standard, Sec. 9.4.2 paragraph 4 says:
    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 name-space scope if it is used in the program and the namespace scope definition shall not contain an initializer.

    So I created following project:


    #ifndef TEST_H
    #define TEST_H
    class Test
        static const int s = 13;

    #include "Test.h"

    int Test::s;

    #include "Test.h"
    int function(const int& a) {
        return Test::s + a;

    #include <iostream> 
    #include "Test.h"
    using namespace std; 
    int function (const int&);
    main() { cout << Test::s << ' ' << function(Test::s) << '\n'; }

    When building this project, all is compiled succesfully, but linker is unhappy with:

    another.obj : error LNK2005: "public: static int const Test::s" (?s@Test@@2HB) already defined in Test.obj
    main.obj : error LNK2005: "public: static int const Test::s" (?s@Test@@2HB) already defined in Test.obj
    e:\path\prog.exe : fatal error LNK1169: one or more multiply defined symbols found

    Except for the code to be completely pointless - it is just for illustration purposes - is there anything wrong with it in terms of C++ language? Problem seems to occur only when I have some static const fields with in-class initializer AND namespace-scope definition. function takes its parameter by const reference to utilize "used elsewhere in program" words mentioned by Standard, as opposed to just "used in constant epression" - so it requires namespace scope definition of static field. At least I think so. Anyway, even with parameter passed by value, problem seems to persist. Removing namespace-scope definition makes MSVC linker happy, but it makes my program ill-formed when I want this field to be "used in program" in any other way than in constant expression (like, let's say, want to have its address taken). Removing in-class initializer and initializing field in namespace scope also fixes things, and it can be used as a workaround. But my question is: does MSVC linker do not get what Standard says correctly, or I am missing something?

    MSVC version used: Microsoft Visual C++ 2008 Express Edition.
    • Edited by Hobson Wednesday, February 10, 2010 10:11 PM code firmatting
    Wednesday, February 10, 2010 9:28 PM

All replies

  • 'const int Test::s;' in test.cpp is in fact defining (but not initializing) s a second time. Remove this line and everything will be fine.
    • Proposed as answer by «_Superman_» Thursday, February 11, 2010 5:52 AM
    • Unproposed as answer by Hobson Thursday, February 11, 2010 7:34 AM
    Thursday, February 11, 2010 2:20 AM
  • I am sorry if my explanation was not clear enough for you, but I am not native English speaker, so it could be so. Let me rephrase then:

    I do know, that removing this definition makes MSVC linker happy. But please read a paragraph of C++ Standard I quoted above and tell me whether I am wrong believing that this definition is required (by Standard, standard-compliant build systems, and, in general, rest of the C++ world outside MSVC) when I want to use static const field in context other than const integral expression (for example, when I want to have its addres taken). If it is not required, tell me where I misinterpreted paragraph quoted above.


    I hope I asked clearer this time.


    Thursday, February 11, 2010 7:33 AM