默认模板参数是否进入单定义规则?

时间:2013-11-01 15:14:12

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

多个翻译单元是否可以使用不同的默认模板参数但相同的定义具有相同模板的声明?例如,如果b.cppc.cpp中的翻译单元链接在一起,以下代码是否会违反ODR?

// a.hpp
template <bool> class x {...};

// b.cpp
template <bool = true> class x;
#include "a.hpp"
// uses of x<>

// c.cpp
template <bool = false> class x;
#include "a.hpp"
// uses of x<>

1 个答案:

答案 0 :(得分:5)

这取决于。默认参数不更改模板的定义,它是相同的。但它确实改变了使用模板的东西的定义,因为它们没有提供任何参数。

考虑:

// d.hpp
struct Broken {
   x<> member;
};

使用该标题:

template <bool = true> class x;
#include "d.hpp"
// use Broken

template <bool = false> class x;
#include "d.hpp"
// Use Broken

现在,您的计划违反了ODR,因为一个翻译单元将Broken视为包含x<true>,而其他翻译单元将Broken视为包含x<false>

更简单更安全的方法是在.cpp中声明一个常量,不要修改模板:

// b.cpp
#include "a.hpp"  // no default argument
const bool default = true;
// any use of x<> becomes x<default> in the rest of the code
// similarly for c.cpp

模板的定义在所有翻译单元中都是相同的,您可以获得与您想要的效果类似的效果。请注意,default存在内部链接,因此不同的default对象不会导致违反ODR。

同样的谨慎适用于此,如果您将Broken的定义替换为使用default并且在不同的翻译单元中定义的值不同,则仍然会违反ODR规则。