Bagaimana cara menentukan file header yang akan dimasukkan?

13

Katakanlah saya memiliki kode di bawah ini (sangat sederhana).

#include <iostream>
int main() {
    std::cout << std::stoi("12");
}

Ini mengkompilasi dengan baik pada g ++ dan dentang; Namun, gagal dikompilasi di MSVC dengan kesalahan berikut:

kesalahan C2039: 'stoi': bukan anggota 'std'

kesalahan C3861: 'stoi': pengidentifikasi tidak ditemukan

Saya tahu itu std::stoiadalah bagian dari <string>header, yang mungkin dua kompiler sebelumnya termasuk sebagai bagian dari <iostream>dan yang terakhir tidak. Menurut standar C ++ [res.on.headers]

Header C ++ dapat menyertakan header C ++ lainnya.

Yang, bagi saya, pada dasarnya mengatakan bahwa ketiga kompiler itu benar.

Masalah ini muncul ketika salah satu siswa saya menyerahkan pekerjaan, yang TA ditandai sebagai tidak dikompilasi; Saya tentu saja pergi dan memperbaikinya. Namun, saya ingin mencegah insiden di masa depan seperti ini. Jadi, apakah ada cara untuk menentukan file header mana yang harus dimasukkan, singkat mengkompilasi pada tiga kompiler berbeda untuk memeriksa setiap waktu?

Satu-satunya cara yang dapat saya pikirkan adalah untuk memastikan bahwa untuk setiap stdpanggilan fungsi, termasuk yang sesuai ada; tetapi jika Anda memiliki kode yang panjangnya ribuan baris, ini mungkin membosankan untuk dicari. Apakah ada cara yang lebih mudah / lebih baik untuk memastikan kompatibilitas lintas-kompiler?

Contoh dengan tiga kompiler: https://godbolt.org/z/kJhS6U

ChrisMM
sumber
6
Jika Anda ingat itu std::stoiuntuk menangani string, Anda bisa menebak itu <string>akan menjadi header yang baik untuk dimasukkan. Atau Anda bisa mencari referensi yang bagus yang akan memberi tahu Anda. Dan saya sarankan Anda selalu secara eksplisit memasukkan file header, jadi Anda tidak harus bergantung pada perilaku spesifik implementasi non-portabel.
Beberapa programmer Bung
3
Cara terbaik adalah pergi ke cppreference sebelum pergi ke platform lain. Mereka memiliki hal-hal yang cukup rinci di sana.
Siddharth
1
Sertakan tajuk yang sesuai saat Anda menulis kode. Yaitu. saat Anda menulis kode yang berisi std::stoi,, Anda segera memastikan #include <string>hadir juga.
Sander De Dycker
3
Dalam kasus umum ini adalah masalah yang sulit . Namun, ketika kita berbicara tentang pustaka standar yang hilang termasuk, cara normal memang akan memeriksa semua panggilan fungsi / tipe yang digunakan.
Max Langhof
1
@ skratchi.at, siswa diberi tahu bahwa mereka dapat menggunakan kompiler mana pun yang mereka inginkan, selama kode mereka sesuai standar. Setelah 4 tahun, ini adalah pertama kalinya ini menjadi masalah.
ChrisMM

Jawaban:

14

Apakah ada cara yang lebih mudah / lebih baik untuk memastikan kompatibilitas lintas-kompiler?

Ini akan selalu menjadi tugas yang berat jika Anda memiliki basis kode yang sangat besar dan belum melakukan ini sejauh ini, tetapi begitu Anda selesai memperbaiki termasuk, Anda dapat tetap berpegang pada prosedur sederhana:

Ketika Anda menulis kode baru yang menggunakan fitur standar, seperti std::stoi, tancapkan nama itu ke Google, buka artikel cppreference.com untuk itu, lalu lihat di bagian atas untuk melihat di mana header itu didefinisikan.

Kemudian sertakan itu, jika belum termasuk. Pekerjaan selesai!

(Anda dapat menggunakan standar untuk ini, tetapi itu tidak dapat diakses.)

Jangan tergoda untuk memecat semuanya demi peretasan yang murah dan tidak dapat diakses seperti <bits/stdc++.h>!


tl; dr: dokumentasi

Lightness Races di Orbit
sumber
3
Agar adil, begitu Anda sudah menghafal semuanya secara efektif dan tidak perlu mencarinya lagi, itu terasa cukup apik
Lightness Races in Orbit
5
@JosephWood: Jika Anda tidak tahu header mana fungsi yang diberikan adalah dengan menghafal, kemungkinan Anda harus melihat fungsi hingga memeriksa ulang asumsi Anda di atasnya, jadi mencari tahu di mana header itu milik bahkan tidak mengambil tambahan waktu.
DevSolar
1
Seperti @JosephWood, saya juga berharap mereka yang lebih berpengalaman memiliki cara yang lebih baik. Saya tahu header mana yang harus disertakan untuk sebagian besar fungsi STL, tetapi berharap ada cara yang lebih mudah untuk mengajar siswa daripada mencari setiap fungsi: P
ChrisMM
1
@ ChrisMM ada alat seperti include-what-you-use . Kebenaran mereka tidak dapat dijamin (dan memang terkadang pekerjaan manual diperlukan) tetapi tidak buruk sama sekali.
aneh
4
@ ChrisMM Mengajari siswa Anda untuk merujuk pada dokumentasi itu sangat, sangat penting . Ribuan orang mengalir ke situs ini setiap hari tanpa gagasan duniawi bahwa mereka harus melakukannya. Menggunakan dokumentasi adalah cara yang lebih mudah / lebih baik.
Lightness Races in Orbit
-1

Selain meninjau dokumentasi dan melakukannya secara manual (menyakitkan dan menghabiskan waktu), Anda dapat menggunakan beberapa alat yang dapat melakukannya untuk Anda.

Anda dapat menggunakan ReSharper di Visual Studio yang mampu mengatur impor (sebenarnya VS tanpa ReSharper tidak bisa digunakan). Jika menyertakan tidak ada, disarankan untuk menambahkannya dan jika sudah usang, baris dengan sertakan ditampilkan dalam warna yang lebih pucat.

Atau Anda dapat menggunakan CLion (tersedia untuk semua platform) yang juga memiliki kemampuan ini (sebenarnya ini adalah pembuatan JetBrains yang sama).

Ada juga alat yang disebut termasuk apa yang Anda gunakan , tetapi tujuannya adalah mengambil keuntungan dari deklarasi maju, saya tidak pernah menggunakannya (secara pribadi - rekan tim saya melakukan itu untuk proyek kami).

Marek R
sumber
clion tidak secara otomatis memasukkan header yang benar ketika header lainnya sudah termasuk jika berfungsi (mis. tidak akan menyarankan string di sini jika iostream sudah termasuk) IIRC
RiaD