Ini baru saja muncul dalam konteks pertanyaan lain .
Tampaknya fungsi anggota di templat kelas hanya dibuat jika digunakan dengan ODR. Bisakah seseorang menjelaskan apa sebenarnya artinya. The artikel wikipedia on One Definition Rule (ODR) tidak menyebutkan " ODR digunakan ".
Namun standar mendefinisikannya sebagai
Variabel yang namanya muncul sebagai ekspresi yang berpotensi dievaluasi digunakan odr kecuali itu adalah objek yang memenuhi persyaratan untuk muncul dalam ekspresi konstan (5.19) dan konversi lvalue-ke-rvalue (4.1) segera diterapkan.
di [basic.def.odr].
Sunting: Rupanya ini adalah bagian yang salah dan seluruh paragraf berisi banyak definisi untuk hal yang berbeda. Ini mungkin yang relevan untuk fungsi anggota templat kelas:
Fungsi non-kelebihan beban yang namanya muncul sebagai ekspresi yang berpotensi dievaluasi atau anggota dari sekumpulan fungsi kandidat, jika dipilih oleh resolusi kelebihan beban saat dirujuk dari ekspresi yang berpotensi dievaluasi, digunakan odr, kecuali jika itu adalah virtual murni fungsi dan namanya tidak terkualifikasi secara eksplisit.
Namun saya tidak mengerti, bagaimana aturan ini bekerja di beberapa unit kompilasi? Apakah semua fungsi anggota dibuat instance-nya jika saya secara eksplisit membuat instance template kelas?
sumber
Jawaban:
Ini hanya definisi sewenang-wenang, yang digunakan oleh standar untuk menentukan kapan Anda harus memberikan definisi untuk suatu entitas (bukan hanya deklarasi). Standar tidak mengatakan hanya "bekas", karena ini dapat ditafsirkan secara berbeda tergantung pada konteksnya. Dan beberapa penggunaan ODR tidak benar-benar sesuai dengan apa yang biasanya diasosiasikan dengan "use"; misalnya, fungsi virtual selalu digunakan ODR kecuali ia murni, meskipun sebenarnya tidak dipanggil di mana pun dalam program.
Definisi lengkapnya ada di §3.2 , paragraf kedua, meskipun ini berisi referensi ke bagian lain untuk melengkapi definisi tersebut.
Berkenaan dengan template, penggunaan ODR hanyalah sebagian dari pertanyaan; bagian lainnya adalah instansiasi. Secara khusus, §14.7 mencakup ketika sebuah templat digunakan. Tetapi keduanya terkait: meskipun teks dalam §14.7.1 (instansiasi implisit) cukup panjang, prinsip dasarnya adalah bahwa template hanya akan dibuat instance-nya jika digunakan, dan dalam konteks ini, digunakan berarti digunakan ODR. Jadi, fungsi anggota template kelas hanya akan dibuat instance-nya jika dipanggil, atau jika itu virtual dan kelas itu sendiri dibuat instance-nya. Standar itu sendiri mengandalkan hal ini di banyak tempat:
std::list<>::sort
penggunaan<
pada masing-masing elemen, tetapi Anda dapat membuat contoh daftar di atas jenis elemen yang tidak mendukung<
, selama Anda tidak memanggilnyasort
.sumber
Sederhananya, odr-used berarti sesuatu (variabel atau fungsi) digunakan dalam konteks di mana definisi itu harus ada.
misalnya,
struct F { static const int g_x = 2; }; int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed. // so it's OK without the definition of g_x vector<int> vi; vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect // a const lvalue, so it's definition must be present
Catatan, push_back di atas diteruskan di MSVC 2013, perilaku ini tidak sesuai standar, baik gcc 4.8.2 dan clang 3.8.0 gagal, pesan kesalahannya adalah: referensi tidak ditentukan ke `K :: g_x '
sumber
vi.push_back( F::g_x );
di c ++?const int&
? Mungkinkah anggota konstanta statis diubah menjadi nilai r?push_back
, tentu saja akan lolos. Bukan?operator+
.