是否可以在 C++ 的命名空间中放置一个宏?

2022-01-11 00:00:00 namespaces macros c++

我的应用程序使用另一个输出而不是标准输出来记录信息,这就是我编写自己的 Log()Error()Panic()Assert() 函数.为了更好地组织事情,我将所有调试内容都包含在 Debug 命名空间中.

My application uses another output than the standard output for logging information, which is why I wrote my own Log(), Error(), Panic() and Assert() functions. To organize things nicely, I enclose all the debugging stuff in a Debug namespace.

Assert() 函数还提供源文件和行号会更有意义,这只能使用 __LINE____FILE__ 宏.但是,总是必须指定这两个参数是非常不愉快、低效的等等.

It would make more sense for the Assert() function to also provide a source file and line number, which is only possible using the __LINE__ and __FILE__ macros. However, it is pretty unpleasant, inefficient etc... to always have to specify these two parameters.

这就是我的代码的样子:

So this is how my code would look like:

namespace Debug {
   void Assert (int condition, std::string message, std::string file, int line);
}

我的问题是,是否可以在 Debug 命名空间中放置一个包含这两个参数的宏?像这样:

My question is, is it possible to place a macro which includes those two parameters inside the Debug namespace? Like this:

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++ 吗?如果没有,有什么办法可以做到吗?

Is this valid c++? If not, is there any way of making this work?

推荐答案

#define 是一个预处理指令.除了删除注释(这意味着,在编译之前)之外,宏被替换之前.因此,在替换宏时,编译器对您的命名空间一无所知.

#define is a preprocessor directive. The macros are being replaced before anything else apart from removing comments (which means, before compilation). So at the time macros are replaced, the compiler knows nothing about your namespaces.

正如其他人所说,在你的情况下它会很好.但是,这就是您遇到问题的方式:

As other people state, in your case it will be fine. However, This is how you can get problems:

namespace A
{
 void Assert_ (int condition, std::string message, std::string file, int line)
 {
     std::cout << "A";
 }
   #define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)

}
namespace B
{
 void Assert_ (int condition)
 {
     std::cout << "B";
 }
   #define Assert(a,b) Assert_(a)

}

int main(int argc, char *argv[])
{
    A::Assert(0,"asdasd");
    B::Assert(0,"asdasd");
}

因此,虽然定义看起来像是在命名空间中",但它们不是 ,并且将始终使用最后一个 #define,在这种情况下将导致编译时错误,因为 main 中的代码将被替换为:

So while it looks like the defines are "in the namespaces", they are not, and the last #define will be always be used, which in this case will lead to a compile-time error, because the code in main will be replaced by:

A::Assert(0);
B::Assert(0);

而不是

A::Assert(0,"asdasd", _FILE_, _LINE_);
B::Assert(0);

相关文章