将实验命名空间注入 std



下面这样将命名空间std::experimental注入std是坏事还是好事?

namespace std
{
namespace experimental
{
}
using namespace experimental;    
}
#include <experimental/optional>
int main()
{
    std::optional< int > o;
    return 0;
}

甚至以更现代的形式:

#if __has_include(<optional>)
# include <optional>
#elif __has_include(<experimental/optional>)
# include <experimental/optional>
namespace std
{
using namespace experimental;    
}
#else
#error !
#endif
int main()
{
    std::optional< int > o;
    return 0;
}

引入std::experimental"子命名空间"的意图很明确std::experimental,因为它目前包含大量库。我认为它们很可能在没有任何实质性更改的情况下迁移到namespace std,并且当前编写的用户代码可以依赖这一点(我完全错了吗?否则,所有这些代码都应重构,以便将来从std::experimental::更改为std::。这没什么大不了的,但可能有理由不这样做。

问题是关于生产代码和不太严肃的代码。

在工作中,我花了很多时间与这种投机复杂性作斗争(我正在寻找一个描述行为的好短语,这是我迄今为止想出的最好的短语(。

在我看来,你现在正在将复杂性和风险引入你的代码中,以避免将来重构。 这已经够糟糕的了,但在这种特殊情况下,我什至会说重构是一个糟糕的词选择——与其说是重构,不如说是简单的文本替换。

通过代码删除std::

experimental的(或更改为std::或std::something_else(实际上只是一个文本替换。 在最好的情况下,您正在编辑器或 ide 中查看快速命令。 在最坏的情况下,你会看到花几个小时编写一个正则表达式——也许在你的编辑器中,也许在 PERL 或 Ruby 中......

那些 std::experimental 表示您正在使用实验性功能,最好在代码中有一个显式语句来实现此效果。 如果某些库进入标准,称职的程序员可以快速轻松地进行必要的文本替换。 如果你的文本编辑技能不能胜任这项任务,不要破解语言——提高你的文本编辑技能。 这是一个机会。

更一般地说,现在编写满足您需求的最简单、最干净的代码,并准备好在情况发生变化时立即更改它。 这通常会产生更灵活的代码,比现在的推测更能支持您的实际未来需求。

听起来是个坏主意。

首先,这是未定义的行为。标准草案N4140说:

[namespace.std]/1: 除非另有指定,否则如果C++程序将声明或定义添加到命名空间std或命名空间std中的命名空间,则未定义它的行为。[...]

using指令是一种声明,因此UB是当天的订单。

其次,std::experimental的事情很容易发生变化。您可能会发现,当事情std适当地移动时,您的代码仍然可以编译,但行为方式并不完全相同。这只是自找麻烦,尤其是在生产代码中。

std::experimental中的许多库可以并且将会以在迁移到std之前破坏用户代码的方式进行更改,甚至可能不会迁移到std。 这就是为什么他们把它们放在std::experimental

.

std::experimental 旨在提供一个相对免费的地方,您可以在其中为C++引入新的建议库功能,编译器可以实现它们,而不会破坏现有代码。 实现是不断变化的,不是标准的。 其中一些可能会进入 C++1z,但其中一些可能不会,那些进入的人可能会被更改,而那些没有进入的人可能会通过实质性更改将其变成 C++2x。

只需查看Ranges的历史即可。 或者微软提出的协程/可恢复函数。 或者反思工作组。 或概念。

我敢说,这次迭代C++的目标是敏捷,并且快速失败。 许多独立提案都在管道中工作,目标是最大限度地减少相互依赖。 如果给定的提案在C++标准时还没有准备好进入黄金时间,它就不会进入。 如果它准备好了,并且值得,它就会被模块化添加。

这是(据我所知(明确这样做的,以避免流程的某些部分变得"太大而不能失败"的混乱,以及尚未准备好的事情发布到标准中,或者标准发布延迟多年因为某些东西没有准备好。

除此之外,以这种方式弄乱std会使您的程序格式不正确,无需诊断,正如其他答案所指出的那样。

你正在做的事情引入了未定义的行为。 一般而言,我会说引入未定义的行为更多地属于不良实践领域,而不是良好实践领域。

根据1998年C++标准第17.4.3.1节第1段。

对于C++程序添加声明或定义是未定义的 到命名空间 std 或命名空间 std 中的命名空间,除非另有说明 指定。程序可以为任何标准添加模板专用化 库模板到命名空间 std。这样的专业化(完整或 部分(导致未定义的行为 除非声明依赖于用户定义的外部名称 链接,除非专业化符合标准库 原始模板的要求。

我没有该标准的最新版本(在我当前的机器上(,但是,从内存中,C++标准的所有版本都有类似的条款。

最新更新