Tür Nitelikleri
__traits anahtar sözcüğü ve std.traits modülü, türlerin niteliklerine yönelik olan üst düzey olanaklar sunarlar. Çoğunlukla kütüphaneler yazarken yararlı olan bu olanaklar başka derlemeli dillerde ya hiç bulunmazlar ya da C++'ta olduğu gibi kullanımları çok zordur.
__traits'in sunduğu bilgiler dilin başka olanakları tarafından edinilemeyen ve çoğunlukla derleyicinin toplamış olduğu bilgilerdir. Bu bilgiler özellikle şablon kodlarında ve koşullu derleme sırasında yararlı olabilirler.
Örneğin yalnızca aritmetik türlerle işleyebilen bir işlev şablonu, "aritmetik mi" anlanıma gelen isArithmetic'i şablon kısıtlamasında şöyle kullanabilir:
void birİşlev(T)() if (__traits(isArithmetic, T)) { // ... }
Başka bir örnek olarak, T gibi bir şablon parametresinin aritmetik bir tür olup olmamasına göre kod farklı biçimde gerçekleştirilebilir:
static if (__traits(isArithmetic, T)) { /* ... aritmetik bir türmüş ... */ } else { /* ... değilmiş ... */ }
__traits
__traits, derleyicinin koddan edinmiş olduğu bilgileri sorgulamaya yarar. Söz dizimi aşağıdaki gibidir:
__traits(sözcük, parametreler)
sözcük, aşağıda listelenen sözcüklerden birisidir ve __traits'in hangi amaçla kullanıldığını belirler. parametreler ise bir veya daha fazla sayıda olmak üzere tür ismi veya ifadedir. Parametrelerin anlamları kullanılan sözcüğe bağlıdır.
__traits sözcükleri
Bu sözcükler sorgulanmakta olan bilgiyi belirlerler.
Aşağıdaki örneklerdeki türler zaten bariz olduklarından __traits'in yararı bu bölümde tam olarak anlaşılamıyor. Örneğin ulong'un aritmetik bir tür olup olmadığını __traits ile sorgulamaya gerek yoktur. Bu sözcükler özellikle şablon kodlarında ve çoğunlukla T olarak isimlendirdiğimiz türler hakkında bilgi edinmek için yararlıdırlar.
Ek olarak, aşağıdaki çoğu örnekte parametre olarak türler kullandığım halde aslında çoğu durumda herhangi bir ifade de kullanılabilir.
isAbstractClass: Soyut sınıflar içintrue, diğerleri içinfalseüretir.
import std.stdio; abstract class BütünİşlevleriSoyutSınıf { void foo(); } class EnAzBirİşleviSoyutSınıf { abstract void foo(); } class SomutSınıf { void foo() {} } void main() { writeln(__traits(isAbstractClass, BütünİşlevleriSoyutSınıf)); writeln(__traits(isAbstractClass, EnAzBirİşleviSoyutSınıf)); writeln(__traits(isAbstractClass, SomutSınıf)); }
true true false
isArithmetic: Aritmetik türler için true üretir.struct Öğrenci {} // ... writeln(__traits(isArithmetic, ulong)); writeln(__traits(isArithmetic, string)); writeln(__traits(isArithmetic, Öğrenci)); }
true false false
isAssociativeArray: Eşleme tabloları için true üretir.writeln(__traits(isAssociativeArray, int[string])); writeln(__traits(isAssociativeArray, int[42]));
true false
isFinalClass: Kendilerinden türetilemeyen sınıflar için true üretir.class TüretilebilenSınıf {} final class TüretilemeyenSınıf {} // ... writeln(__traits(isFinalClass, TüretilebilenSınıf)); writeln(__traits(isFinalClass, TüretilemeyenSınıf));
false true
isFloating: Kesirli sayılar için true üretir.writeln(__traits(isFloating, double)); writeln(__traits(isFloating, 7));
true false
isIntegral: Tamsayılar için true üretir.writeln(__traits(isIntegral, double)); writeln(__traits(isIntegral, 7));
false true
isScalar: Büyüklüğü olan türler için true üretir.Aritmetik türler olmadıkları halde göstergelerin de büyüklükleri vardır:
writeln(__traits(isArithmetic, int*)); writeln(__traits(isScalar, int*));
false true
isStaticArray: Sabit uzunluklu diziler için true üretir.writeln(__traits(isStaticArray, int[10])); writeln(__traits(isStaticArray, int[]));
true false
isUnsigned: İşaretsiz türler için true üretir.writeln(__traits(isUnsigned, ulong)); writeln(__traits(isUnsigned, long));
true false
isVirtualFunction: Sınıf işlevleri için true üretir.struct Yapı { void foo() {} } class Sınıf { void foo() {} } // ... writeln(__traits(isVirtualFunction, Yapı.foo)); writeln(__traits(isVirtualFunction, Sınıf.foo));
false true
isAbstractFunction: abstract işlevler için true üretir.class Sınıf { abstract void altSınıflardaTanımlanmalıdır(); } // ... writeln(__traits(isAbstractFunction, Sınıf.altSınıflardaTanımlanmalıdır));
true
isFinalFunction: final işlevler için true üretir.class Sınıf { final void tanımıDeğiştirilemez() {} } // ... writeln(__traits(isFinalFunction, Sınıf.tanımıDeğiştirilemez));
true
isStaticFunction: static işlevler için true üretir.class Sınıf { static void nesneÜyesineErişmesiGerekmeyenİşlev() {} } // ... writeln( __traits(isStaticFunction, Sınıf.nesneÜyesineErişmesiGerekmeyenİşlev));
true
isRef: ref parametreler için true üretir.void birİşlev(ref int refParametre, out int outParametre, lazy int lazyParametre) { writeln(__traits(isRef, refParametre)); // ... }
true
isOut: out parametreler için true üretir.void birİşlev(ref int refParametre, out int outParametre, lazy int lazyParametre) { writeln(__traits(isOut, outParametre)); // ... }
true
isLazy: lazy parametreler için true üretir.void birİşlev(ref int refParametre, out int outParametre, lazy int lazyParametre) { writeln(__traits(isLazy, lazyParametre)); // ... }
true
hasMember: Türün belirtilen üyesi varsa true üretir.struct BirTür { int birÜye; void birİşlev() {} } // ... writeln(__traits(hasMember, BirTür, "birÜye")); writeln(__traits(hasMember, BirTür, "birİşlev")); writeln(__traits(hasMember, BirTür, "bulunmayanÜye"));
true true false
identifier: Bir ifadenin programdaki ismini üretir.Örneğin bir alias şablon parametresinin yerine kullanılmış olan asıl isim elde edilebilir:
struct BirYapı(alias T) { static string bilgi = __traits(identifier, T) ~ " ile kullanıldım"; void bilgiVer() { writeln(bilgi); } } // ... int birDeğişken; auto nesne = BirYapı!birDeğişken(); nesne.bilgiVer();
birDeğişken ile kullanıldım
getMember: Belirtilen üyeye eriştirir.struct Yapı { int i; } // ... auto nesne = Yapı(); // nesne.i = 42 ifadesinin eşdeğeri: __traits(getMember, nesne, "i") = 42; // writeln(nesne.i) ifadesinin eşdeğeri: writeln(__traits(getMember, nesne, "i"));
42
getOverloads: Belirtilen işlevin yüklemelerinden oluşan dizi üretir.struct Yapı { void foo() {} double foo(int i) { return i; } } // ... foreach (i, yükleme; __traits(getOverloads, Yapı, "foo")) { writefln("%s: %s", i, typeid(typeof(yükleme))); }
0: void() 1: double()
getVirtualFunctions: Belirtilen işlevin, tanımları alt sınıflar tarafından değiştirilebilen yüklemelerinden oluşan dizi üretir.class Sınıf { void foo() {} double foo(int i) { return i; } } // ... foreach (i, yükleme; __traits(getVirtualFunctions, Sınıf, "foo")) { writefln("%s: %s", i, typeid(typeof(yükleme))); }
0: void() 1: double()
parent: Belirtilen ismi içeren ortamı üretir.void foo(alias değişken)() { writeln(typeid(typeof(__traits(parent, değişken)))); } void main() { double içeren() { int i; foo!i(); return 0; } içeren(); }
foo()'nun şablon parametresi olarak kullanılan i'yi içeren ortamın türü yazdırılır:
double()
classInstanceSize: Sınıf nesnesinin büyüklüğünü üretir.class Sınıf { int[10] dizi; } // ... writeln("değişkenin büyüklüğü: ", Sınıf.sizeof); writeln("nesnenin büyüklüğü : ", __traits(classInstanceSize, Sınıf));
Sınıf değişkenleri yalnızca bir referans olduklarından çoğu durumda sınıf nesnelerinden küçüktürler:
değişkenin büyüklüğü: 4 nesnenin büyüklüğü : 48
allMembers: Bütün üyelerin isimlerinden oluşan dizi üretir.class ÜstSınıf { double üstSınıfÜyesi; void üstSınıfİşlevi() {} } class AltSınıf : ÜstSınıf { int altSınıfÜyesi; void altSınıfİşlevi() {} } // ... foreach (üye; __traits(allMembers, AltSınıf)) { writeln(üye); }
altSınıfÜyesi altSınıfİşlevi üstSınıfÜyesi üstSınıfİşlevi toString toHash opCmp opEquals Monitor factory
derivedMembers: Alt sınıf üyelerinden oluşan dizi üretir.foreach (üye; __traits(derivedMembers, AltSınıf)) { writeln(üye); }
altSınıfÜyesi altSınıfİşlevi
isSame: İki parametre de aynı isim iseler true üretir.void foo(alias isim0, alias isim1)() { writeln(__traits(isSame, isim0, isim1)); } // ... int i; foo!(i, i)();
true
compiles: Parametreleri derlenebiliyorsa true üretir.struct Yapı { int foo() { return 0; } } class Sınıf { double bar() { return 1.5; } } class BaşkaSınıf { void bar() {} } void birİşlev(T0, T1)(T0 birinci, T1 ikinci) { static if (__traits(compiles, birinci.foo() / ikinci.bar())) { writeln("bölme işlemi uygulanabiliyor"); } else { writeln("bölme işlemi uygulanamıyor"); } } // ... auto yapı = Yapı(); auto sınıf = new Sınıf(); auto başkaSınıf = new BaşkaSınıf(); birİşlev(yapı, sınıf); birİşlev(yapı, başkaSınıf);
Sınıf.bar'ın dönüş türü double olduğu için bölme işlemi derlenebilir ama BaşkaSınıf.bar'ın dönüş türü void olduğu için derlenemez:
bölme işlemi uygulanabiliyor bölme işlemi uygulanamıyor
Ne zaman kullanmalı
Bu olanaklardan çoğunlukla şablon içeren kütüphanelerde yararlanılır. isArithmetic, isIntegral, hasMember ve compiles gibi basit olanların dışındakilerle günlük programlamada fazla karşılaşılmaz.
std.traits modülü
Bu modüldeki şablonlar, __traits'in ürettiği bilgilerin benzerlerini kütüphane olanakları olarak ve yine derleme zamanında üretirler.
Burada örnek olarak yalnızca karakter ve dizgi türleriyle ilgili olanlarını göstereceğim. Bu modülde çok sayıda başka olanak da bulunur.
isSomeChar: Bir karakter türüysetrueüretir.
import std.traits; void foo(T)(T parametre) if (isSomeChar!T) { // ... } // ... foo('a'); // ← derlenir foo(42); // ← derleme HATASI
isSomeString: Herhangi bir dizgi türüyse true üretir.static if (isSomeString!T) { // ... bir dizgi türüymüş ... } else { // ... değilmiş ... }
isNarrowString: char ve wchar dizgileri için true üretir.void foo(T)(T parametre) if (isNarrowString!T) { // ... }
std.traits modülünün diğer olanakları da benzer biçimde kullanılırlar.
Özet
__traits ve std.traits türler hakkında derleme sırasında bilgi edinmeye yararlar. Özellikle __traits, derleyicinin derleme sırasında toplamış olduğu bilgileri edinmeye yarayan güçlü bir olanaktır.
Kitaplar
Forum
Tanıtım
İletişim
Hakları