Je viens de remarquer que __func__
, __FUNCTION__
et __PRETTY_FUNCTION__
ne sont pas traités comme des macros de préprocesseur et ils ne sont pas mentionnés dans la section 16.8 Noms de macro prédéfinis de la norme ( N4527 Working Draft ).
Cela signifie qu'ils ne peuvent pas être utilisés dans l'astuce de concaténation de chaînes phase 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__}; }
Pour autant que je sache, le __FILE__
, __DATE__
et __TIME__
sont traduits en littéraux de chaîne comme indiqué par la norme:
16.8 Noms de macro prédéfinis [cpp.predefined]
__DATE__
La date de traduction du fichier source: une chaîne de caractères littérale de la forme
"Mmm dd yyyy"
, où les noms des mois sont les mêmes que ceux générés par la fonction asctime, et le premier caractère de dd est un espace si la valeur est inférieure à 10. Si la date de traduction n'est pas disponible, une date de validité définie par l'implémentation doit être fournie.
__FILE__
Le nom présumé du fichier source actuel (un littéral de chaîne de caractères ).
__TIME__
Le temps de traduction du fichier source: une chaîne de caractères littérale de la forme
"hh:mm:ss"
comme dans le temps généré par la fonction asctime.
__func__
est mentionné par la norme comme une variable prédéfinie locale de la forme:
static const char __func__[] = "function-name ";
Donc, c'est une variable locale, donc l'astuce de concaténation de chaînes ne fonctionne pas avec elle.
Pour ce qui est de __FUNCTION__
et __PRETTY_FUNCTION__
ne sont pas mentionnés dans la norme (l'implémentation est-elle définie?), mais il est assez sûr de penser qu'ils se comporteraient comme __func__
.
Donc la question est pourquoi __func__
, __FUNCTION__
et __PRETTY_FUNCTION__
sont un tableau de constantes statiques locales fonctionnelles tandis que __FILE__
, __DATE__
et __TIME__
sont des littéraux de chaîne? Quelle est la justification (le cas échéant) de cette décision?
Expansion __func__
au moment du prétraitement, le préprocesseur doit savoir quelle fonction il traite. Le préprocesseur ne le sait généralement pas, car l'analyse se produit une fois le préprocesseur terminé.
Certaines implémentations combinent le prétraitement et l'analyse, et dans ces implémentations, il aurait été possible pour __func__
pour travailler comme vous le souhaitez. En fait, si je me souviens bien, le MSVC __FUNCTION__
fonctionne comme ça. C'est une demande déraisonnable sur les implémentations qui séparent les phases de traduction.