Подтвердить что ты не робот

Почему __func__, __FUNCTION__ и __PRETTY_FUNCTION__ не являются макросами препроцессора?

Я только заметил, что __func__, __FUNCTION__ и __PRETTY_FUNCTION__ не рассматриваются как макросы препроцессора, и они не упоминаются в разделе предопределенных макросов 16.8 Стандартного (Рабочий проект N4527).

Это означает, что они не могут использоваться в трюке конкатенации строки фазы 6:

// Valid
constexpr char timestamp[]{__FILE__ " has been compiled: " __DATE__ " " __TIME__};
// Not valid!!!
template <typename T>
void die() { throw std::runtime_error{"Error detected in " __PRETTY_FUNCTION__}; }

Насколько я знаю, __FILE__, __DATE__ и __TIME__ переводятся в строковые литералы, как указано стандартом:

16.8 Предопределенные имена макросов [cpp.predefined]

__DATE__

Дата перевода исходного файла: символьный строковый литерал формы "Mmm dd yyyy", где имена месяцев те же, что и имена, сгенерированные функцией asctime, и первая символ dd является символом пробела, если значение меньше 10. Если дата перевода не является доступный, должна быть предоставлена ​​дата выполнения, соответствующая реализации.

__FILE__

Предполагаемое имя текущего исходного файла (символьный строковый литерал).

__TIME__

Время перевода исходного файла: символьный строковый литерал формы "hh:mm:ss", как и во время, генерируемое функцией asctime.

__func__ упоминается стандартом как функция-локальная предопределенная переменная формы:

static const char __func__[] = "function-name ";

Таким образом, факт заключается в том, что это локальная переменная, поэтому трюк конкатенации строк не работает с ним.

Что касается __FUNCTION__ и __PRETTY_FUNCTION__, не упоминаются в стандарте (определены ли реализации?), но это довольно безопасная ставка, чтобы думать, что они будут вести себя как __func__.

Итак, вопрос: почему __func__, __FUNCTION__ и __PRETTY_FUNCTION__ являются функционально-локальным статическим постоянным массивом символов, а __FILE__, __DATE__ и __TIME__ являются строковыми литералами? Какое обоснование (если таковое имеется) за этим решением?

4b9b3361

Ответ 1

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

В некоторых реализациях сочетаются предварительная обработка и синтаксический анализ, и в этих реализациях было бы возможно, чтобы __func__ работал так, как вам хотелось бы. На самом деле, если я правильно помню, MSVC __FUNCTION__ работает так. Это необоснованный спрос на реализации, которые разделяют фазы перевода, хотя.