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