混合boost :: optional和std :: unique_ptr

use*_*462 5 c++ optional unique-ptr c++11

我承认:我爱上了可选的概念.自从我发现它以来,我的代码质量已经提高了很多.明确变量是否有效比明确错误代码和带内信令要好得多.它还让我不必担心必须阅读文档中的合同,或担心它是否是最新的:代码本身就是合同.

也就是说,有时我需要处理std::unique_ptr.此类型的对象可能为null或不为null; 在代码中的给定点,不可能知道是否std::unique_ptr应该有值; 从代码中知道合同是不可能的.

我想以某种方式混合optional(可能与boost::optional)和std::unique_ptr,以便我有一个动态分配的对象具有范围破坏和正确的复制/移动行为,明确表明它可能没有值.这样,我可以使用这种新类型来明确表示需要检查值并避免对plain进行不必要的检查std::unique_ptr.

在C++ 11标准中是否有这样的工具,boost或者是一个足够流行的库?我可以接受为此定义我自己的类,但这将是最不受欢迎的方法(由于缺乏彻底的测试).

Art*_*cca 5

所以要回顾一下你的问题,你想要:

  1. 由值/在堆栈上分配的非可选类型:您很高兴直接使用对象类型.
  2. 由值/在堆栈上分配的可选类型:您很乐意使用boost::optional它(或者您可以使用std::optionalC++ 17).
  3. 在堆上分配并拥有指向对象的非可选类型.
  4. 在堆上分配并拥有指向对象的可选类型.

您不能表达1和2之间的差异,但3和4通常使用相同的类型(std::unique_ptr).你建议使用std::unique_ptr3,永不允许nullptr,以及4的其他东西,但想知道你可以使用什么.(在评论你也接受使用的可能性std::unique_ptrnullptr,如果别的东西可以为3.找到4)

对你的问题的直译答案:你可以简单地使用boost::optional<std::unique_ptr<T>>4(当unique_ptr你建议使用裸3时).

你的问题的替代字面答案:正如@StoryTeller所说,你可以定义自己的智能指针类型,就像unique_ptr但不允许nullptr,并将其用于3.更快(但非常脏)的替代方法是强制函数返回pair两者的unique_ptr以及对同一个对象的引用.然后只能通过引用访问结果,但只有在unique_ptr仍然存在时才这样做:

template<class T>
using RefAndPtr = std::pair<T&, std::unique_ptr<T>>;

RefAndPtr<Foo> getFoo()
{
    std::unique_ptr<Foo> result = std::make_unique<Foo>();
    return RefAndPtr<Foo>(*result, std::move(result));
}
Run Code Online (Sandbox Code Playgroud)

我的实际建议:只需将它吸干并std::unique_ptr用于3和4两个.在类型系统中明确你的意图是一件好事,但太多好事可能会很糟糕.使用上述任一选项只会让任何读取代码的人感到困惑.即使你阻止人们错误地传递nullptr,有什么阻止他们将指针传递给错误的对象,或者已经释放的内存等等?在某些时候,您必须指定类型系统之外的东西.

  • 您也可以使用`gsl :: not_null <std :: unique_ptr <T >>`作为约定. (2认同)