如何避免使用traits类违反ODR

时间:2017-06-10 20:49:12

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

SpecialTraits.hpp

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

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

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

注意请忽略foo()案件中Special本身可能&&专用的事实。我想不出更好的例子。

1 个答案:

答案 0 :(得分:3)

将专业化放在&#34; WidgetWrapper.hpp&#34;而不是&#34; Widget.hpp&#34;并包括&#34; WidgetWrapper.hpp&#34;到处。否则,请向Boost提交一份错误报告,并期望它无处可去,因为这个确切的problem在15年前已经讨论过,没有解决方案。