首頁 >後端開發 >C++ >C 中列表初始化能否正確處理僅移動類型的向量?

C 中列表初始化能否正確處理僅移動類型的向量?

DDD
DDD原創
2024-12-24 16:41:14915瀏覽

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