
Alih-alih kata pengantar
Mungkin dengan gambar ini, cerita apa saja tentang
boost ,
Loki , independen, dan juga implementasi dari pustaka C ++ standar yang disertakan dengan kompiler harus dimulai.
Ya, ya, dan jika Anda berpikir bahwa pengembang perpustakaan standar untuk g ++ yang sama, dentang, Visual Studio atau, Tuhan maafkan saya, C ++ Builder (sebelumnya Borland, tetapi Embarcadero saat ini) adalah guru yang tidak membuat kruk, mereka tidak melanggar standar untuk kompiler mereka dan jangan menulis sepeda, maka kemungkinan besar Anda tidak begitu aktif menggunakan pustaka C ++ standar seperti yang Anda pikirkan.
Artikel ini ditulis sebagai sebuah cerita, dan berisi banyak "air" dan penyimpangan, tetapi saya berharap bahwa pengalaman saya dan kode yang dihasilkan akan bermanfaat bagi mereka yang menghadapi masalah yang sama ketika mengembangkan C ++, terutama pada kompiler yang lebih tua. Tautan ke GitHub dengan hasil untuk hari ini untuk yang tidak sabar dan yang bukan pembaca:
https://github.com/oktonion/stdex (komitmen dan kritik konstruktif dipersilahkan)
Dan sekarang, hal pertama yang pertama.
Daftar isi
Pendahuluan
Bab 1. Viam supervadet vadensBab 2. #ifndef __CPP11_SUPPORT__ #define __COMPILER_SPECIFIC_BUILT_IN_AND_MACRO_HELL__ #endifBab 3. Menemukan implementasi nullptr yang sempurnaBab 4. C ++ Template Magic....
4.1 Kita mulai dari yang kecil....
4.2 Tentang berapa banyak kesalahan ajaib yang dikompilasi oleh log untuk kita....
4.3 Pointer dan semuanya....
4.4 Apa lagi yang diperlukan untuk pustaka templatBab 5
...
Entri
Saat itu tahun 2017, C ++ 11 telah lama mengalir ke aliran baru kompiler baru dan relatif baru, membawa pekerjaan terstandarisasi dengan aliran, mutex, memperluas pemrograman templat dan pendekatan standardisasi untuk itu, ada โbesarโ jenis
panjang yang panjang dalam standar , akhirnya menyingkirkan kebutuhan luas untuk menampilkan jenis untuk kompiler menggunakan
otomatis (selamat tinggal
std :: map <type, type> :: const_iterator it = ... - well, Anda mengerti saya), dan kombinasi fitur ini dengan yang baru
untuk masing-masing telah menjadi salah satu yang paling umum menggunakan implementasi loop iterator. Akhirnya, kami (pengembang) dapat memberi tahu pengguna (pengembang) secara manusiawi mengapa kode tersebut tidak dikumpulkan menggunakan
static_assert , serta
enable_if , yang sekarang memilih overload yang diperlukan seperti sulap.
Di halaman itu tahun 2017! Sudah C + + 17 secara aktif diperkenalkan di GCC, dentang, Visual Studio, di mana-mana ada
dectype (karena C + + 11),
constexpr (sejak C + + 11, tetapi secara signifikan ditingkatkan), modul hampir di jalan, ada waktu yang baik. Saya sedang bekerja dan dengan beberapa ketidaksetujuan melihat Internal Compiler Error berikutnya di Borland C ++ Builder 6.0 saya, serta banyak kesalahan build dengan versi berikutnya dari boost library. Saya pikir sekarang Anda mengerti dari mana keinginan untuk membangun sepeda ini berasal. Kami menggunakan Borland C ++ Builder 6.0 dan Visual Studio 2010 untuk Windows, g ++ versi 4.4.2 atau lebih rendah untuk
QNX dan untuk beberapa sistem unix. Kami terhindar dari MacOS, yang tidak diragukan lagi merupakan nilai tambah. Tidak ada kompiler lain (termasuk C ++ 11) yang dapat dipertimbangkan dengan alasan kami meninggalkan artikel ini.
"Dan apa yang bisa sangat rumit di sana" - sebuah pemikiran merayap ke dalam upaya saya yang lelah untuk meningkatkan di bawah otak pembangun tua yang baik. "Yang saya butuhkan adalah
type_traits ,
utas ,
mutex , mungkin
chrono ,
nullptr akan menyenangkan." Saya beralasan dan mulai bekerja.
Bab 1. Viam supervadet vadens
Itu perlu untuk memulai dari mana, dan untuk memulai dari mana - tentu saja saya memiliki sejumlah file header dan kode sumber yang tersebar di seluruh proyek dengan implementasi fungsionalitas yang serupa atau identik dari pustaka standar C ++ 11 standar perkembangan saya, serta secara jujur โโmeminjam atau memproses dari kode-kode itu. gcc dan boost yang sama. Menggabungkan semua ini bersama-sama, saya punya beberapa fungsi, kelas, makro yang seharusnya berubah menjadi perpustakaan standar yang elegan dan ramping. Setelah memperkirakan jumlah pekerjaan, saya segera memutuskan untuk meninggalkan implementasi segalanya dan segalanya, membatasi diri pada pengembangan "add-on" di atas pustaka C ++ 98 standar yang disertakan dengan kompiler.
Dalam versi awal tidak ada kepatuhan khusus terhadap standar, terutama masalah yang diterapkan diselesaikan. Misalnya,
nullptr terlihat seperti ini:
#define nullptr 0
static_assert juga diselesaikan dengan sederhana:
#define STATIC_ASSERT(expr) typedef int test##__LINE__##[expr ? 1 : -1];
std :: to_string diimplementasikan melalui
std :: stringstream , yang digantikan oleh
std :: strstream dalam implementasi tanpa file header
sstream , dan semua ini segera dimasukkan ke
namespace std :
#ifndef NO_STD_SSTREAM_HEADER #include <sstream> #else #include <strstream> namespace std {typedef std::strstream stringstream;} #endif namespace std { template<class T> string to_string(const T &t) { stringstream ss; ss << t; return ss.str(); } }
Ada juga "trik" yang tidak termasuk dalam standar, tetapi tetap berguna dalam pekerjaan sehari-hari, seperti
makro selamanya atau
hitungan :
#define forever for(;;)
countof kemudian diubah menjadi lebih banyak opsi C ++:
template <typename T, std::size_t N> char(&COUNTOF_REQUIRES_ARRAY_ARGUMENT(T(&)[N]))[N];
Bekerja dengan utas (
utas file header dari std) diimplementasikan melalui beberapa pustaka Tiny, ditulis ulang dengan mempertimbangkan fitur-fitur seluruh kebun binatang kompiler dan OS. Dan mungkin
type_traits sampai taraf tertentu sudah mirip dengan apa yang diperlukan standar C ++ 11. Ada
std :: enable_if ,
std :: integral_constant ,
std :: is_const dan templat sejenisnya yang sudah digunakan dalam pengembangan.
namespace std { template<bool Cond, class Iftrue, class Iffalse> struct conditional { typedef Iftrue type; };
Diputuskan untuk memisahkan semua makro, fungsi, tipe non-standar dan "kompiler" menjadi file
header.h. Dan, bertentangan dengan praktik boost, di mana implementasi "switching" menggunakan makro banyak digunakan, untuk mengabaikan macro terkait dengan hal-hal yang
bergantung pada compiler di semua file library, kecuali
core.h. Juga, fungsionalitas yang tidak dapat diimplementasikan tanpa menggunakan "peretasan" (pelanggaran standar, bergantung pada Perilaku Tidak Terdefinisi untuk Ditentukan secara Agak), atau diterapkan secara individual untuk setiap kompiler (misalnya dengan makro bawaannya), diputuskan untuk tidak menambah perpustakaan, agar tidak menghasilkan dorongan mengerikan lain (tapi indah). Akibatnya, satu-satunya hal utama dan praktis yang digunakan
core.h adalah untuk menentukan apakah ada dukungan untuk
nullptr bawaan (karena kompiler bersumpah jika mengganti kata yang dipesan), dukungan untuk
static_assert bawaan (sekali lagi, untuk menghindari memotong kata yang dipesan) dan dukungan untuk tipe bawaan C ++ 11
char16_t dan
char32_t .
Ke depan saya dapat mengatakan bahwa idenya hampir berhasil, karena sebagian besar dari apa yang didefinisikan dalam boost oleh macro keras tergantung pada kompiler tertentu, dalam implementasi ini ditentukan oleh kompiler itu sendiri pada tahap kompilasi.
Akhir bab pertama. Pada
bab kedua, saya akan melanjutkan narasi tentang kesulitan berurusan dengan kompiler, tentang kruk yang ditemukan dan solusi elegan di perut gcc, boost dan Visual Studio, serta deskripsi kesan saya tentang apa yang saya lihat dan dapatkan pengalaman dengan contoh kode.
Terima kasih atas perhatian anda