Можно ли использовать встроенные пространства имен для обеспечения обратной совместимости в общей библиотеке?

Обоснование для внутренних пространств имен С++ является как исходной, так и двоичной совместимостью (см. документ Герба Саттера, связанный в N2535), но у меня есть не смогли найти хороших примеров сохранения двоичной совместимости для существующих библиотек при введении встроенных пространств имен или, если это возможно.

(для получения дополнительной информации и примеров совместимости источников см. этот вопрос)

(для решения связанной задачи, используя встроенное пространство имен для представления несовместимости, см. этот вопрос)

Если это наша текущая библиотека (например, mylib.dll), которая используется совместно с клиентами и должна быть стабильной:

struct ModelA
{
   /* (...) lots of stuff */
};

struct ModelB
{
   /* (...) lots of stuff */
};

Можем ли мы использовать inline namespaces для представления новых версий структур/классов без разрыва клиентов (т.е. заменить файл общей библиотеки (mylib.dll), не обязательно перекомпилировать)?

inline namespace mylib
{

inline namespace v1
{
struct ModelA
{
   /* (...) lots of stuff */
};
} // end namespace v1

namespace v2
{
struct ModelA
{
   /* (...) lots of stuff + newstuff */
};
} // end namespace v2

struct ModelB
{
   /* (...) lots of stuff */
};

} // end namespace mylib

Если нет, будет ли он работать без встроенного пространства имен mylib?

Ответ 1

Не совсем ответ на ваш вопрос, но, вероятно, может привести к ответу.

Протестировано под gcc 4.8.2 двумя простыми источниками:

namespace n1
{
   void f1 (int);

   inline namespace n2
   {
      void f2 (int);
   }
}

void f (int x)
{
   n1::f1(x);
   n1::f2(x);
}

И без встроенного пространства имен:

namespace n1
{
   void f1 (int);
   void f2 (int);
}

void f (int x)
{
   n1::f1(x);
   n1::f2(x);
}

Затем проверены искаженные имена символов в скомпилированных объектных файлах с помощью objdump -t.

Результаты для первой версии (с встроенным пространством имен):

_ZN2n12f1Ei
_ZN2n12n22f2Ei

Вторая версия (без встроенного пространства имен):

_ZN2n12f1Ei
_ZN2n12f2Ei

Вы можете видеть, что измененное имя f2 отличается (первое включает имя пространства имен n2). Это означает, что в случае, если вы используете gcc, вы не можете просто заменить свою библиотеку на новую с помощью встроенных пространств имен. Я не буду ожидать, что какой-нибудь другой компилятор сделает это по-другому (сохраните двоичную совместимость с внутренними пространствами имен).