Я только заметил, что __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__
являются строковыми литералами? Какое обоснование (если таковое имеется) за этим решением?