
On Tue, Feb 10, 2015 at 11:53 AM, Michael Powell <mwpowellhtx@gmail.com> wrote:
ODR itself I understand. To my knowledge, you can't apply it to template, header only libraries.
Abandon your notion of ODR. Where Fusion, Spirit, etc, are concerned, AFAIK, it's irrelevant. These are C++ template-based, which means by definition, their 'definition' may be different from instance to instance, but the underlying pattern is consistent, interface driven, etc. That's a fundamental SOLID principle.
1. I assure you Nevin understands ODR (as much as anyone understands C++ - no one is an expert). Let's give him that much. 2. Fusion/Spirit/templates/... maybe, but in general "header only" doesn't mean no ODR issues. The answer really is "it depends". ie template <typename T> struct SboContainer { T sbo[SBO_SMALL_AMOUNT]; T * more; ... }; Imagine the above is a template for a container that uses a "small buffer optimization" - for a small number of elements, they are local. For more elements, it allocates. Now imagine that SBO_SMALL_AMOUNT is a #define. Now imagine that foo.cpp and bar.cpp both use SboContainer<int>, but foo.cpp #defines SBO_SMALL_AMOUNT differently than bar.cpp (before #including SboContainer.hpp). Now imagine that foo.cpp passes a SboContainer<int> & to bar.cpp... Bad things happen. ODR violation, undefined behaviour, cats getting pregnant, etc. Conversely, if we instead do template <typename T, size_t BuffSize = SBO_SMALL_AMOUNT> struct SboContainer { T sbo[BuffSize]; T * more; ... }; now SboContainer<int> from foo.cpp and SboContainer<int> from bar.cpp may actually be different *types*, and instead of a runtime crash we get a compile/link time error. Yay. Parts of Boost have these ODR issues if you are not careful. Other parts don't. So you need to "do it right" when designing/implementing the API. It sounds like Nigel has convinced Nevin that for a hypothetical thread-safe + non-thread-safe "Signals3", we could/would do it the right way. Tony