首页 >后端开发 >C++ >C 中列表初始化能否正确处理仅移动类型的向量?

C 中列表初始化能否正确处理仅移动类型的向量?

DDD
DDD原创
2024-12-24 16:41:14920浏览

Can List-Initialization Correctly Handle Vectors of Move-Only Types in C  ?

列表初始化可以与仅移动类型的向量一起使用吗?

使用仅移动类型初始化向量时列表初始化语法中,GCC 尝试将 unique_pointers 复制到向量中。此行为源于 unique_ptr 不可复制的事实。

GCC 尝试复制指针是否正确?

GCC 在这种情况下的行为不正确。 unique_ptrs 的向量不能通过复制指针来构造;相反,必须使用移动语义。

替代解决方案

要正确初始化仅移动类型的向量,有必要使用 std::make_move_iterator 来创建迭代器来移动指向的元素取消引用:

#include <iterator>
#include <vector>
#include <memory>

int main() {
  using move_only = std::unique_ptr<int>;
  move_only init[] = { move_only(), move_only(), move_only() };
  std::vector<move_only> v{std::make_move_iterator(std::begin(init)),
      std::make_move_iterator(std::end(init))};
}

其他方法

另一种替代方法,虽然不那么简单,但涉及使用 std::enable_if 和辅助结构 rref_wrapper 来构造移动向量-仅限类型:

#include <utility>
#include <type_traits>

template<class T>
struct rref_wrapper
{ // CAUTION - very volatile, use with care
  explicit rref_wrapper(T&amp;&amp; v)
    : _val(std::move(v)) {}

  explicit operator T() const{
    return T{ std::move(_val) };
  }

private:
  T&amp;&amp; _val;
};

// only usable on temporaries
template<class T>
typename std::enable_if<
  !std::is_lvalue_reference<T>::value,
  rref_wrapper<T>
>::type rref(T&amp;&amp; v){
  return rref_wrapper<T>(std::move(v));
}

// lvalue reference can go away
template<class T>
void rref(T&amp;) = delete;

使用此助手,向量可以分两步初始化:

std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()),
                                                   rref(move_only()),
                                                   rref(move_only()) };
std::vector<move_only> v(il.begin(), il.end());

此方法利用 std::enable_if 来确保 rref 只能用于临时变量,从而防止任何潜在的误用。

以上是C 中列表初始化能否正确处理仅移动类型的向量?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn