
Sebastian Redl wrote:
Arkadiy Vertleyb wrote:
I would say that, if your technique, as a library author, can easily lead to the violation of language rules by your users, even though these users don't do anything obviously wrong, such technique can be defined as invalid.
Define "easily", then.
If the documentation of the library says, in a sufficiently prominent location: "If you want to use this library together with XYZ, you must include xyz-interop.hpp in all translation units that do so." Does ignoring this count as "easy"?
Just want to point out that the problem is larger than just unnamed namespaces. Global const objects are also given internal linkage. // foo.hpp struct placeholder {}; placeholder const _1 = {}; template<class T> void foo(T const &) { // use _1 here } That's a potential ODR violation right there. Every translation unit that includes foo.hpp gets it's own _1 object. Therefore, the foo() template gets instantiated differently in each TU. Dave and I spent a long time, and started a discussion on the std reflectors, figuring out how to avoid ODR in this very common and useful scenario without giving up static initialization. It's hard and not obvious: template<typename T> struct static_const { static T const value; }; template<typename T> T const static_const<T>::value = {}; struct placeholder {}; // This is *supposed* to be statically initialized but many // compilers do dynamic initialization for it. :-( placeholder const &_1 = static_const<placeholder>::value; template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. } -- Eric Niebler Boost Consulting www.boost-consulting.com