【发布时间】:2020-08-03 23:36:36
【问题描述】:
我想对库 (seastar) 的 API 进行重大更改,但不会影响用户。所以我想为客户提供一种按照自己的节奏迁移到新 API 的方法。为此,我想使用内联命名空间。基本思想很简单,您为旧版本引入namespace v1,为新版本引入inline namespace v2(或相反)。这在https://foonathan.net/2018/11/inline-namespaces/ 中有很好的描述。当您想要引入另一个重大更改时,麻烦就开始了,namespace v3。让我们有一些示例代码作为进一步讨论的基础:
namespace v1 {
int foo(); // old version of foo
}
inline namespace v2 {
std::string foo(); // new, incompatible version of foo
int bar(); // old version of bar
}
namespace v3 {
std::string bar(); // new, incompatible version of bar
}
现在如果我想将默认的 API 版本更新为 v3,即默认使用 v3 版本的bar(),我可以将namespace v3 设置为inline。我们遇到了困境:如果我只做 v3 inline 我会破坏我的客户,他们已经迁移到使用最新的v2 版本的foo()(因此正在使用它)没有命名空间限定符)。如果我同时创建v2 和v3 inline,以便可以在全局(库)命名空间中访问所有函数的最新版本,我会在v3::bar() 和v2:bar() 之间引入歧义。如果我将 v2::foo() 移动到 v3,我会破坏刚开始迁移到 v2::foo() 并使用完全限定名称 (::v2::foo()) 的客户。另一种选择是在与最新 API 版本相对应的命名空间中重新声明所有最新版本的函数,并仅生成 inline。这是很多重复和一些额外生成的代码。有没有更优雅的解决方案?
我还被建议只在inline namespace v3 中使用using v2::bar(等等)将所有符号的最新版本导出到最新的内联命名空间中。然而,据我所知,这会破坏 ADL。
【问题讨论】:
标签: c++ api-design