可以使用内联命名空间来保持共享库的向后兼容性吗?
Can inline namespaces be used to keep backwards compatibility in a shared library?
C++ 内联命名空间的基本原理是源代码和二进制兼容性(参见 N2535 中链接的 Herb Sutter 的论文),但我没能找到保持 引入内联命名空间时现有库的二进制兼容性,或者如果可能的话。
(有关更多信息和源兼容性示例,请参阅 this question)
(解决一个相关问题,使用inline namespace引入不兼容,见this question)
如果这是我们当前的库(例如mylib.dll),与客户共享并且需要稳定:
struct ModelA
{
/* (...) lots of stuff */
};
struct ModelB
{
/* (...) lots of stuff */
};
我们能否使用内联命名空间引入新版本的 structs/classes 而不会破坏客户端(即仅替换共享库文件 (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 的情况下工作?
不是你问题的真正答案,但可能会导致答案。
在 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
,您不能只用一个具有内联命名空间的新库替换您的库。我不希望其他一些编译器会以另一种方式来做(保存与内联命名空间的二进制兼容性)。
C++ 内联命名空间的基本原理是源代码和二进制兼容性(参见 N2535 中链接的 Herb Sutter 的论文),但我没能找到保持 引入内联命名空间时现有库的二进制兼容性,或者如果可能的话。
(有关更多信息和源兼容性示例,请参阅 this question)
(解决一个相关问题,使用inline namespace引入不兼容,见this question)
如果这是我们当前的库(例如mylib.dll),与客户共享并且需要稳定:
struct ModelA
{
/* (...) lots of stuff */
};
struct ModelB
{
/* (...) lots of stuff */
};
我们能否使用内联命名空间引入新版本的 structs/classes 而不会破坏客户端(即仅替换共享库文件 (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 的情况下工作?
不是你问题的真正答案,但可能会导致答案。
在 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
,您不能只用一个具有内联命名空间的新库替换您的库。我不希望其他一些编译器会以另一种方式来做(保存与内联命名空间的二进制兼容性)。