Jawaban singkat: Anda sedang mencampur konsep sebelum waktu kompilasi dan waktu kompilasi yang memiliki kesamaan dalam tujuannya. Antarmuka (kelas abstrak dan semua implementasi paradigma objek-orientasi) diinformasikan pada waktu kompilasi . Konsep adalah ide yang sama tetapi dalam konteks pemrograman generik yang dalam C ++ terjadi SEBELUM waktu kompilasi . Kami belum memiliki fitur terakhir.
Tapi saya akan jelaskan dari awal.
Jawaban panjang:
Bahkan, Konsep hanyalah informasi bahasa dan "membuat lebih mudah bagi programmer" dari sesuatu yang sudah ada dalam bahasa, yang bisa Anda sebut "mengetik bebek".
Ketika Anda meneruskan suatu tipe ke fungsi templat, itu adalah fungsi generik yang darinya kompiler akan menghasilkan kode nyata (sebaris) ketika dipanggil, tipe itu perlu memiliki beberapa properti (ciri?) Yang akan digunakan dalam kode templat. Jadi ini adalah ide untuk mengetik bebek tetapi itu semua dihasilkan dan dilakukan pada waktu kompilasi .
Apa yang terjadi ketika tipe tidak memiliki properti yang diperlukan?
Nah, kompiler akan tahu bahwa ada masalah hanya setelah kode yang dihasilkan dari template dikompilasi dan gagal. Itu berarti bahwa kesalahan yang akan dihasilkan akan menjadi kesalahan di dalam kode templat, yang akan ditampilkan kepada programmer sebagai kesalahannya. Juga, kesalahan akan memiliki banyak informasi karena informasi meta yang disediakan dalam hal pembuatan kode templat, untuk mengetahui instantiasi templat mana yang sedang kita bicarakan.
Beberapa masalah dengan itu: pertama, sebagian besar waktu, kode template adalah kode perpustakaan dan kebanyakan programmer adalah pengguna kode perpustakaan, bukan penulis kode perpustakaan. Itu berarti bahwa jenis kesalahan samar ini benar-benar sulit untuk dipahami ketika Anda tidak mengerti bagaimana perpustakaan ditulis (bukan hanya desain, bagaimana itu benar-benar dilaksanakan). Masalah kedua adalah bahwa bahkan ketika programmer menulis kode templat, alasan kegagalan mungkin masih tidak jelas karena kompiler akan dapat mengatakan bahwa ada masalah terlambat: ketika kode yang dihasilkan sedang dikompilasi. Jika masalahnya relatif terhadap tipe properti, maka ia harus memeriksanya bahkan sebelum membuat kode.
Itulah yang dibolehkan Konsep (dan dirancang untuk): untuk memungkinkan pemrogram (kode generik) untuk menentukan properti tipe yang dilewatkan sebagai parameter templat dan kemudian memungkinkan kompiler untuk memberikan kesalahan eksplisit jika jenis yang disediakan tidak memenuhi Persyaratan.
Setelah pemeriksaan berhasil, kode akan dihasilkan dari template dan kemudian dikompilasi, tentunya berhasil.
Semua pengecekan Konsep terjadi secara eksklusif sebelum waktu kompilasi . Itu memeriksa jenis sendiri, bukan jenis objek . Tidak ada objek sebelum waktu kompilasi.
Sekarang, tentang "antarmuka".
Saat Anda membuat tipe basis abstrak atau virtual, Anda mengizinkan kode menggunakannya untuk memanipulasi objek tipe anak tanpa mengetahui implementasinya yang sebenarnya. Untuk menegakkan ini, tipe dasar mengekspos anggota yang virtual dan mungkin (atau harus) kelebihan beban oleh tipe anak.
Itu berarti bahwa kompilator dapat memeriksa pada waktu kompilasi bahwa semua objek yang dilewatkan ke fungsi yang memerlukan referensi ke kelas dasar harus 1. menjadi salah satu dari tipe anak dari kelas dasar, 2. bahwa tipe anak harus memiliki implementasi dari fungsi virtual murni dideklarasikan di kelas dasar jika ada.
Jadi pada saat kompilasi , kompiler akan memeriksa antarmuka tipe objek dan melaporkan jika ada sesuatu yang hilang.
Itu ide yang sama dari Konsep, tetapi terjadi terlambat , seperti yang dikatakan dalam deskripsi Konsep. Itu terjadi pada waktu kompilasi. Kami tidak dalam kode generik (kode templat), kami setelah diproses dan sudah terlambat untuk memeriksa apakah jenis memenuhi persyaratan umum, yang tidak dapat diekspos oleh kelas dasar virtual. Bahkan, seluruh implementasi paradigma orientasi objek di C ++ bahkan tidak ada ketika kode templat sedang diproses. Tidak ada objek (belum). Itu
Kelas menggambarkan batasan pada objek yang akan digunakan untuk memeriksa persyaratan untuk fungsi memanipulasi objek tersebut. Konsep menjelaskan batasan pada tipe (termasuk kelas) yang akan digunakan untuk memeriksa persyaratan kode generik untuk menghasilkan kode nyata dari tipe tersebut dan kombinasi kode generik.
Jadi, sekali lagi, ini adalah "pemeriksaan kewarasan" yang sama, tetapi di lapisan lain bahasa, yaitu templat. Templat adalah bahasa lengkap (turing lengkap) yang memungkinkan meta-pemrograman, tipe pemrograman bahkan sebelum mereka muncul dalam kode yang dikompilasi. Ini sedikit seperti skrip kompiler. Katakanlah Anda dapat membuat skrip, kelas hanyalah nilai yang dimanipulasi oleh skrip. Saat ini, tidak ada cara untuk memeriksa batasan pada nilai-nilai ini selain untuk menghentikan skrip dengan cara yang tidak jelas. Konsepnya hanya itu: berikan pengetikan pada nilai-nilai ini (yang dalam kode yang dihasilkan adalah tipe). Tidak yakin saya jelas ...
Perbedaan lain yang sangat penting antara kelas dasar virtual dan Konsep adalah bahwa yang pertama memaksa hubungan yang kuat antara jenis, membuat mereka "terikat oleh darah". Sementara metaprogramming template memungkinkan "duck typing", Konsep hanya memungkinkan untuk membuat persyaratan menjadi lebih jelas.
Jawaban sederhana untuk hampir semua pertanyaan Anda adalah, "Karena penyedot C ++ menyedot". Serius. Mereka dibangun di atas teknologi Unit Terjemahan C, yang secara efektif melarang banyak hal bermanfaat, dan implementasi templat yang ada sangat lambat. Konsep tidak dipotong untuk alasan konseptual apa pun - mereka dipotong karena tidak ada implementasi yang dapat diandalkan, ConceptGCC sangat lambat, dan menspesifikasikan konsep memakan waktu lama. Herb Sutter menyatakan bahwa dibutuhkan lebih banyak ruang untuk menentukan konsep yang digunakan dalam pustaka Standar daripada menentukan seluruh templat.
Bisa dibilang, antara SFINAE,
decltype
danstatic_assert
, mereka sebagian besar dapat diterapkan seperti sekarang.sumber
Dalam pemahaman saya, Antarmuka dan Konsep memiliki tujuan yang sama di berbagai bagian bahasa C ++.
Seperti disebutkan dalam jawaban untuk pertanyaan asli: Implementasi Antarmuka ditentukan oleh implementor kelas pada waktu desain. Setelah sebuah kelas diterbitkan, ia hanya dapat mendukung antarmuka yang berasal dari waktu desain.
Dua Antarmuka yang berbeda dengan fungsi dan semantik anggota yang sama persis (yaitu konsep yang sama) masih akan menjadi dua Antarmuka yang berbeda. Jika Anda ingin mendukung semantik kedua Antarmuka, Anda mungkin harus menerapkan dukungan dua kali.
Itulah masalah yang ingin dipecahkan oleh Pemrograman Generik. Dalam C ++ Generic Programming, jenis yang diteruskan ke templat hanya perlu mendukung antarmuka (tidak menggunakan huruf besar, dalam arti "antarmuka pemrograman" dari suatu jenis) yang digunakan oleh templat. Dua Antarmuka berbeda dengan fungsi anggota yang sama akan cocok, dan Anda harus menulis kode hanya sekali. Selain itu, semua jenis (bahkan tanpa Antarmuka eksplisit) yang mendukung antarmuka yang sama akan berfungsi dengan baik.
Ini mengarah ke masalah kedua: bagaimana jika Anda memiliki dua jenis dengan antarmuka yang tumpang tindih tetapi semantik yang berbeda ? Pemrograman generik tidak akan dapat membedakan dan semuanya akan dikompilasi dengan baik, tetapi hasil run-time akan mengejutkan dan mungkin salah.
Di situlah Konsep masuk. Jika Anda terlalu menyederhanakan Anda dapat mempertimbangkan Konsep versi generik (templat) Antarmuka. Itu perlu diimplementasikan hanya sekali untuk diterapkan ke sejumlah besar tipe potensial yang dapat "berasal" dari Konsep. Sebuah Konsep adalah antarmuka semantik yang telah ditentukan dari tipe (kelas-) yang tidak terbatas pada tipe itu saja. Ini tidak seperti Antarmuka di mana dua jenis yang sangat berbeda (ke kompiler generik) masih dapat memiliki Konsep yang sama, tanpa harus menggunakan untuk membatasi Antarmuka kelas dasar, atau Antarmuka kelas dasar yang tidak memiliki semantik nyata yang dapat dilihat oleh kompiler mereka. sendiri tetapi hanya digunakan untuk jenis perbedaan.
sumber