如何避免使用traits类违反ODR

Cur*_*ous 6 c++ templates one-definition-rule

在从生产库在线阅读代码时,我发现了类似的东西

Traits.hpp

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

SpecialTraits.hpp

template <>
class Traits<Special> {
    static void foo(Special& object) {
        object.foo();
    }
    static void foo(Special&& object) {
        object.special_foo();
    }
};
Run Code Online (Sandbox Code Playgroud)

如果库实例化在一个翻译单元中使用Traitsfor 的类型Something而不包括SpecialTraits.hpp然后实例化在另一个翻译单元中使用专用特征的类型,则会导致ODR违规.当这两个翻译单元链接在一起时,这将导致ODR违规.

建议的避免此问题的方法是什么?我是否必须在原始Traits.hpp文件中包含所有专业化?如果我不允许编辑带有定义的文件Special怎么办?

注意请忽略在本案中本身foo()可能是专门Special&&事实.我想不出一个更好的例子..

小智 4

将专业化放在“WidgetWrapper.hpp”而不是“Widget.hpp”中,并在各处包含“WidgetWrapper.hpp”。否则,向 Boost 提交错误报告并期望它无济于事,因为这个确切的问题在 15 年前就已经讨论过,但没有解决方案。