|
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