宏无法正确扩展
I have these macros defined:
#define AL_ASSERT_NO_MSG(x) if (!(x)) { assertDialog(__LINE__, __FILE__); __debugbreak(); }
#define AL_ASSERT_MSG(x, msg) if (!(x)) { assertDialog(msg, __LINE__, __FILE__); __debugbreak(); }
#define GET_MACRO(_1, _2, NAME, ...) NAME
#define AL_ASSERT(...) GET_MACRO(__VA_ARGS__, AL_ASSERT_MSG, AL_ASSERT_NO_MSG)(__VA_ARGS__)
I wanted to have it dispatched to the AL_ASSERT_NO_MSG
macro if I only pass one argument and AL_ASSERT_MSG
if I pass two arguments.
但是,当我使用这样的宏时:al_assert(false,“ test”)
它扩展到if(!(false,“ test”))){assertDialog(23,“ C: \\ dev \\ c ++ \\ sortingalgorithms \\ algorithmvisualizer \\ src \\ window.cpp”); __debugbreak(); };
,并且不起作用。
更多信息:我正在使用MSVC使用Visual Studio。这不是基于解决方案的项目,而是一个CMAKE项目作为文件夹打开。
我做错了什么?任何帮助都将受到赞赏。
I have these macros defined:
#define AL_ASSERT_NO_MSG(x) if (!(x)) { assertDialog(__LINE__, __FILE__); __debugbreak(); }
#define AL_ASSERT_MSG(x, msg) if (!(x)) { assertDialog(msg, __LINE__, __FILE__); __debugbreak(); }
#define GET_MACRO(_1, _2, NAME, ...) NAME
#define AL_ASSERT(...) GET_MACRO(__VA_ARGS__, AL_ASSERT_MSG, AL_ASSERT_NO_MSG)(__VA_ARGS__)
I wanted to have it dispatched to the AL_ASSERT_NO_MSG
macro if I only pass one argument and AL_ASSERT_MSG
if I pass two arguments.
However, when I use the macro like this: AL_ASSERT(false, "Test")
it expanded to if (!(false, "Test")) { assertDialog(23, "C:\\Dev\\c++\\SortingAlgorithms\\AlgorithmVisualizer\\src\\Window.cpp"); __debugbreak(); };
and it does not work.
More information: I am using Visual Studio with MSVC. This is not a solution-based project but a CMake project opened as a folder.
What did I do wrong? Any help is appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于使用
__行__
和__文件__
,因此您只需要宏。所有其他逻辑都可以在通常的函数中完成:使用C ++ 20,根本不需要宏:
可以直接使用宏而不是将宏用作
al_assert(/*.....*/)< /代码>。
std :: source_location
在参数包工作之后的CTAD技巧是 。(模板参数和转发引用涵盖了潜在的边缘情况,以使其与宏观行为尽可能近。根据您的用例,您可能会对EG进行
>条件
简单地简单地感到满意bool
而不是。)You only need the macro because of the use of
__LINE__
and__FILE__
. All the other logic can be done in a usual function:With C++20 the macro is not required at all:
This can be used directly instead of using the macro as
al_assert(/*...*/)
. The CTAD trick to makestd::source_location
after the parameter pack work is due to this answer.(The template parameters and forwarding references are there to cover potential edge cases to make it as close as possible to the macro behavior. Depending on your use case, you may be happy with e.g. making the
condition
simply abool
instead.)MSVC似乎不会将
__ va_args __
扩展到多个参数(请参阅此相关问题: msvc not /a>)这似乎有效:
如果您针对C ++ 20(并且具有Visual Studio 2019版本16.5),则可以使用
__ va_opt __
:或者您可以使用某些功能来完成:
使用版本16.10,您可以在没有
std :: source_location
:It seems that MSVC does not expand
__VA_ARGS__
into multiple arguments (see this related question: MSVC doesn't expand __VA_ARGS__ correctly)This seems to work:
And if you are targeting C++20 (and have Visual Studio 2019 version 16.5), you can use
__VA_OPT__
:Or you can do it with some functions:
And with version 16.10 you can do it without a macro with
std::source_location
:尝试使用预处理器将表达式与消息分开并不是最好的主意,因为两者都可以包含逗号,从而使其总体上不可能。
但是您可以做到这一点:
然后,如果您确实提供了Mesasge,则
foo(line,cond,“消息”,“ file”)
将被调用,否则foo(line,cond cond cond ,“文件”,nullptr)
。通过检查最后一个参数是否为零,您可以查看第三个parmaeter是消息还是文件名。
...或者您可以超载该功能。
Trying to separate the expression from the message using preprocessor is not the best idea, since both can contain commas, making it impossible in general.
But you can do this:
Then, if you do provide a mesasge,
foo(line, cond, "message", "file")
will be called, and otherwisefoo(line, cond, "file", nullptr)
will be called.By checking if the last parameter is zero, you see whether the third parmaeter is a message or a filename.
... Or you can just overload the function.