#c #visual-c #namespaces #c 11 #inline-namespaces
#c #visual-c #пространства имен #c 11 #встроенные пространства имен
Вопрос:
Есть ли какой-либо способ эмулировать inline namespace
с помощью MSVC?
LIBC LLVM использует это для создания скрытого версионного пространства имен следующим образом:
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE {
#define _LIBCPP_END_NAMESPACE_STD } }
#define _VSTD std::_LIBCPP_NAMESPACE
namespace std {
inline namespace _LIBCPP_NAMESPACE {
}
}
И эмулирует его в GCC следующим образом:
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { namespace _LIBCPP_NAMESPACE {
#define _LIBCPP_END_NAMESPACE_STD } }
#define _VSTD std::_LIBCPP_NAMESPACE
namespace std {
namespace _LIBCPP_NAMESPACE {
}
using namespace _LIBCPP_NAMESPACE __attribute__((__strong__));
}
Теперь мой вопрос в том, как мне добиться того же с MSVC? Если это невозможно, я буду доволен решением, которое исключает управление версиями (на данный момент), что, я думаю, будет
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
#define _LIBCPP_END_NAMESPACE_STD }
#define _VSTD std
Но это как бы противоречит цели…
Ответ №1:
Боюсь, что такой эмуляции нет. Microsoft, похоже, очень не заинтересована в управлении версиями символов, даже несмотря на то, что они нарушают ABI в своей стандартной библиотеке при каждой новой редакции своего компилятора. Эмуляция GCC работает, потому что сильное использование было основой для функции встроенного пространства имен. У Microsoft никогда не было подобной вещи, поэтому вы не можете эмулировать встроенные пространства имен. Боюсь, на данный момент вы застряли без управления версиями libc .
В компиляторе Microsoft есть одна функция, которая может помочь. Это #pragma detect_mismatch: http://msdn.microsoft.com/en-us/library/ee956429.aspx
По сути, вы помещаете
#pragma detect_mismatch("libcxx_version", "1.0")
в центральный заголовочный файл libc , и в каждый модуль, включающий этот файл, будет помещена запись, содержащая ключ и значение. Компоновщик Microsoft проверяет при связывании модулей, что все такие записи имеют одинаковое значение для любого заданного имени, и жалуется, если есть несоответствие.
Конечным результатом является то, что вы не можете иметь несколько параллельных версий libc в одной программе, но, по крайней мере, вы не получите скрытого повреждения от связывания несовместимых объектных файлов, которые вызывают неприятные сбои во время выполнения.
Редактировать: забыл упомянуть: эта функция является новой в VS2010, но перенос libc на компилятор без ссылок rvalue, вероятно, в любом случае довольно безнадежен.
Комментарии:
1. На данный момент вы лидируете ;). Это другой метод для достижения практически того же результата.
2. Я вижу две возможные проблемы / недостатки в этом: 1) как эта прагма влияет на клиентский код? Как будет ограничено использование этой прагмы в клиентском коде для целей управления версиями? 2) Подход встроенного пространства имен был введен (я думаю), чтобы обеспечить средства будущей совместимости с ABI, которые в идеале сохраняли бы старые символы (хотя я могу ошибаться, это кажется логичным). Я боюсь, что этого будет недостаточно для этих целей и вообще лишит цели управления версиями.
3. 1) Не уверен, что вы имеете в виду. Вы можете использовать прагму так часто, как захотите, если ключ отличается. Компоновщик требует, чтобы все пары ключ-значение совпадали.
4. 2) Правильно, встроенные пространства имен допускают параллельные версии, а pragma detect_mismatch — нет. Он обеспечивает защиту только от объединения несовпадающих версий. Однако, учитывая, что я был укушен этим в прошлом, я благодарен, что теперь у нас есть хотя бы это от MS.