Saya mengambil ini di salah satu upaya singkat saya ke reddit:
http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/
Pada dasarnya, penulis menunjukkan bahwa di C ++:
throw "error"
adalah ekspresi. Ini sebenarnya dijelaskan dengan cukup jelas dalam Standar C ++, baik dalam teks utama maupun tata bahasa. Namun, yang tidak jelas (setidaknya bagi saya) adalah jenis ekspresi apa? Saya menebak " void
", tetapi sedikit bereksperimen dengan g ++ 4.4.0 dan Comeau menghasilkan kode ini:
void f() {
}
struct S {};
int main() {
int x = 1;
const char * p1 = x == 1 ? "foo" : throw S(); // 1
const char * p2 = x == 1 ? "foo" : f(); // 2
}
Kompiler tidak memiliki masalah dengan // 1 tetapi muncul di // 2 karena tipe dalam operator bersyarat berbeda. Jadi jenis throw
ekspresi sepertinya tidak kosong.
Jadi apa itu?
Jika Anda menjawab, harap dukung pernyataan Anda dengan kutipan dari Standard.
Ini ternyata bukan tentang jenis ekspresi lemparan melainkan bagaimana operator bersyarat menangani ekspresi lemparan - sesuatu yang pasti tidak saya ketahui sebelum hari ini. Terima kasih untuk semua yang menjawab, tetapi khususnya untuk David Thornley.
Jawaban:
Menurut standar, 5.16 paragraf 2 poin pertama, "Operan kedua atau ketiga (tetapi tidak keduanya) adalah ekspresi-lemparan (15.1); hasilnya adalah jenis yang lain dan merupakan nilai r." Oleh karena itu, operator kondisional tidak peduli apa tipe ekspresi-lemparan itu, tetapi hanya akan menggunakan tipe lainnya.
Faktanya, 15.1, paragraf 1 mengatakan secara eksplisit "Ekspresi lemparan adalah tipe kosong."
sumber
ISO14882 Bagian 15
sumber
void
Dari [expr.cond.2] (operator bersyarat
?:
):Jadi, dengan
//1
Anda berada dalam kasus pertama, dengan//2
, Anda melanggar "salah satu dari yang berikut akan berlaku", karena tidak ada yang melakukannya, dalam kasus itu.sumber
Anda dapat memiliki printer tipe yang mengeluarkannya untuk Anda :
Pada dasarnya kurangnya implementasi untuk
PrintType
akan menyebabkan laporan kesalahan kompilasi mengatakan:jadi kami benar-benar dapat memverifikasi bahwa
throw
ekspresi memiliki tipevoid
(dan ya, kutipan Standar yang disebutkan dalam jawaban lain memverifikasi bahwa ini bukan hasil spesifik implementasi - meskipun gcc mengalami kesulitan mencetak info berharga)sumber