C++ 是否可以在c++;?

C++ 是否可以在c++;?,c++,macros,namespaces,C++,Macros,Namespaces,我的应用程序使用标准输出以外的另一个输出来记录信息,这就是我编写自己的Log()、Error()、Panic()和Assert()函数的原因。为了很好地组织事情,我将所有调试内容封装在Debug名称空间中 如果Assert()函数还提供源文件和行号,则更有意义,因为只有使用\uuuuuuuuuuu行和\uuuuuu文件宏才能提供源文件和行号。然而,这是相当令人不快,效率低下等。。。始终必须指定这两个参数 这就是我的代码的样子: namespace Debug { void Assert (

我的应用程序使用标准输出以外的另一个输出来记录信息,这就是我编写自己的
Log()
Error()
Panic()
Assert()
函数的原因。为了很好地组织事情,我将所有调试内容封装在
Debug
名称空间中

如果
Assert()
函数还提供源文件和行号,则更有意义,因为只有使用
\uuuuuuuuuuu行
\uuuuuu文件
宏才能提供源文件和行号。然而,这是相当令人不快,效率低下等。。。始终必须指定这两个参数

这就是我的代码的样子:

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++吗?如果没有,有什么方法可以实现这一点吗?

\define
是一个预处理器指令。除了删除注释(也就是说,在编译之前),宏将被替换。因此,在替换宏时,编译器对名称空间一无所知

正如其他人所说,对你来说,一切都会好起来的。但是,这是您遇到问题的方式:

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");
}
而不是

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

是的,您的宏将扩展到您所期望的范围

Debug::Assert (some_condition, "Some_condition should be true");
将由

Debug::Assert_(some_condition, "Some_condition should be true", __FILE__, __LINE__)

不,预处理器根本不关心名称空间。事实上,预处理器至少在概念上是在编译器看到任何东西之前运行的

就我自己而言,我只是做了一个标准的ASSERT宏,并期望没有“健全的名称空间”有所谓的ASSERT。问题解决了。如果我需要一个有自己主张的图书馆,那么我仍然可以决定如何处理这个问题;然而,我目前使用的唯一一个带有自己的“assert”的库称之为BOOST\u assert或类似的东西

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"); 
此特定用法将完全满足您的要求,但Assert宏绝不是调试命名空间的一部分。。。就好像你做了:

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"); 
在这里,替换工作不是因为
Assert
Debug
命名空间中(它不在您的代码或此代码中,预处理器不知道命名空间是关于什么的)-它工作是因为
Assert
被识别为宏的标识符,对
Assert
进行替换,随后,编译器碰巧发现有一个
Debug::Assert\uu
因此,假设您在翻译单元的后面有一些完全不相关的代码:

my_object.Assert(my_functor);
宏替换仍然会产生编译时错误,表示宏的参数数目错误。假设不相关的代码是:

my_object.Assert(my_functor, "some text");
然后,将替换为:

my_object.Assert_(my_functor, "some text", __FILE__, __LINE__);

(另外,标准做法是在预处理器宏名称中不使用小写字母)。

您可以尝试使用uu PRETTY_FUNCTION uuu宏打印所有名称空间,包括函数参数。

@Tibi-方法是不使用
s。使用命名空间中定义的常量或内联函数。为什么它不起作用<代码>断言将扩展到
断言
,并带有额外的2个参数。问题是什么?@鲁基安格里戈-“问题”在TITME中:“是否可以在C++中的命名空间中放置宏?”KielkiRov,你在那里失去了我。调用函数时,如何使用常量和内联函数获取行和源文件?@KirilKirov我不认为这是个问题。您可以将宏放在任何位置。这可以工作,但宏不是命名空间的一部分。@PaulR因此,换句话说,如果我省略
Debug::
,宏仍然可以工作?否-您仍然需要命名空间前缀(因为您所做的只是在预处理器中将
Assert
转换为
Assert
)-问题是,如果您在名称空间之外使用
Assert
,它仍然会被翻译,这可能不是您想要的。
另外,标准做法是在预处理器宏名称中不使用小写字母
。我知道,但以WindowsAPI为例。有许多宏不遵守这种做法,因此它们调用另一个函数的ascii/unicode版本。虽然这可能是解决问题的一个有价值的提示,但确实需要一个答案来演示解决方案。请提供示例代码来说明您的意思。或者,考虑将此写入评论。
my_object.Assert_(my_functor, "some text", __FILE__, __LINE__);