質問

Can multiple translation units have declarations of the same template with different default template arguments but the same definition? For example, does the following code violate ODR if the translation units in b.cpp and c.cpp are linked together?

// 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<>
役に立ちましたか?

解決

It depends. The default argument does not change the definition of the template, it is the same. But it does change the definition of things that use the template when they provide no argument.

Consider:

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

And uses of that header:

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

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

Now your program is in violation of the ODR as one translation unit sees Broken as containing a x<true> while a different translation unit sees Broken as containing a x<false>.

A simpler safer approach would be to declare a constant in your .cpp's and don't modify the template:

// 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

The definition of the template is the same in all translation units and you get some effect similar to what you want. Note that default there has internal linkage so the different default objects would not cause a violation of the ODR.

The same kind of caution applies here as before, if you substitute the definition of Broken to use default and the value is defined to be different in different translation units, it will still be a violation of the ODR rule.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top