Требуется ли инициализация первичного шаблона ссылочной переменной, даже если он никогда не создавался? - PullRequest
0 голосов
/ 28 ноября 2018

Разрешено ли объявлять эталонный шаблон в C ++ 14 без инициализации первичного эталонного шаблона, если он никогда не создается?

template<class T>
const T& ref;

template<>
auto ref<int> = 1;

auto x = ref<int>;

Это приводит к различным результатам в GCC и Clang:

$ g++ -std=c++14 -c ref.cpp
$

$ clang -std=c++14 -c ref.cpp
ref.cpp:2:10: error: declaration of reference variable 'ref' requires an
      initializer
const T& ref;
         ^~~
1 error generated.

Нет смысла инициализировать первичный эталонный шаблон, потому что до его создания это шаблон, а не эталон.

Я обнаружил, что могу сделать что-то вроде:

template<class T>
const T& ref = "Meaningless initialization with any value of any type";

template<>
auto ref<int> = 1;

auto x = ref<int>;

, поскольку очевидно, что GCC и Clang оба принимают, но игнорируют RHS инициализатора эталонного шаблона, если это допустимое выражение и первичный эталонный шаблон никогда не создается.И любое выражение любого типа удовлетворяет требованию инициализации Clang.

GCC не требует инициализатора до тех пор, пока первичный эталонный шаблон никогда не создается.Кажется, это правильное поведение «по духу», потому что, пока эталонный шаблон не будет фактически создан, он не должен нуждаться в инициализаторе.

Стандарт не на 100% ясен для эталонных шаблонов.Вот что я мало мог найти при создании экземпляра шаблона переменной:

14.7.1

Если специализация шаблона переменной не была явно создана или явно специализирована, переменнаяспециализация шаблона неявно создается при использовании специализации.

...

Реализация не должна неявно создавать экземпляр ... шаблона переменной ..., который не требует создания экземпляра.

14.7.2

За исключением встроенных функций, объявления с типами, выведенными из их инициализатора или возвращаемого значения (7.1.6.4), const переменные литеральных типов, переменные ссылочных типов и специализации шаблонов классов, явные объявления экземпляров подавляют неявное создание экземпляров сущности, к которой они относятся.[Примечание: намерение состоит в том, чтобы встроенная функция, являющаяся предметом явного объявления экземпляра, все еще неявно создавалась, когда используется odr (3.2), так что тело можно рассматривать для встраивания, но не для копирования вне строкивстроенная функция будет сгенерирована в единице перевода. - примечание к концу]

14.7.3

Объявление шаблона функции, шаблона класса или переменный шаблон будучи явно специализированным, должен предшествовать объявлению явной специализации.[ Примечание: требуется декларация, но не определение шаблона.- конец примечания ].

Изменить, чтобы добавить:

Объявление шаблона переменной, объявление шаблона класса или объявление шаблона функции не являетсято же самое, что и объявление переменной, объявление класса или объявление функции, соответственно, и не подчиняется тем же правилам.Пока не создан экземпляр шаблона, это всего лишь шаблон.

Шаблоны классов, шаблоны переменных и шаблоны функций могут быть объявлены без предоставления основного определения, только определения специализации.Следующий код допустим как для Clang, так и для GCC:

// Class
template<class T> class foo;        // Declaration, not definition
template<> class foo<int> {};       // Specialization definition
using ifoo = foo<int>;              // Specialization instantiation

// Function
template<class T> void bar(T);      // Declaration, not definition
template<> void bar(int) {}         // Specialization definition
void (*barp)(int) = bar<int>;       // Specialization instantiation

// Variable
int j;
template<class T> T* point;         // Declaration, not definition
template<> int* point<int> = &j;    // Specialization definition
int *k = point<int>;                // Specialization instantiation

Тогда возникает вопрос: почему он должен отличаться для эталонного шаблона?Почему первичным объявлением эталонного шаблона должно быть определение с инициализацией эталона, если это не относится ни к каким другим шаблонам?

template<class T> const T& ref;      // Declaration, not definition
template<> const int& ref<int> = 1;  // Specialization definition
const int& iref = ref<int>;          // Specialization instantiation

1 Ответ

0 голосов
/ 28 ноября 2018

Я полагаю, что это покрыто [temp.res] / 8:

... Программа некорректна, диагностика не требуется, если:

  • невозможно создать действительную специализацию для шаблона или подстановки constexpr, если оператор внутри шаблона и шаблон не создан ...

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


Цитата, которую я предоставил, взята из C ++ 17, но в C ++ 14 есть аналогичное утверждение.

...