#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
в шаблонах переменных.