我遇到了一对非常奇怪的编译器警告,看起来相互矛盾。以下是我写的代码:
#include <functional>
#include <iostream>
namespace {
std::function<void()> callback = [] {
void theRealCallback(); // Forward-declare theRealCallback
theRealCallback(); // Invoke theRealCallback
};
void theRealCallback() {
std::cout << "theRealCallback was called." << std::endl;
}
}
int main() {
callback();
}
换句话说,我在未命名的命名空间中定义了一个 lambda 函数,该函数前向声明稍后在该未命名的命名空间中定义的函数。
当我使用 g++ 7.4.0(Ubuntu 7.4.0-1ubuntu1~18.04.1)编译此代码时,会出现以下两个警告:
CompilerWarningsNamespace.cpp:6:10: warning: ‘void {anonymous}::theRealCallback()’ used but never defined
void theRealCallback();
^~~~~~~~~~~~~~~
CompilerWarningsNamespace.cpp:10:8: warning: ‘void {anonymous}::theRealCallback()’ defined but not used [-Wunused-function]
void theRealCallback() {
^~~~~~~~~~~~~~~
这很奇怪,因为第一个警告说我在使用未定义的函数,第二个警告说我在定义没有使用的函数。
运行这个程序确实会产生输出。
theRealCallback was called.
程序正常终止。
有趣的是,如果我不使用匿名命名空间,而是给命名空间指定一个名称,这些警告就会消失,如下所示:
#include <functional>
#include <iostream>
namespace NamedNamespace {
std::function<void()> callback = [] {
void theRealCallback();
theRealCallback();
};
void theRealCallback() {
std::cout << "theRealCallback was called." << std::endl;
}
}
int main() {
NamedNamespace::callback();
}
修改后的代码与原始代码一样,会打印出一条消息,指示已调用theRealCallback
。
有人能解释一下为什么我会收到这些警告吗?我猜测这可能与在 lambda 函数中的函数前向声明被解释为不同于出现在未命名命名空间中的后续函数有关,但如果是这样,我不确定为什么最终会链接并且为什么我会收到这些警告。