我的应用程序使用了不同于标准输出的另一种输出来记录信息,这就是为什么我编写了自己的Log()
、Error()
、Panic()
和Assert()
函数。为了更好地组织这些内容,我将所有调试内容都包含在一个Debug
名称空间中。Assert()
函数还提供源文件和行号会更有意义,这只能使用__LINE__
和__FILE__
宏。然而,这是非常不愉快的,效率低下等。必须始终指定这两个参数。
这就是我的代码看起来的样子:
namespace Debug {
void Assert (int condition, std::string message, std::string file, int line);
}
我的问题是,是否可以在Debug
命名空间中放置一个包含这两个参数的宏?像这样:
namespace Debug {
void Assert_ (int condition, std::string message, std::string file, int line);
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
// Output: Assertion failed on line 10 in file test.cpp:
// Some_condition should be true
这是有效的C++吗?如果没有,有没有办法让它工作?
5条答案
按热度按时间svujldwt1#
在c++中可以将宏放在命名空间中吗?
没有
#define
是预处理器指令。除了删除注解(这意味着,在编译之前),宏被替换 * 在 * 其他任何东西之前。所以在宏被替换的时候,编译器对你的命名空间一无所知。就像其他人说的那样,在你的情况下会很好。然而,这是你如何可以得到的问题:
因此,虽然看起来定义是“在名称空间中”,但它们不是 *,并且最后一个
#define
将始终被使用,在这种情况下,这将导致编译时错误,因为main中的代码将被替换为:而不是
wwtsj6pe2#
不,预处理器根本不关心名称空间。事实上,预处理器至少在概念上在编译器看到任何东西之前运行。
对于我自己来说,我只是做了一个标准的ASSERT宏,并期望没有“健全的名称空间”有一个叫做ASSERT的东西。问题解决了如果我需要一个有自己的ASSERT的库,那么我仍然可以决定如何处理这个问题;然而,我目前使用的唯一一个带有自己的“assert”的库称之为BOOST_ASSERT或类似的东西……
gajydyqb3#
这个特定的用法将完全按照您的意愿执行,但是 * Assert宏绝不是Debug命名空间的一部分 *……就好像你做了
在这里,替换起作用不是因为
Assert
在Debug
名称空间中(它不在你的代码或这段代码中,预处理器不知道名称空间是什么)-它工作是因为Assert
被识别为宏的标识符,Assert_
的替换被完成,然后编译器恰好发现有一个Debug::Assert_
所以,假设你在你的翻译单元后面的某个地方有一些完全不相关的代码:宏替换仍然会产生一个编译时错误,说你对一个宏有错误的参数数量。假设不相关的代码是:
然后将其替换为:
(另外,标准做法是在预处理器宏名称中不使用小写字母)。
ldioqlga4#
你可以尝试__PRETTY_FUNCTION __宏来打印包括函数参数在内的所有命名空间。
wf82jlnq5#
是的,你的宏将扩展到你所期望的。
将被替换为