CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Feb 2004
    Location
    Texas, USA
    Posts
    1,206

    Question about internal linkage

    Hi guys,

    I have an interesting scenario I've tested that really doesn't make any sense to me. First note that I'm using the Visual Studio 2008 compiler.

    I have 3 files:

    Foo.h
    A.cpp
    B.cpp

    In Foo.h, I have the following:
    Code:
    class foo
    {
        static int s_member;
    };
    
    int foo::s_member = 14;
    In A.cpp and in B.cpp, I do the following (code is identical in both):

    Code:
    static int maintest()
    {
        foo<0> myfoo;
    }
    When I compile and link this code, the linker fails saying that two definitions of s_member has been found. This is what I expected. Now let's change the implementations a bit:

    Foo.h is now this:

    Code:
    template< unsigned int t_val >
    class foo
    {
    	static int s_member;
    };
    
    template< unsigned int t_val >
    int foo<t_val>::s_member = 14;
    Both A.cpp and B.cpp have been changed to this:

    Code:
    static int maintest()
    {
        foo<0> myfoo;
    }
    In the second scenario, the linker does not fail. I would expect it to fail. Since we're instantiating the class with the same template arguments, both files should be referencing the same static member, and thus the same static member should be getting duplicated between translation units *just* like the former scenario. What is happening here? Where is the static *actually* stored?

    ::EDIT::
    Note that A.cpp and B.cpp both include "foo.h", this should have been obvious but I just wanted to mention it.
    --MrDoomMaster
    --C++ Game Programmer


    Don't forget to rate me if I was helpful!

  2. #2
    Join Date
    Apr 2005
    Location
    Norway
    Posts
    3,934

    Re: Question about internal linkage

    Quote Originally Posted by MrDoomMaster
    In the second scenario, the linker does not fail. I would expect it to fail. Since we're instantiating the class with the same template arguments, both files should be referencing the same static member, and thus the same static member should be getting duplicated between translation units *just* like the former scenario. What is happening here?
    It seems that VC++ initializes the templates static field only if necessary (in compliance with the standard), and only once.
    But, it also seems that if you put different definitions of the static in different translation units, then VC++ will simply use the 'first found'. AFAIK that violates the 'one definition rule'.

    - petter

  3. #3
    Join Date
    Feb 2004
    Location
    Texas, USA
    Posts
    1,206

    Re: Question about internal linkage

    Quote Originally Posted by wildfrog
    It seems that VC++ initializes the templates static field only if necessary (in compliance with the standard), and only once.
    But, it also seems that if you put different definitions of the static in different translation units, then VC++ will simply use the 'first found'. AFAIK that violates the 'one definition rule'.

    - petter
    Thanks for your response to my inquiry. Could you explain what you mean by "first found"? How does this violate ODR (Note that I already am a little bit fuzzy on the definition of ODR)?
    --MrDoomMaster
    --C++ Game Programmer


    Don't forget to rate me if I was helpful!

  4. #4
    Join Date
    Apr 2005
    Location
    Norway
    Posts
    3,934

    Re: Question about internal linkage

    Actually "first found" is just my assumtion, but you'll probably have to ask the folks as Microsoft on how it actually works.

    Try adding some code to your second sample, intialize s_member in both you code files:
    Code:
    //a.cpp
    int initA() { return 5; }
    
    int foo<0>::s_member = initA();
    static int maintest()
    {
        foo<0> myfoo;
    }
    Code:
    //b.cpp
    int initB() { return 19; }
    
    int foo<0>::s_member = initB();
    static int maintest()
    {
        foo<0> myfoo;
    }
    This does to compile, but only one of the definition are actually executed (some simple tests suggests that if a.cpp is added to the solution first then initA() is executed, and if b.cpp is added first then initB() is executed...

    - petter

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured