Saya percaya ini pada dasarnya mendidih ke [temp.inst] / 2 (penekanan milik saya):
Instansiasi implisit dari spesialisasi templat kelas menyebabkan instantiasi implisit dari deklarasi, tetapi bukan definisi , argumen default, atau noexcept-specifier dari fungsi anggota kelas, kelas anggota, enumerasi anggota ruang lingkup, anggota data statis , templat anggota, dan teman; [...]
dan [temp.inst] / 9
Suatu implementasi tidak akan secara implisit memberi contoh […] anggota data statis dari templat kelas […] kecuali jika instantiasi tersebut diperlukan.
Kata-kata dalam standar tentang instantiasi template implisit membuat banyak detail terbuka untuk interpretasi. Secara umum, bagi saya tampaknya Anda tidak bisa mengandalkan bagian-bagian dari template yang tidak sedang dipakai kecuali spesifikasi secara eksplisit mengatakan demikian. Jadi:
Cuplikan # 1
Q. Mengapa kode ini dikompilasi? Bukankah kita membuat Instansiasi A ketika mewarisi dari B? Tidak ada VD di B, jadi bukankah seharusnya kompiler membuat kesalahan di sini?
Anda sedang instantiating A<B>
. Tapi instantiating A<B>
hanya instantiate deklarasi, bukan definisi anggota data statisnya. VB
tidak pernah digunakan dengan cara yang akan membutuhkan definisi yang ada. Kompiler harus menerima kode ini.
Cuplikan # 2
P. Mengapa kompilasi dengan gcc9 / mengapa tidak dikompilasi dengan clang9?
Seperti yang ditunjukkan oleh Jarod42, deklarasi AB
berisi tipe placeholder. Tampak bagi saya bahwa kata-kata dari standar tidak benar-benar jelas tentang apa yang seharusnya terjadi di sini. Apakah instantiasi deklarasi anggota data statis yang berisi tipe placeholder memicu pengurangan tipe placeholder dan, dengan demikian, merupakan penggunaan yang memerlukan definisi anggota data statis? Saya tidak dapat menemukan kata-kata dalam standar yang jelas akan mengatakan ya atau tidak pada itu. Jadi, saya akan mengatakan bahwa kedua interpretasi sama-sama valid di sini dan, dengan demikian, GCC dan dentang keduanya benar ...
Cuplikan # 3
Q. Jika struct B tidak lengkap di sini maka mengapa tidak lengkap di snippet # 2?
Sebuah jenis kelas hanya selesai pada titik di mana Anda mencapai penutupan }
dari kelas-specifier [class.mem] / 6 . Dengan demikian, B
tidak lengkap selama instantiasi implisit A<B>
dalam semua cuplikan Anda. Hanya saja ini tidak relevan untuk Cuplikan # 1. Dalam Cuplikan # 2, dentang memang memberi Anda kesalahan No member named AD in B
sebagai hasilnya. Mirip dengan kasus Snippet # 2, saya tidak dapat menemukan kata-kata kapan tepatnya anggota alias deklarasi akan dipakai. Namun, tidak seperti definisi anggota data statis, tidak ada kata-kata di tempat untuk secara eksplisit mencegah instantiasi alias deklarasi anggota selama instantiasi implisit templat kelas. Jadi, saya akan mengatakan bahwa perilaku GCC dan dentang adalah interpretasi yang valid dari standar dalam kasus ini ...
struct B
instantiatingA
denganB
?