Эмуляция встроенного пространства имен для MSVC (10.0 / 11.0)

#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.