Можно ли сделать макросы, являющиеся аргументами по умолчанию, развернутыми на сайте вызова? - PullRequest
0 голосов
/ 20 ноября 2018
#include <stdio.h>

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

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

Макрос __LINE__ в этом случае расширяется до 3, поэтому функция печати вызывается 4 раза с одним и тем же значением.Есть ли способ убедить компилятор развернуть этот макрос на месте вызова, чтобы функция печати вызывалась с 6,7,8,9 вместо 3,3,3,3 с функциями, существующими в C ++ 11?

Мой вариант использования:

В моем приложении я предоставляю несколько функций, которые принимают уникальный идентификатор.Идентификатор должен быть уникальным для каждого места вызова / местоположения (поэтому, если функция вызывается два раза через один и тот же оператор, она должна получить один и тот же идентификатор).В настоящее время пользователь всегда должен вручную вводить макрос LOCATION на месте вызова, например:

#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)

Было бы удобнее, если бы я мог сохранить их при наборе текста, не создавая макрос для каждой функциивот так:

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

Поэтому я подумал, что аргумент по умолчанию поможет.Есть ли способ добиться этого?

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Макрос __LINE__ в этом случае расширяется до 3

Конечно, потому что ваше объявление функции выполнено в строке 3, а препрепроцессор расширяет его оттуда.

Другой макрос вместо объявления функции сработает хорошо (взято из @ комментария Эджая ):

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

См. Рабочий пример здесь .

0 голосов
/ 20 ноября 2018

Вы можете написать макрос, который вставит __FILE__ и __LINE__ в список аргументов:

// 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);
}

Приложив немного больше работы, вы можете сделать его более привлекательным на сайте вызова:

#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 голосов
/ 20 ноября 2018

Вы, похоже, ищете std::experimental::source_location, который в будущем стандарте будет std::source_location:

#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());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...