Ini dilarang baik oleh teks standar dan oleh beberapa implementasi utama seperti yang disebutkan dalam komentar, tetapi untuk alasan yang sama sekali tidak terkait.
Pertama, alasan "menurut buku": titik instantiasi A<C>adalah, menurut standar, tepat sebelum definisiB , dan titik instantiasi std::is_default_constructible<C>adalah tepat sebelum itu:
Untuk spesialisasi templat kelas, [...] jika spesialisasi secara implisit instantiated karena dirujuk dari dalam spesialisasi templat lain, jika konteks dari mana spesialisasi dirujuk tergantung pada parameter templat, dan jika spesialisasi tidak instantiated sebelumnya ke instantiation dari template yang dilampirkan, titik instantiation adalah tepat sebelum titik instantiation dari template yang melampirkan. Kalau tidak, titik instantiasi untuk spesialisasi seperti itu segera mendahului deklarasi ruang lingkup atau definisi namespace yang mengacu pada spesialisasi.
Karena Cjelas tidak lengkap pada saat itu, perilaku instantiating std::is_default_constructible<C>tidak terdefinisi. Namun, lihat masalah inti 287 , yang akan mengubah aturan ini.
Pada kenyataannya, ini ada hubungannya dengan NSDMI.
- NSDMI aneh karena tertunda parsing - atau dalam bahasa standar mereka adalah "konteks kelas lengkap".
- Dengan demikian, yang
= 0pada prinsipnya dapat merujuk pada hal-hal yang Bbelum dinyatakan, sehingga implementasi tidak dapat benar-benar mencoba menguraikannya sampai selesai B.
- Menyelesaikan kelas mengharuskan deklarasi implisit fungsi anggota khusus, khususnya konstruktor default, karena
Ctidak ada konstruktor yang dideklarasikan.
- Bagian dari deklarasi itu (keteguhan, ketidak-kecurangan) tergantung pada sifat-sifat NSDMI.
- Jadi, jika kompiler tidak dapat mengurai NSDMI, ia tidak dapat menyelesaikan kelas.
- Akibatnya, pada saat instantiate
A<C>, ia berpikir bahwa Citu tidak lengkap.
Seluruh area yang berurusan dengan wilayah yang diurai-tertunda ini sangat tidak ditentukan, disertai dengan divergensi implementasi. Mungkin perlu beberapa saat sebelum dibersihkan.