是否可以使作为默认参数的宏在调用站点展开?
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));
}
#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));
}