Saya memahami bahwa parameter template bukan tipe harus berupa ekspresi integral yang konstan. Bisakah seseorang menjelaskan mengapa demikian?
template <std::string temp>
void foo()
{
// ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.
Saya mengerti apa itu ekspresi integral konstan. Apa alasan untuk tidak mengizinkan jenis tidak konstan seperti std::string
pada cuplikan di atas?
Jawaban:
Alasan Anda tidak dapat melakukan ini adalah karena ekspresi non-konstan tidak dapat diurai dan diganti selama waktu kompilasi. Mereka bisa berubah selama runtime, yang akan membutuhkan pembuatan template baru selama runtime, yang tidak mungkin dilakukan karena template adalah konsep waktu kompilasi.
Inilah yang diizinkan standar untuk parameter template non-tipe (14.1 [temp.param] p4):
sumber
Itu tidak diperbolehkan.
Namun, ini diperbolehkan:
template <std::string * temp> //pointer to object void f(); template <std::string & temp> //reference to object void g();
Lihat §14.1 / 6,7,8 dalam C ++ Standard (2003).
Ilustrasi:
template <std::string * temp> //pointer to object void f() { cout << *temp << endl; } template <std::string & temp> //reference to object void g() { cout << temp << endl; temp += "...appended some string"; } std::string s; //must not be local as it must have external linkage! int main() { s = "can assign values locally"; f<&s>(); g<s>(); cout << s << endl; return 0; }
Keluaran:
can assign values locally can assign values locally can assign values locally...appended some string
sumber
std::string
pointer atau objek referensi. Jika variabel itu lokal, Anda mungkin akan mendapatkan alamat yang berbeda setiap kali fungsi dipanggil.Anda harus mampu mengatasi argumen template
template <std::string temp> void f() { // ... } f<"foo">(); f<"bar">(); // different function!?
Sekarang impl akan perlu muncul dengan urutan karakter yang unik untuk
std::string
atau, dalam hal ini, kelas yang ditentukan pengguna sewenang-wenang lainnya, menyimpan nilai tertentu, yang artinya tidak diketahui oleh implementasi. Selain itu, nilai objek kelas arbitrer tidak dapat dihitung pada waktu kompilasi.Direncanakan untuk mempertimbangkan mengizinkan jenis kelas literal sebagai jenis parameter template untuk post-C ++ 0x, yang diinisialisasi oleh ekspresi konstan. Mereka dapat dihancurkan dengan membuat anggota data secara rekursif dihancurkan sesuai dengan nilainya (untuk kelas dasar, misalnya kita dapat menerapkan depth-first, traversal kiri-ke-kanan). Tapi itu pasti tidak akan berhasil untuk kelas yang sewenang-wenang.
sumber
Argumen template non-tipe yang disediakan dalam daftar argumen template adalah ekspresi yang nilainya dapat ditentukan pada waktu kompilasi. Argumen seperti itu harus:
Selain itu, literal string adalah objek dengan tautan internal, jadi Anda tidak dapat menggunakannya sebagai argumen template. Anda juga tidak dapat menggunakan penunjuk global. Literal floating-point tidak diperbolehkan, mengingat kemungkinan kesalahan pembulatan yang jelas.
sumber