【问题标题】:Implementing boost::optional in c++11在 C++11 中实现 boost::optional
【发布时间】:2012-08-06 04:25:37
【问题描述】:

我正在尝试使用 c++11 特性实现类似数据结构的 boost::optional。这是我到目前为止所拥有的:

template<typename T>
struct maybe {
  bool valid;

  union {
    T value;
  };

  maybe() : valid(false) {}
  maybe(const T& _v) {
  valid = true;
    new (&value) T(_v);
  }
  maybe(const maybe& other) {
    if (other.valid) {
      valid = true;
      new (&value) T(other.value);
    }
    else valid = false;
  }

  ~maybe() {
     if (valid)
       value.~T();
  }

  bool is_valid() { return valid; }

  operator T&() {
    if (valid) return value;
    throw std::bad_exception();
  }
};

我利用不受限制的联合功能为可以就地存储的可选值创建正确对齐的空间,而不是动态分配空间。事情大部分都有效,除非我想创建一个带有引用的可能。例如maybe&lt;int&amp;&gt; 导致 g++ 4.7 抱怨:

error: ‘maybe<int&>::<anonymous union>::value’ may not have reference type ‘int&’
because it is a member of a union

我应该怎么做才能使可能的类存储引用?也欢迎对课程提出任何其他改进/建议。

【问题讨论】:

    标签: c++ c++11 maybe boost-optional


    【解决方案1】:

    要使用引用进行这项工作,您肯定需要明确的特化,因为您不能对引用进行放置新:您需要使用指针进行存储。

    除此之外,代码缺少复制赋值运算符。移动构造函数和移动赋值运算符也很好(特别是因为这是重新实现 boost::optional 的第一大原因:boost 中缺少它们)。

    【讨论】:

    • “这使得你的类不能使用非默认的可构造类型”但这不是真的。该标准似乎表明工会成员禁止自动初始化和销毁​​。
    • 顺便说一句,alignas(T) char data[sizeof(T)] 似乎比你所拥有的更 C++11-ish。
    • @keveman 这可能是aligned_storage 的实现方式。我发现aligned_storage 对其业务的了解更加明确。
    • @rmartinho 对于每个人,他自己的。委员会煞费苦心地将aligned_storage 习语移到了语言本身,所以我不想在语言特性上使用库包装器。
    • @keveman 关于默认可构造性,这很有趣。能否请您参考相应的标准部分?
    【解决方案2】:

    可选类型是为 C++14 提出的,但由于标准中未定义行为的一些极端情况,它被推迟到 C++17。

    幸运的是,UB 问题对大多数人来说应该无关紧要,因为所有主要编译器都正确定义了它。因此,除非您使用旧的编译器,否则您实际上可以在项目中放入可用于实现可选类型的代码(它只是一个头文件):

    https://raw.githubusercontent.com/akrzemi1/Optional/master/optional.hpp

    那么你可以这样使用它:

    #if (defined __cplusplus) && (__cplusplus >= 201700L)
    #include <optional>
    #else
    #include "optional.hpp"
    #endif
    
    #include <iostream>
    
    #if (defined __cplusplus) && (__cplusplus >= 201700L)
    using std::optional;
    #else
    using std::experimental::optional;
    #endif
    
    int main()
    {
        optional<int> o1,      // empty
                      o2 = 1,  // init from rvalue
                      o3 = o2; // copy-constructor
    
        if (!o1) {
            cout << "o1 has no value";
        } 
    
        std::cout << *o2 << ' ' << *o3 << ' ' << *o4 << '\n';
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-19
      • 2021-01-22
      • 2014-09-15
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 2019-12-27
      • 2012-04-11
      • 2015-06-17
      相关资源
      最近更新 更多