D: Mengapa opIndex tidak memenuhi syarat const di kelas std.container.Array?

Saya baru-baru ini ingin menggunakan std.container.Array dan mulai membuat kelas dengan fungsi anggota pengambil yang mengembalikan nilai dari kelas Array. Saya segera menyadari bahwa saya tidak dapat memenuhi syarat const pengambil saya, karena opIndex adalah fungsi yang bisa berubah.

Saya mencoba mengubah kode sumber menjadi const-qualify Array.opIndex, dan hasilnya baik-baik saja. Namun, beberapa pengujian unit di std.algorithm tidak lulus, mengeluh bahwa nilai kembalian Array.opIndex bukanlah nilai l.

Berikut ini kode untuk Array.opIndex:

ref T opIndex(size_t i)
{
    version (assert) if (!_data.refCountedStore.isInitialized) throw new RangeError();
    return _data._payload[i];
}

Apakah ada sesuatu yang saya lewatkan di sini? Mengapa tidak memenuhi syarat const?


person David Eränen    schedule 18.08.2014    source sumber


Jawaban (1)


Ada sejumlah masalah dalam membuat container const-benar, karena const membuat container tidak dapat mengubah apa pun di internalnya, tidak seperti di C++, di mana Anda dapat membuat beberapa hal mutable selama saat Anda memastikan bahwa fungsinya secara logis const. IIRC, ada operasi yang Array lakukan yang secara teoritis bisa menjadi const tetapi tidak bisa karena cara kerja beberapa internalnya. Dan saya tidak heran jika karena itu, orang-orang yang mengerjakannya tidak berhasil const, meskipun sebagian bisa saja berhasil.

Adapun opIndex, saya tidak melihat sesuatu yang jelas dalam implementasi itu yang tidak mungkin const, dan fakta bahwa itu dikompilasi menyiratkan bahwa itu mungkin berhasil. Namun, jika Anda melakukan itu, Anda perlu membebaninya secara berlebihan daripada hanya membuat kelebihan tersebut menjadi const, atau Anda tidak akan dapat menetapkannya - yang mungkin merupakan keluhan std.algorithm tentang hal itu. Jadi, Anda memerlukan sesuatu seperti

ref T opIndex(size_t i) {...}
ref const(T) opIndex(size_t i) const {...}

sehingga masih berfungsi untuk ditugaskan ke sana - mis. arr[5] = "foo"; - selama Array bukan const. Namun, karena banyak dari operasi Array tidak bisa menjadi const karena cara kerja implementasinya, saya tidak tahu seberapa berguna sebenarnya membuat fungsi seperti opIndex const, karena apa yang dapat Anda lakukan dengan a akan sangat terbatas const Array!T meskipun setiap fungsi anggota yang dapat menjadi const adalah const.

person Jonathan M Davis    schedule 18.08.2014
comment
Terima kasih atas jawabannya Jonatan! - person David Eränen; 19.08.2014
comment
Anda benar karena saya tidak bisa begitu saja mengubah kelebihan asli menjadi const, saya perlu menambahkan yang lain. Anda juga benar karena perlu mengembalikan ref const(T) dan bukan ref T. Tes unit masih berfungsi dengan perubahan ini! Mungkin versi const ini harus ditambahkan ke kode? - person David Eränen; 19.08.2014
comment
Dan untuk memperjelas: Saya tidak ingin opIndex menjadi const agar dapat menggunakannya dengan const Array!T; sebagai gantinya saya ingin dapat memenuhi syarat const fungsi anggota pengambil saya yang menggunakan Array.opIndex sebagai hanya-baca. - person David Eränen; 19.08.2014
comment
@ DavidEränen Ya, Anda menggunakan const Array!T jika Anda menggunakan opIndex di dalam fungsi const dari sebuah struct atau kelas yang menjadi anggotanya, tetapi jika yang Anda coba lakukan hanyalah menggunakan opIndex daripada menggunakannya sebagai const di secara umum, sepertinya ini dapat dengan mudah dibuat berfungsi. Jangan ragu untuk membuka permintaan penyempurnaan issues.dlang.org atau bahkan membuat permintaan tarik jika Anda mau merasa berani github.com/D-Programming-Language/phobos . Sepertinya lebih banyak pekerjaan yang harus dilakukan untuk membuat Array const-benar, meskipun kita tidak dapat memperbaikinya sepenuhnya. - person Jonathan M Davis; 19.08.2014