如何让普通的 C++ 编译器打印某行所在的命名空间?

How can I make common C++ compilers print the namespace a certain line is in?

我试图弄清楚在一堆代码中我遗漏了命名空间的右括号(即获取:

At end of source: error: expected a "}"

错误)。也许有更聪明的方法来解决它,但是 - 我想尝试在我的代码的不同点检查当前的命名空间是什么。我不需要宏;而且我不需要字符串;而且我不需要在 运行 时间存在的东西。我只想让编译器以某种方式打印名称空间。如果它在 #error#warning 或某些无法编译、产生其中的命名空间错误的结构中,我觉得没问题。

我想概括的例子:

namespace ns1 { }
namespace ns2 {
namespace ns3 {

// MAGIC GOES HERE

}

此源文件某处缺少 }。但是 - 我忘记关闭 ns1 了吗?或者也许是 ns2?我不记得了——它们离我感兴趣的那条线很远。所以我想插入一些神奇的东西,它会告诉我我现在所在的命名空间。好吧,对于这个例子,我可以这样写:

namespace ns1 { }
namespace ns2 {
namespace ns3 {

void ns_detector() { return 0; }

}

对于 GCC 6.3,出现错误:

b.cpp: In function ‘void ns2::ns3::ns_detector()’:
b.cpp:5:29: error: return-statement with a value, in function returning 'void' [-fpermissive]
 void ns_detector() { return 0; }
                             ^
b.cpp: At global scope:
b.cpp:7:1: error: expected ‘}’ at end of input
 }
 ^

该错误的第一行告诉我我需要知道的内容:尚未关闭的是 ns2。但是——这不是那么可靠。对于更长、更复杂的代码,我使用 nvcc 编译,使用 "ns detector" 函数只会给我这样的东西:

/path/to/file.cu(135): error: return value type does not match the function type

At end of source: error: expected a "}"

所以,我需要更强大的东西。

备注:

这取决于编译器及其版本。当前适用于所有 gcc、clang、icc 和 msvc 的一个(让我们知道它是否适用于 nvcc!)正在访问一个丢失的数据成员:

struct A { A() { this->a; } };

所有的编译器都会报告一个带有限定名的错误,例如:

error: no member named 'a' in 'foo::bar::A'

因此您可以轻松地 grep 查找 ::A'::A" 并提取它(所有这 4 个主要编译器都将名称放在引号之间;否则,只需使用您找不到的唯一标识符其他任何地方等)。

对@Acorn 好的简单解决方案的(可能)改进,可以使用 多次 次,用于在同一文件的多个位置进行检测:

#define CONCATENATE(s1, s2) s1##s2
#define EXPAND_THEN_CONCATENATE(s1, s2) CONCATENATE(s1, s2)
#define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_CONCATENATE(prefix, __LINE__)

#define DETECT_NAMESPACE \
struct UNIQUE_IDENTIFIER(namespace_detector_on_line_) { \
    void f() { look_at_the_class_name_above = 0; } \
};

现在您应该可以在许多不同的行上写 DETECT_NAMESPACE 了。此外,宏定义可以放在单独的文件中。

对于示例中的代码,这将给出:

b.cpp: In member function ‘void ns2::ns3::namespace_detector_on_line_13::f()’:
b.cpp:5:93: error: ‘look_at_the_class_name_above’ was not declared in this scope
 #define DETECT_NAMESPACE struct UNIQUE_IDENTIFIER(namespace_detector_on_line_) { void f() { look_at_the_class_name_above! = 0; } };
                                                                                             ^
b.cpp:13:1: note: in expansion of macro ‘DETECT_NAMESPACE’
 DETECT_NAMESPACE
 ^~~~~~~~~~~~~~~~
b.cpp: At global scope:
b.cpp:15:1: error: expected ‘}’ at end of input
 }