2

多个翻译单元是否可以声明具有不同默认模板参数但定义相同的相同模板?例如,如果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<>
4

1 回答 1

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包含 ax<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。

此处同样需要注意,如果将Brokento use的定义替换default为在不同的翻译单元中定义的值不同,则仍将违反 ODR 规则。

于 2013-11-01T15:34:30.117 回答