web-dev-qa-db-fra.com

Pourquoi __func__, __FUNCTION__ et __PRETTY_FUNCTION__ ne sont pas des macros de préprocesseur?

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?

29
PaperBirdMaster

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.

28
user743382