将nullptr“回移”到C++0x之前的程序中

10
更或者少就是标题所说的。虽然我还没有使用C++0x,但我希望为它到来做好准备,并且我也想减少我需要重写来使用一些新功能的代码量。这样我就可以一次性实现向前和向后兼容。
我发现最有趣的之一是nullptr,最近我已经经常在使用它了。
在检查了“官方解决方法”和Meyer的建议之后,我决定要在我的C++和未来的C++0x程序中都使用它。第二部分很简单——作为关键字,nullptr将被支持。但第一部分让我感到有些不舒服。
Meyers提案的功能如下:
class nullptr_t { // ← this is my issue
    // definition of nullptr_t
} nullptr = { };

该提议的问题在于它声明了类型必须被声明为C++0x所需的std::nullptr_t。这意味着为了让解决方法“感觉本地”,必须通过重新打开std::命名空间来添加类型。我理解在C++程序中这是非法的(与添加特化不同,后者显然是不受欢迎但可以放行并带有警告)。
我想以一种舒适且合法的方式在C++程序中使用nullptr。我曾考虑过在另一个命名空间中声明该类型,然后使用using将其引入:
namespace mylibrary {
class nullptr_t {
    ....
} nullptr = { };
// end namespace
}

// These would have to go in the header file.
using mylibrary::nullptr;
using mylibrary::nullptr_t; // apparently this is necessary as well?

这样做是正确的吗?它会强制使用using指令,这也强制了特定顺序的#include指令。我是否可以期望没有任何早于C++0x的代码会请求带有命名空间的nullptr_t类型(例如作为函数参数类型)?如果这样做,它是否会“感觉本地化”?


作为补充,尝试将一些C++0x的有用特性移植到C++以提高兼容性和编码是否受欢迎或不被赞同?同时,我已经将此解决方案和其他正在开发中的解决方案集成在即将发布的软件中
2个回答

3

除非你能想到一个需要声明另一个nullptr_t类型对象的原因(我想不到),否则我会隐藏该类型并将nullptr放在全局命名空间中,以最大程度地模拟关键字:

namespace mylibrary
{
    class nullptr_t
    {
        ....
    };
}

mylibrary::nullptr_t nullptr = { };

1
是的,隐藏类型是我想要做的。我更或多或少地担心是否有任何理由需要使用类型 nullptr_t 来完成无法通过简单传递 nullptr 或指针类型来完成的任何事情。 - Luis Machuca

1

不允许向namespace std添加内容的主要原因是您不会破坏已经存在的东西。否则,这很容易做到。我在过去发现的问题是多个定义用于内置类型实例化的容器的输出运算符,例如std::vector<int>。然而,在此命名空间中没有定义nullptr_t,添加一个typedef应该是相当无害的。也就是说,我将在与namespace std 不同的命名空间中定义nullptr_t,然后将nullptr_ttypedef添加到namespace std 中。变量nullptr需要在全局作用域中声明,因为它在C ++ 2011中未经限定地使用。

是否需要类型std::nullptr_t取决于您是否有兴趣添加使用此类型的函数。例如,std::shared_ptr<T>可以与nullptr进行比较。为此,必须添加适当的重载,提及类型std::nullptr_t(或使用此类型的其他名称)。


我一直认为不能向namespace std添加内容的原因不是为了避免破坏其中的内容,而是为了让你的代码能够在许多编译器上编译(这些编译器可能正在使用你选择的名称),并且当标准向std命名空间添加内容时,你的代码仍然可以编译。 - Mooing Duck
据我所知,“下划线”规则的存在正是为了让“实现”自由使用这些名称(只需查看任何一份<algorithm>的副本即可),因此除了标准提供的名称(如cincout)之外,在命名空间std中没有其他名称被保留;在那个点上,一个typedef不能比实际声明更有害于前向兼容性,除非它防止我们添加“过多”的内容(如“详细命名空间”)。 - Luis Machuca
啊,我稍微有点偏差。从https://dev59.com/KHVC5IYBdhLWcg3woSxW“保留一些标识符名称类别,以备将来扩展到C语言或POSIX.1环境。尽管现在为自己的目的使用这些名称可能不会导致问题,但它们确实提高了与C或POSIX标准的未来版本冲突的可能性,因此您应避免使用这些名称。…以“_t”结尾的名称被保留。” - Mooing Duck
@DietmarKühl:我检查了一下,C++11没有保留它们,只有POSIX。 - Mooing Duck
我可以接受 POSIX。我猜他们足够聪明,不会尝试定义 nullptr_t 类型。所以,如果我理解正确的话,"做到这一点"的方法是定义一个 nullptr_t 宏,或者一个 typedef? - Luis Machuca
显示剩余2条评论

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