#include <stdio.h>

void print(int a = __LINE__){printf("hello %d\n", a);}

void main(){
  print();
  print();
  print();
  print();
}

La macro __LINE__ dans ce cas se développe à 3, donc la fonction d'impression est appelée 4 fois avec la même valeur. Existe-t-il un moyen de convaincre le compilateur d'étendre cette macro sur le site d'appel, de sorte que la fonction d'impression soit appelée avec 6,7,8,9 au lieu de 3,3,3,3 avec des fonctionnalités qui existent dans C ++ 11?

Mon cas d'utilisation:

Dans mon application, je propose plusieurs fonctions qui prennent un identifiant unique. L'ID doit être unique par site d'appel / emplacement (donc si la fonction est appelée deux fois dans la même instruction, elle doit recevoir le même identifiant). Actuellement, l'utilisateur doit toujours taper manuellement une macro LOCATION sur le site d'appel, comme ceci:

#define S1(x) #x //voodoo to concat __FILE__ and __LINE__
#define S2(x) S1(x)
#define LOCATION __FILE__ S2(__LINE__)

do_stuff1(arguments, LOCATION)
do_stuff2(arguments, LOCATION)

Ce serait plus pratique si je pouvais leur enregistrer la saisie, sans créer une macro pour chaque fonction comme ceci:

#define do_stuff1(do_stuff1_imp(arguments, LOCATION))
#define do_stuff2(do_stuff2_imp(arguments, LOCATION))

Par conséquent, je pensais qu'un argument par défaut ferait l'affaire. Y'a-t-il une quelconque façon de réussir cela?

1
pulp_user 20 nov. 2018 à 21:13

3 réponses

Meilleure réponse

La macro __LINE__ dans ce cas passe à 3

Bien sûr, car votre déclaration de fonction est effectuée à la ligne 3 et le préprocesseur la développe à partir de là.

Une autre macro au lieu d'une déclaration de fonction ferait bien l'affaire (tirée de @ Commentaire d'Ejay):

#define print() printf("hello %d\n", __LINE__)

Consultez un exemple de travail ici.

2
Jarod42 20 nov. 2018 à 18:54

Vous semblez rechercher std::experimental::source_location, qui sera { {X1}} dans une future norme:

#include <experimental/source_location>

void print(std::experimental::source_location const& location
    = std::experimental::source_location())
{
    printf("hello %s:%d\n", location.file_name(), location.line());
}
4
Justin 20 nov. 2018 à 18:18

Vous pouvez écrire une macro qui insère __FILE__ et __LINE__ dans la liste d'arguments:

// Note: this doesn't work with a 0-argument function. Supporting 0-arg functions
// is much harder to do; I'd recommend just having a separate macro like as follows
#define LOCATED(fn, ...) fn(__VA_ARGS__, __FILE__, __LINE__)

#define LOCATED0(fn) fn(__FILE__, __LINE__)

void print(char const* file_name, int line)
{
    printf("hello %s:%d\n", file_name, line);
}

int do_something(int value, char const* file_name, int line);

int main() {
    LOCATED0(print);
    LOCATED(do_something, 42);
}

Avec un peu plus de travail, vous pouvez le rendre plus joli sur le site d'appel:

#define LOCATED(...) LOCATED_##__VA_ARGS__

void print(char const* file_name, int line)
{
    printf("hello %s:%d\n", file_name, line);
}
#define LOCATED_print() ::print(__FILE__, __LINE__)

int do_something(int value, char const* file_name, int line);
#define LOCATED_do_something(value) ::do_something(value, __FILE__, __LINE__)

int main() {
    LOCATED(print());
    LOCATED(do_something(42));
}
0
Justin 20 nov. 2018 à 18:45