如何让普通的 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、nvcc、msvc、icc。我特别关心 nvcc(CUDA 编译器)和 gcc。
- 除了名称空间和我将在输出中寻找的一些 "marker text" 之外,我更喜欢尽可能少的 "noise"。
- 有点相关的问题:How to get string for current namespace in Macro
这取决于编译器及其版本。当前适用于所有 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
}
我试图弄清楚在一堆代码中我遗漏了命名空间的右括号(即获取:
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、nvcc、msvc、icc。我特别关心 nvcc(CUDA 编译器)和 gcc。
- 除了名称空间和我将在输出中寻找的一些 "marker text" 之外,我更喜欢尽可能少的 "noise"。
- 有点相关的问题:How to get string for current namespace in Macro
这取决于编译器及其版本。当前适用于所有 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
}