В приведенном ниже коде приведен пример прямого объявления константных переменных шаблона, который компилируется как в clang, так и в gcc:
template<class T>
extern const T value;
template<class T>
const T value= 0;
auto test = value<int>;
template<class T>
extern const T value2;
template<class T>
constexpr T value2 =0;
auto test2 = value2<int>;
template<class T>
extern const T value3;
template<class T>
inline constexpr T value3 =0;
auto test3 = value3<int>;
Тем не менее, если я объявляю переменные не const, gcc выдает ошибку компоновщика: undefined reference to value4<int>
и undefined symbol value5<int>
, но clang принимает код:
template<class T>
extern T value4;
template<class T>
T value4= 0;
auto test4 = value4<int>; //gcc linker error
template<class T>
extern T value5;
template<class T>
inline T value5=0;
auto test5 = value5<int>; //gcc linker error
Изначально я был уверен, что все эти случаи использования соответствуют стандарту.Но поскольку gcc выдает ошибку компоновщика для последних двух случаев, мне было интересно, были ли какие-либо из этих предварительных объявлений законными?GCC неверен или я не требует диагностики ошибка?Может ли предварительное объявление с последующим встроенным определением переменных шаблона как value3
или value5
в нескольких единицах перевода вызвать нарушение odr?
Демонстрация ошибки фазового связывания
Примечание: в этих ответах на эти вопросы кажется, что они упустили возможность объявить переменную как extern const.