Я занимался портированием некоторого кода со старого 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 и везде?