Каков переносимый способ объявления классов вперед во встроенном пространстве имен в libC++?
Следующий код не компилируется только когда я указываю -stdlib=libc++
в clang++
:
namespace std {
class mutex;
}
void f(std::mutex &x);
#include <mutex>
void f(std::mutex &x) { }
- http://goo.gl/Uqpv6f (gcc.godbolt.org)
примечание: кандидат найден по имени поиска 'std::__1::mutex'
Я понимаю что такое ::__1
там,
но на мой взгляд, libc++
нарушает API, определенный стандартом C++:
- http://en.cppreference.com/w/cpp/thread/mutex (ну, это не совсем стандарт...)
Должна быть возможность заранее объявить std::mutex
потому что он должен находиться непосредственно под std
не так ли?
Обратите внимание, что фаза компиляции, а не фаза компоновки, терпит неудачу. Поэтому я не думаю, что ответ на мой вопрос должен быть таким, как "потому что в libC++ используется другой ABI, чем в GNU libstdC++..."
1 ответ
но, на мой взгляд, libC++ нарушает API, определенный стандартом C++:
На самом деле это не так. Стандарт указывает на [содержание]:
Не указано, объявлены ли имена, объявленные в определенном пространстве имен, непосредственно в этом пространстве имен или во встроенном пространстве имен внутри этого пространства имен.
libC++ разрешено ставить mutex
в inline namespace __1
, Обратите внимание, что есть веские причины для того, чтобы хотеть встроенные пространства имен, и, как правило, как пользователь, вам даже не важно, существуют они или нет.
На ваш конкретный вопрос вы все еще можете переслать std::mutex
с libC++... вам просто нужно включить все пространства имен (см. этот вопрос, чтобы узнать, как определить -std=libC++):
namespace std {
#ifdef _LIBCPP_VERSION
inline namespace __1 {
struct mutex;
}
#else
struct mutex;
#endif
}
Однако из [namespace.std]:
Поведение программы на C++ не определено, если она добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен std, если не указано иное.
Форвардное объявление все еще является объявлением, поэтому даже приведенная выше версия, которая учитывает встроенные пространства имен, является неопределенным поведением. Поэтому предпочитаю делать это прямым способом:
#include <mutex>