【问题标题】:How to avoid violating ODR with traits classes如何避免使用特征类违反 ODR
【发布时间】:2017-06-10 20:49:11
【问题描述】:

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

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

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

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

注意请忽略foo()&amp;&amp; 案例中可能被Special 本身特化的事实。我想不出更好的例子了..

【问题讨论】:

  • 将特化放在与Special的定义相同的标题中。
  • @PeteBecker 好主意!我应该把它包括在问题中。但是,如果您无法访问它怎么办?例如说这是boost 模块的特化
  • 在带有特化的标头中包含带有声明的标头,并且只包含后者。
  • 您也可以使用template&lt;&gt; class Traits&lt;Special&gt;; 让编译器知道存在特化,而不是从主模板中实例化它。如果你不能把它放在头文件 Traits.hpp 中,这并不是说有多大帮助。

标签: c++ templates one-definition-rule


【解决方案1】:

将专业化放在“WidgetWrapper.hpp”而不是“Widget.hpp”中,并在任何地方包含“WidgetWrapper.hpp”。否则,请向 Boost 提交错误报告,并期望它不会有任何结果,因为这个确切的 problem 在 15 年前就已经讨论过,但没有得到解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    相关资源
    最近更新 更多