Rumah >pembangunan bahagian belakang >C++ >Bolehkah Senarai-Inisialisasi Mengendalikan Vektor Jenis-Jenis Sahaja dalam C?

Bolehkah Senarai-Inisialisasi Mengendalikan Vektor Jenis-Jenis Sahaja dalam C?

DDD
DDDasal
2024-12-24 16:41:14915semak imbas

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

Bolehkah Senarai-Inisialisasi Digunakan dengan Vektor Jenis Alih Sahaja?

Apabila memulakan vektor dengan jenis bergerak sahaja menggunakan sintaks permulaan senarai, GCC cuba menyalin unique_pointers ke dalam vektor. Tingkah laku ini berpunca daripada fakta bahawa unique_ptrs tidak boleh disalin.

Adakah GCC Betul dalam Percubaan Menyalin Penunjuk?

Tingkah laku GCC dalam kes ini adalah tidak betul. Vektor unique_ptrs tidak boleh dibina dengan menyalin penunjuk; sebaliknya, semantik bergerak mesti digunakan.

Penyelesaian Alternatif

Untuk memulakan vektor jenis bergerak sahaja dengan betul, anda perlu menggunakan std::make_move_iterator untuk cipta iterator yang menggerakkan elemen yang ditunjuk apabila dialih rujukan:

#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))};
}

Pendekatan Tambahan

Alternatif lain, walaupun tidak semudah itu, melibatkan penggunaan std::enable_if dan penolong struct rref_wrapper untuk membina vektor pergerakan -jenis sahaja:

#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;

Menggunakan pembantu ini, vektor boleh dimulakan dalam dua langkah:

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());

Pendekatan ini menggunakan std::enable_if untuk memastikan rref hanya boleh digunakan pada sementara, dengan itu mengelakkan sebarang kemungkinan penyalahgunaan.

Atas ialah kandungan terperinci Bolehkah Senarai-Inisialisasi Mengendalikan Vektor Jenis-Jenis Sahaja dalam C?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn