是否可以使作为默认参数的宏在调用站点展开?

Is it possible to make macros that are default arguments expand at call site?

#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 中存在的功能?

我的用例:

在我的应用程序中,我提供了多个采用唯一 ID 的函数。每个 callsite/location 的 ID 应该是唯一的(因此,如果通过同一语句两次调用该函数,它应该收到相同的 ID)。目前,用户总是必须在调用站点手动键入 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))

因此我认为默认参数可以解决问题。有什么办法可以实现吗?

您似乎在寻找 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());
}

The __LINE__ macro in this case expands to 3

当然可以,因为您的函数声明是在第 3 行完成的,预处理器会从那里扩展它。

另一个宏而不是函数声明就可以很好地解决这个问题(取自):

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

查看工作示例 here

您可以编写一个宏,将 __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));
}