Входят ли аргументы шаблона по умолчанию в правило с одним определением?

Могут ли несколько единиц перевода иметь объявления одного и того же шаблона с разными аргументами шаблона по умолчанию, но с одинаковым определением? Например, нарушает ли следующий код ODR, если единицы перевода в b.cpp а также c.cpp связаны вместе?

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

2

Решение

Это зависит. Аргумент по умолчанию не менять По определению шаблона это одно и то же. Но это меняет определение вещей, которые используют шаблон, когда они не дают аргументов.

Рассматривать:

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

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]