我正在研究将一些代码从较旧的 C++ 移植到更现代的 C++ 版本(例如 C++ 11 或更高版本)。然后我注意到当我添加编译器标志时一些网络代码无法编译-std=c++11
最简单的 MVCE 示例。我使用的是最新的 Cygwin(实际上是今天安装的)。g++ --version
表示版本7.3.0。
将以下源文件精简到几乎没有,但足以显示我将要解释的问题。
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
int some_networking_code()
{
addrinfo* addr = NULL;
int flags = AI_NUMERICHOST;
return 0;
}
在全新安装 Cygwin 时,以下命令可以正常工作:
g++ foo.cpp -c
但现在切换到使用 C++11 进行编译。
g++ foo.cpp -c -std=c++11
编译器的输出结果是:
foo.cpp: In function ‘int some_networking_code()’:
foo.cpp:8:4: error: ‘addrinfo’ was not declared in this scope
addrinfo* addr = NULL;
^~~~~~~~
foo.cpp:8:4: note: suggested alternative: ‘addr_t’
addrinfo* addr = NULL;
^~~~~~~~
addr_t
foo.cpp:8:14: error: ‘addr’ was not declared in this scope
addrinfo* addr = NULL;
^~~~
foo.cpp:8:14: note: suggested alternative: ‘addr_t’
addrinfo* addr = NULL;
^~~~
addr_t
foo.cpp:9:16: error: ‘AI_NUMERICHOST’ was not declared in this scope
int flags = AI_NUMERICHOST;
^~~~~~~~~~~~~~
调试这个,我看了一下/usr/include/netdb.h
我看到定义addrinfo
需要一个名为__POSIX_VISIBLE大于或等于200112
。 AI_NUMERICONLY 的定义包含在类似的块中。
#if __POSIX_VISIBLE >= 200112 && !defined(__INSIDE_CYGWIN_NET__)
struct addrinfo {
int ai_flags; /* input flags */
… <deleted for brevity>
#endif
使用-dM -E
开关,我们可以询问编译器它正在引入哪些宏并过滤到 POSIX_VISIBLE
$ g++ foo.cpp -c -dM -E | grep POSIX_VIS
#define __POSIX_VISIBLE 200809
好的,这对于传统 C++ 来说看起来是正确的。让我们检查一下 C++11 构建:
$ g++ foo.cpp -c -std=c++11 -dM -E | grep POSIX_VIS
#define __POSIX_VISIBLE 0
__POSIX_VISIBLE
被定义为 0。这解释了为什么我们会出现上述错误。
看起来POSIX_VISIBLE
由头文件定义/usr/include/sys/features.h
基于其他定义的宏。但这就是我开始感到困惑的地方。
这是 Cygwin 发行版或其头文件中的错误吗?编译器的构建方式是什么?或者是其他东西?什么是不会影响在 Linux、Mac、BSD 和其他地方构建的适当解决方法?