Рассмотрим следующий код:
template <class T>
struct computation {
using type = /* something based on T that takes time to compile */;
};
Теперь рассмотрим два кода:
using x = computation<T>;
и:
using y = typename computation<T>::type;
Мне интересно, подразумевает ли стандарт, что:
x
и долгому времени компиляции для y
computation<T>::type
, даже если вызывается только computation<T>
, что приводит к длительному времени компиляции даже для x
Другими словами, я пытаюсь узнать, указывает ли стандарт что-либо, что, скорее всего, приведет к варианту A или варианту B для «разумного» компилятора. Я знаю, что стандарт ничего не говорит о реализации компилятора, но, например, если он требует, чтобы ::type
не обязательно существовал до тех пор, пока он не будет вызван специально, это будет в пользу варианта A.
ПРИМЕЧАНИЕ: По своему опыту я почти уверен, что g++
, clang++
, msvc
и intel
следуют варианту A), но я понятия не имею, является ли это чистой случайностью или связано с чем-то в стандарте.
Я знаю это, и это не то, что я пытаюсь узнать. Но если в стандартах сказано, что ::type
на самом деле не «существует», пока его не вызовут, это будет убедительным признаком.
Я думаю, что компилятор должен выбрать вариант B, потому что он должен убедиться, что computation<T>::type
действительно дает что-то разумное при сопоставлении с T. Но, может быть, просто попробуйте. Сделайте ::type fail для T и посмотрите, работает ли using x = computation<T>;
.
@GoswinvonBrederlow См. добавленную заметку
iirc, стандарт требует минимальной глубины стека (которая действительно мала), но компиляторы могут предоставить более глубокую глубину стека, если они хотят.
Я не знаю, указано ли это явно где-либо в стандарте, раздел шаблона и ODR несколько утомительны для чтения, но правило «как если бы» дает компиляторам большую свободу действий, и я ожидаю, что вариант A был тем, что больше всего/ все компиляторы используют. Если что-то никогда не используется, у компилятора нет причин выполнять эту работу.
@NathanOliver Что, если ::type выдает ошибку для заданного T, которая очевидна только тогда, когда вы выполняете работу, и поэтому вывод шаблона должен завершиться неудачно?
T
в двух строках using
должен быть фактическим типом или другим параметром шаблона? В первом случае typename
не имеет смысла, а во втором случае ни одна из строк сама по себе не вызовет никаких экземпляров чего-либо.
@GoswinvonBrederlow: компиляторам разрешено выполнять работу, которая не является строго необходимой, но они не могут отклонять действительные программы. Поскольку computation<T>
само по себе не является явным или неявным воплощением, действительность type
не имеет значения.
Я предполагаю, что T
здесь является независимым типом, а не другим параметром шаблона.
Линия
using x = computation<T>;
не вызывает неявную реализацию computation<T>
. Поэтому у компилятора нет причин пытаться вычислить type
в этот момент, в частности, поскольку любой сбой создания экземпляра нужно будет игнорировать. Программа не может не скомпилироваться, если вычисление type
даст недопустимый тип или по какой-либо иной причине завершится ошибкой.
Линия
using y = computation<T>::type;
требует неявного создания экземпляра computation<T>
, потому что к нему применяется оператор разрешения области видимости. Неявная реализация включает в себя вычисление псевдонимов типов внутри computation<T>
. Компилятор должен выполняет вычисление, потому что, если вычисление завершится ошибкой или будет получен недопустимый тип, программа будет неправильно сформирована, и компилятору придется ее диагностировать.
На самом деле это не зависит конкретно от части ::type
. Даже если это было ::type2
для псевдонима другого типа, неявное создание экземпляра специализации шаблона класса потребует вычисления type
.
Точно так же использование computation<T>
в любом другом контексте, требующем его завершения, потребует неявного создания экземпляра и, следовательно, вычисления type
, например.
auto z = computation<T>{};
Кто-то может доказать, что я ошибаюсь, но учтите возможность того, что стандарт ничего не говорит о скорость компиляции при определении типа.