Şablonlar çok güzel bir olanak ve C++'dakilerden çok daha güçlü.
Şablorlar dersini mutlu mutlu yazarken bir sorunla karşılaştım. Şimdi Digital Mars haber grubundan sordum bakalım mantıklı bir açıklaması varmıymış...
Sorun şu: Girişten istediğim türde bir değer okuyan bir şablon yazıyoruz:
import std.cstream;
T giriştenOku(T)(string soru)
{
dout.writef(soru, ": ");
T cevap;
din.readf(&cevap);
return cevap;
}
void main()
{
auto yaş = giriştenOku!int("Yaşınız?");
}
int, double, kendi türlerimiz, vs. için gayet güzel çalışıyor. Ama string için çalışmıyor. string'in elemanları 'immutable char' oldukları için, şablon içindeki 'din.readf' çağrısı parçalama hatasına (segmentation fault) neden oluyor.
Mantıklı... O zaman şablonların özelleme (specialization) olanağından yararlanarak string için özel bir tanımını veriyoruz:
T giriştenOku(T : string)(string soru)
{
// ... öncekinin tekrarı olabilir; ama .idup döndürmesi gerek:
return cevap.idup;
}
'(T : string)', bu tanımın şablonun string özellemesi olduğunu belirtiyor.
Sorun bu noktada ortaya çıkıyor: dmd char[] türü için de aynı özellemeyi seçiyor ve bu sefer de sonundaki .idup, char[] için sorun oluşturuyor.
Sorunlu bütün bir program:
import std.cstream;
T giriştenOku(T)(string soru)
{
dout.writef(soru, ": ");
T cevap;
din.readf(&cevap);
return cevap;
}
T giriştenOku(T : string)(string soru)
{
dout.writef(soru, ": ");
T cevap;
din.readf(&cevap);
return cevap.idup;
}
void main()
{
auto isim = giriştenOku!string("İsminiz?");
auto adres = giriştenOku!(char[])("Adres?");
auto yaş = giriştenOku!int("Yaşınız?");
}
İsim için '!string', ve adres için '!(char[])' kullandığıma dikkat edin. Her ikisi için de özelleştirme seçiliyor ve program char[] durumundaki .idup için derlenmiyor.
Tabii aslında kod tekrarını azaltmak için asıl özelleme şöyle:
T giriştenOku(T : string)(string soru)
{
return giriştenOku!(char[])(soru).idup;
}
Yani string özellemesinde, genel tanımı char[] için kullanmayı umuyorum ama olmuyor.
Çözüm: std/conv.d dosyasının içine bakıyorum ve bu işi to!string için nasıl hallettiklerini öğreniyorum. Çok güzel değil... :) D'nin koşullu derleme olanaklarından yararlanıyorlar: 'static if'...
Ben de şablonların koşullu derleme olanağına da başvuruyorum ve sonunda herşey halloluyor. Çalışan program şöyle:
import std.cstream;
T giriştenOku(T)(string soru)
{
dout.writef(soru, ": ");
T cevap;
din.readf(&cevap);
return cevap;
}
T giriştenOku(T : string)(string soru)
if (is (T == string)) // <-- GEREKLİ
{
return giriştenOku!(char[])(soru).idup;
}
void main()
{
auto isim = giriştenOku!string("İsminiz?");
auto adres = giriştenOku!(char[])("Adres?");
auto yaş = giriştenOku!int("Yaşınız?");
}
Ama bu da çok saçma çünkü o özellemede şöyle bir anlam var: "bu, T'nin string olduğu durum için özellemedir; ama bunu T'nin string olduğu durumda göze al." :)
Bir bozukluk var. Haber gruplarında sordum; belki bilinen bir hatadır veya bir açıklaması vardır.
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]
Permalink
Reply