I have a header file that declares a template with a static variable and also defines it:
#ifndef MY_HEADER_HPP_ #define MY_HEADER_HPP_ #include <cstdio> template<int n> struct foo { static int bar; static void dump() { printf("%d\n", bar); } }; template<int n> int foo<n>::bar; #endif // MY_HEADER_HPP_
This header is included by both main.cpp and the mylib shared library. In particular, mylib_baz.hpp simply includes this template and declares a function that modifies the template specialization.
#ifndef MYLIB_BAZ_HPP_ #define MYLIB_BAZ_HPP_ #include "my_header.hpp" typedef foo<123> mylib_foo; void init_mylib_foo(); #endif // MYLIB_BAZ_HPP_
and
#include "mylib_baz.hpp" void init_mylib_foo() { mylib_foo::bar = 123; mylib_foo::dump(); };
When I do mylib.so (containing mylib_baz.o ), the symbol foo<123>::bar present and declared weak. However, the symbol foo<123>::bar declared weak also in my main.o :
#include "my_header.hpp" #include "mylib_baz.hpp" int main() { foo<123>::bar = 456; foo<123>::dump(); /* outputs 456 */ init_mylib_foo(); /* outputs 123 */ foo<123>::dump(); /* outputs 123 -- is this guaranteed? */ }
It looks like I'm breaking one definition rule ( foo<123>::bar , defined both in my_header.cpp and main.cpp ). However, with both g ++ and clang, characters are declared weak (or unique), so I'm not bitten by this - all calls to foo<123>::bar modify the same object.
Question 1: Is this a coincidence (maybe ODR works differently for static template members?), Or did I really guarantee this behavior by the standard?
Question 2:. How could I predict the behavior that I observe? That is, what exactly causes the compiler to declare a character weak?