Явное создание экземпляра шаблона переменной, определенного с помощью ключевого слова «auto»

#c #c 14 #language-lawyer #auto #variable-templates

Вопрос:

Если у вас есть шаблон переменной с типом, выведенным из инициализатора с помощью auto ключевого слова, например:

 template <typename T>
auto * p = (T*)nullptr;
 

Как создать экземпляр переменной для определенного типа (например, чтобы экспортировать ее из общей библиотеки)?

Способ GCC и Clang заключается в замене auto на определенный тип:

 template int * p<int>;
 

Но MSVC отклоняет его с ошибкой:

 error C3410: 'p<int>': the type of the explicit instantiation 'int *' does not match the type of the variable template 'auto *'
 

Демо: https://gcc.godbolt.org/z/66xModTjK

MSVC требует, чтобы экземпляр создавался как:

 template auto * p<int>;
 

который, в свою очередь, отклоняется GCC и лязгает какими-то странными сообщениями:

 error: 'auto' variable template instantiation is not allowed
error: declaration of 'auto* p<int>' has no initializer
 

Демо: https://gcc.godbolt.org/z/7j3nh7Whx

Какие компиляторы находятся здесь в соответствии со стандартом?

Комментарии:

1. «шаблон переменной», а не «переменная шаблона»

2. Вы можете создавать явные экземпляры шаблонов переменных!?

3. [temp.явный]p6: «Объявление в явном экземпляре и объявление, созданное соответствующей подстановкой в шаблонную функцию, переменную или класс, являются двумя объявлениями одной и той же сущности. [Примечание 1: Эти объявления должны иметь соответствующие типы, как указано в 6.6, за исключением случаев, указанных в 14.» — Это единственное, что может сказать об этом стандарт.

4. Обратите внимание, что компиляторы даже не соглашаются на смешивание auto и явные типы при повторном объявлении простых переменных. extern int* i; auto* i = (int*)nullptr; работает в Clang, но не компилируется в GCC и MSVC.

5. Итог: не используйте auto в шаблонах переменных.