c++ - 如何制作简化版的 boost::variant?

标签 c++ templates c++11 void variant

我有一组更简单的要求,不需要太多变体的机制。如果可以的话,我也不想依赖 boost。

我需要存储编译时已知的任意类型(可能是 void )。它要么是可移动构造的,要么是可复制构造的,如果其中任何一个抛出异常,则允许包含的值未定义。

除了这个值,它还可以包含 ::std::exception_ptr::std::error_code .

::boost::variant<T, ::std::exception_ptr, ::std::error_code>如果 T 会起作用允许无效。除了 ::boost::variant提供我在这种情况下实际上不需要的“永不空保证”。而且,如果我理解它是如何正确工作的,它与可以移动但不能复制的类型不太兼容。

现在我正在编写大量重复的代码,我不应该编写这些代码来分别处理这些类型中的每一种。我还存储了每种类型的对象的拷贝和标志值,说明哪个是相关的。最后,void给整个系统 conniptions 并要求我在所有地方编写特化。

有没有更好的办法?

这是我所拥有的一个简化示例。这基本上是一个类,旨在保存要传输到另一个线程的结果,有点像 future :

template <typename ResultType>
class stored_result {
 public:
   stored_result() : is_val_(false), is_err_(false), is_exception_(false) { }

   void set_bad_result(::std::error err) {
      is_err_ = true;
      error_ = ::std::move(err);
   }
   void set_bad_result(::std::exception_ptr exception) {
      is_exception_ = true;
      exception_ = ::std::move(exception);
   }
   void set_result(ResultType res) {
      is_val_ = true;
      val_ = ::std::move(res);
   }

   ResultType result() {
      if (is_val_) {
         is_val_ = false;
         return ::std::move(val_);
      } else if (is_exception_) {
         is_exception_ = false;
         ::std::rethrow_exception(::std::move(exception_));
      } else if (is_error_) {
         is_error_ = false;
         throw ::std::system_error(error_);
      } else {
         throw ::std::runtime_error("Asked for result when there was none.");
      }
   }

 private:
   bool is_val_, is_err_, is_exception_;
   T val_;
   ::std::exception_ptr exception_;
   ::std::error_code error_;
};

最佳答案

如何使用您现在拥有的代码以透明方式处理 void 的示例:

struct empty_type {};

template<typename T>
using Store = typename std::conditional<std::is_void<T>::value, empty_type, T>::type;

template<typename T>
T&&
restore(T&& t)
{
    return std::forward<T>(t);
}

void
restore(empty_type)
{}

template <typename ResultType>
class stored_result {
public:
    // snipped everything that is left unchanged

    template<
        typename U = ResultType
        , typename std::enable_if<
            !std::is_void<U>::value
            , int
        >::type = 0
    >          
    void set_result(U res) {
        is_val_ = true;
        val_ = std::move(res);
    }

    template<
        typename U = ResultType
        , typename std::enable_if<
            std::is_void<U>::value
            , int
        >::type = 0
    >          
    void set_result() {
        is_val_ = true;
    }

    ResultType result() {
        if (is_val_) {
            is_val_ = false;
            return restore(std::move(val_));
        } else if {
            // rest as before
    }

private:
    Store<T> val_;
};

尽管代码未经测试,但可能存在一些问题。

关于c++ - 如何制作简化版的 boost::variant?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9986595/

相关文章:

c++ - 如何编写以可变参数作为模板参数的成员函数

c++ - 在重载的 operator new 中初始化类成员是否未定义?

c++ - 如何在 C++ 中移动、交换和比较快速排序的计数

templates - 如何从宏创建参数化类型?

c++ - 我可以检查哪些函数模板至少实例化过一次吗?

c++ - 抛出 'std::bad_alloc' 实例后调用终止

c++ - 在模板类上调用的析构函数过多 (N)RVO 优化

c++ - C++命名空间中的名称解析规则是什么?

c++ - 模板和函数重载

c++ - 如何将 vector 转换为 Armadillo 矩阵?