Как избежать нарушения ODR с классами признаков

При чтении кода онлайн из производственных библиотек я нашел что-то вроде этого

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();
    }
};

Это приведет к нарушению ODR, если библиотека создает экземпляр типа, который использует Traits вместо Something в одной единице перевода, не включая SpecialTraits.hpp, а затем создает экземпляр типа, который использует специализированные признаки в другой единице перевода. Это может привести к нарушению ODR, когда эти две единицы перевода связаны вместе.

Каков предлагаемый способ избежать этой проблемы? Должен ли я прибегать к включению всех специализаций в исходный файл Traits.hpp? А что, если мне не разрешено редактировать файл с определением для Special?

Примечание. Пожалуйста, не обращайте внимания на тот факт, что foo() могла быть специализирована самим Special в случае &&. Я не мог придумать лучшего примера..


person Curious    schedule 10.06.2017    source источник
comment
Поместите специализацию в тот же заголовок, что и определение Special.   -  person Pete Becker    schedule 10.06.2017
comment
@PeteBecker Хорошая мысль! Я должен был включить это в вопрос. но что, если у вас нет доступа к этому? Например, скажите, что это специализация для модуля boost.   -  person Curious    schedule 10.06.2017
comment
Включите заголовок с объявлением в заголовок со специализацией и включайте только последнее.   -  person Daniel Jour    schedule 11.06.2017
comment
Вы также можете выполнить template<> class Traits<Special>;, чтобы сообщить компилятору о существовании специализации, а не создавать ее экземпляр из основного шаблона. Не то, чтобы это сильно помогло, если вы не можете поместить его в заголовок Traits.hpp.   -  person aschepler    schedule 11.06.2017


Ответы (1)


Поместите специализацию в «WidgetWrapper.hpp» вместо «Widget.hpp» и включите «WidgetWrapper.hpp» везде. В противном случае отправьте отчет об ошибке в Boost и ожидайте, что он никуда не денется, поскольку именно этот проблема обсуждалась 15 лет назад и не решена.

person user8142939    schedule 10.06.2017