如何在C++中更改函数的返回类型时弃用函数

6
有哪些策略可以在函数返回类型需要更改时使其废弃?例如,我有以下代码:
BadObject foo(int); // Old function: BadObject is being removed. 
Object    foo(int); // New function. 

ObjectBadObject在内部非常不同,交换它们的返回类型将会破坏当前使用我的库的用户的代码。我希望避免这种情况。

我可以将BadObject foo(int)标记为已弃用,并给用户时间来更改受影响的代码。
然而,我无法根据返回类型重载foofoo的命名非常好,不需要添加额外的参数。如何在保留旧版本的同时向我的库中添加新函数,至少要有一段时间?

如何在不破坏太多相关代码的情况下弃用旧函数,同时提供用户迁移到新版本的时间?理想情况下,我想保留当前的函数名称和参数列表,因为它现在已经命名得很好了。这似乎应该是一个相当常见的问题:有什么好的解决方法?


如果用户在任何地方都使用自动功能,而不是手动输入返回类型,那么一切都会自动工作 :). - ScarletAmaranth
这对您现在没有帮助,但是C++11的内联命名空间非常适合此类情况。在inline namespace v0中声明foo,当需要更改时,在inline namespace v1中声明foo'(并从v0中删除inline)。 - mythagel
3个回答

4
尽管这个解决方案 将会 强制您更改函数名称,但它将是旧用户和新用户之间的一种妥协。
因此,请将旧的foo重命名为deprecatedFoo,将新的foo重命名为foo2(或其他任何名称)。然后,在您包含在库中的头文件中,您只需:
#define deprecatedFoo foo

并且在函数内部执行:

#warning ("This function is deprecated. Use 'foo2' or change the #define in LINE in file HEADER.")

旧版本的用户不需要更改他们的代码,只会收到警告,而新用户可能会听取并更改#define以使用新的foo

在下一个版本中,您只需删除旧的foodefine即可。


1
你的意思是要反过来 #define 吗?如果不改变,新函数的用户将会得到和旧函数用户一样多的警告。 - aschepler
新版本的用户应该收到警告,这样他们就可以(如果愿意)进行更改。如果您以相反的方式进行了#define,则代码将与旧版本不兼容。但我想这是一个由OP决定的选择,我们不是讨论这个问题的人。 - Paweł Stawarz

0

我认为一个经典的例子是Boost's Spirit

从他们的FAQ中:

在介绍 Spirit V2 的同时,我们重新构建了目录结构,以便同时容纳两个版本。现在,所有的 Spirit.Classic 都存放在目录 boost/spirit/home/classic 中。上面的目录包含转发头文件到新位置,以保持应用程序的兼容性。转发头文件会发出警告(从 Boost V1.38 开始),告诉用户更改其包含路径。请预计上述目录/转发头文件很快就会消失。
这解释了目录 boost/spirit/include 的必要性,其中也包含转发头文件。但是这次头文件不会消失。我们鼓励应用程序编写者仅使用此目录中包含的头文件。这使我们可以重新构建底层目录,而不必担心应用程序的兼容性。请仅在您的应用程序中使用这些文件。如果发现缺少某个转发文件,请将其报告为错误。
您可以通过将新旧版本保存在单独的目录中并使用转发头文件来维护兼容性来简化迁移。最终用户将被迫使用新的头文件。

SDL 2.0采用了不同的方法。他们没有提供兼容性层,而是提供了一个迁移指南,引导用户完成最重要的更改。在这种情况下,您可以帮助用户理解他们需要如何重构代码。


0
如果让你的Object类继承自BadObject类(暂时保留),会怎样呢?那么旧的用户代码就不会知道这一点,只要你的新“foo”函数仍然正确地返回对象,它就不会出错。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接