2017-06-10 97 views
5

违反ODR在从生产线上图书馆阅读代码,我发现这样的事情如何避免与traits类

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违例for Something在一个翻译单元中不包括SpecialTraits.hpp,然后实例化在另一个翻译单元中使用专门特征的类型。当这两个翻译单元连接在一起时,这将导致ODR违规。

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

注意请忽略foo()可能已经在&&情况下,由专业本身Special的事实。我想不出一个更好的例子。

+1

将专业化放在与'Special'定义相同的标题中。 –

+0

@PeteBecker好想法!我应该在问题中包括这一点。但如果你没有访问权限呢?例如,假设这是一个“boost”模块的专门化 – Curious

+0

在具有专业化的标题中包含具有声明的标题,并且只包含以后的更高版本。 –

回答

3

将专业化放在“WidgetWrapper.hpp”而不是“Widget.hpp”中,并在所有地方包含“WidgetWrapper.hpp”。否则,请用Boost提交错误报告,并期望它不会出现,因为这个确切的problem在15年前被讨论过,没有解决方案。