Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-06-14 13:39:18


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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk