unique_ptr <0 ATAU apa yang kurang dari operator lakukan?

9

Saya berurusan dengan kode yang telah ditulis bukan oleh saya. Saya memiliki pernyataan ini:

// p is type of std::unique_ptr<uint8_t[]>
if (p < 0) { /* throw an exception */ }

Jadi apa p < 0artinya dalam konteks ini?
Pada halaman dokumentasi , saya percaya kasus saya adalah 16) y < nullptr, di mana 0adalah nullptr.

Tapi apa fungsinya?

Sagid
sumber
1
Berdasarkan fakta bahwa, pada x64, pointer kanonik dalam rentang kernel memiliki bit set atas, itu bisa menjadi (bodoh hardcoded) cara untuk memeriksa apakah pointer milik ruang kernel - jika jawaban di bawah ini benar, maka tidak ada .
Michael Chourdakis
1
Dalam WINAPI p==-1adalah pegangan yang tidak valid. Karena 2^64jumlah yang luar biasa besar, setiap akal sehat pselalu positif. Jadi p<0periksa untuk menangani WINAPI yang tidak valid. Ini bukan kode yang bagus.
ALX23z
@OP: Bisakah Anda sedikit menjelaskan dalam konteks mana kode ini digunakan? Apakah ini digunakan di Linux atau Windows? Apakah nilai pointer terkait dengan beberapa kode WINAPI? Saya pikir jika Anda mengklarifikasi itu, komentar di atas mungkin merupakan jawaban yang baik.
kenari
@ ALX23z Tapi apakah pegangan WINAPI harus bertipe uint8_t*(atau bahkan array uint8_t)? Saya pikir mereka begitu void*, bukan?
walnut
@walnut mereka bukan void*mereka memiliki HANDLE_PTR makro atau sesuatu yang pada dasarnya long*iirc.
ALX23z

Jawaban:

2

unique_ptr <0 ATAU apa yang kurang dari operator lakukan?

Cocok dengan overload (11) pada cppreference operator<(const unique_ptr&, nullptr_t);. 0 secara implisit dikonversi ke std::nullptr_t. Sesuai dokumentasi, hasilnya adalah std::less<unique_ptr<T,D>::pointer>()(x.get(), nullptr).

Hasilnya adalah implementasi yang didefinisikan, tetapi tanpa syarat salah pada sebagian besar sistem. Agaknya pada sistem eksotis di mana nol tidak memiliki representasi biner 0, hasilnya mungkin benar.

Saya yakin kasus saya 16)

(16) adalah jalan di sekitar lainnya yang sama: 0 > unique_ptr. Hasilnya sama.

eerorika
sumber
Tetapi 0dipertimbangkan nullptroleh kompiler? Saya pikir itu yang dia tanyakan. Setidaknya tidak masuk akal bagi saya.
diubahinstan
@alteredinstance 0 tidak "dianggap" nullptr(atau tergantung pada apa yang Anda maksud dengan pertimbangan). 0 secara implisit dikonversi ke std::nullptr_t.
eerorika
Itu yang saya duga. Saya bertanya-tanya apakah ada dokumentasi tentang konversi implisit 0ke nullptr, karena saya hanya melihat dua yang kompatibel dengan perbandingan boolean. Mereka sebanding, tetapi saya mendapat kesan bahwa mereka tidak dapat dikonversi.
diubahinstan
@alteredinstance Konversi tidak terjadi sebaliknya. int x = nullptrberbentuk buruk.
eerorika
2
@alteredinstance std::nullptr_tdirancang agar dapat digunakan dengan konstanta null pointer; bukan hanya nullptr. 0 (dan juga 0L misalnya) adalah konstanta penunjuk nol, sehingga maksudnya adalah mereka dapat digunakan untuk membuat a std::nullptr_t.
eerorika
2

Periksa yang operator <tidak kelebihan beban di suatu tempat di basis kode Anda. Yang tampaknya menjadi satu-satunya cara bagaimana (p < 0)bisa true.

Contoh:

bool operator< (const std::unique_ptr<uint8_t[]>&, int) { return true; }

int main() {
    std::unique_ptr<uint8_t[]> p;
    std::cout << (p < 0) << std::endl;
}

Cetakan:

1

demo langsung

Kalau tidak seperti yang dikatakan orang lain, 0secara implisit mengkonversi std::nullptr_t, yang akan memilih bool operator<(const unique_ptr<T, D>& x, nullptr_t)kelebihan yang akan memanggil std::less(p, 0)yang akan kembali false(bahkan pada Windows dengan -1nilai pointer).

rustyx
sumber
Itu tidak selalu kembali false. Entah itu implementasi yang ditentukan atau tidak ditentukan (saya tidak yakin.) Tapi saya setuju bahwa itu mungkin akan mengembalikan falsesebagian besar (semua?) Implementasi. Lihat juga jawaban oleh @eerorika
walnut
0

Ungkapan ini cocok dengan operator templat ini (0 dikonversi ke nullptr):

template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);

Ini mengembalikan std::less<unique_ptr<T,D>::pointer>()(p.get(), nullptr)yang selalu salah (seperti halnya std::lessfunctor urutan ketat) ( demo ).

YSC
sumber
Itu tidak selalu kembali false. Apakah itu dilakukan adalah implementasi yang ditentukan atau tidak ditentukan. Mungkin selalu kembali falsemeskipun pada sebagian besar (semua?) Implementasi saat ini.
walnut
@walnut Kecuali jika ada pertanyaan yang secara eksplisit bertanya tentang apa yang dikatakan Standar (melalui tag bahasa-pengacara misalnya), saya mencoba menjawab dari sudut pandang praktis. Semua implementasi praktis std::lesspengembalian false.
YSC
Tidak apa-apa, saya hanya tidak menemukan alasan Anda (" sebagai std :: less adalah perintah yang ketat ") meyakinkan. Ini bisa menjadi perintah ketat tanpa kembali false. Alasan praktisnya adalah bahwa nilai pointer nol diwakili oleh alamat serendah mungkin atau sesuatu di sepanjang garis itu.
kenari