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
Lepaskan: 2024-12-24 16:41:14
asal
996 orang telah melayarinya

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))};
}
Salin selepas log masuk

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;
Salin selepas log masuk

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());
Salin selepas log masuk

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 Laman Web ini
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan