How to avoid violating ODR with traits classes
Asked Answered
C

1

6

On reading code online from production libraries I found something like this

Traits.hpp

template <typename Type>
class Traits {
    template <typename T, 
              detail::EnableIfIsInstantiation<T, Type>* = nullptr>
    static void foo(T& object) { 
        object.foo();
    } 
};

SpecialTraits.hpp

template <>
class Traits<Special> {
    static void foo(Special& object) {
        object.foo();
    }
    static void foo(Special&& object) {
        object.special_foo();
    }
};

This will cause an ODR violation if a library instantiates a type that uses Traits for Something in one translation unit without including SpecialTraits.hpp and then instantiates a type that uses the specialized traits in another translation unit. This would cause an ODR violation when those two translation units are linked together.

What is the suggested way to avoid this problem? Do I have to resort to including all the specializations in the original Traits.hpp file? And what if I am not allowed to edit the file with the definition for Special?

Note Please ignore the fact that foo() could have been specialized by Special itself in the && case. I could not think of a better example..

Carrara answered 10/6, 2017 at 20:49 Comment(4)
Put the specialization in the same header as the definition of Special.Mediation
@PeteBecker Good thought! I should have included that in the question. but what if you do not have access to that? For example say this is a specialization for a boost moduleCarrara
Include the header with the declaration in the header with the specialisation, and only include the later ever.Teddytedeschi
You can also do template<> class Traits<Special>; to let the compiler know the specialization exists and not to instantiate it from the primary template. Not that this helps that much if you can't put it in the header Traits.hpp.Crappie
G
4

Put the specialization in "WidgetWrapper.hpp" instead of "Widget.hpp" and include "WidgetWrapper.hpp" everywhere. Otherwise, file a bug report with Boost and expect it to go nowhere since this exact problem was discussed 15 years ago with no resolution.

Giron answered 10/6, 2017 at 23:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.