Metaprogramming | basic implementation of std::enable_if and SFINAE - 1

std::enable_if C++11 ile hayatımıza giren bir özellik ve Metaprogramming yapılırken SFINAE olarak bilinen idiyomun en önemli kullanım senaryosunu oluşturmaktadır. std::enable_if'in olası implementasyonu aşağıdaki gibidir.


Burada kritik nokta birinci template için sınıfın içinde hiç bir bildirim yapılmazken 2. ise template partial specialization olarak isimlendirilen bir özelleştirilmiş şablon sınıfta typedef bildirimi yapılmış olmasıdır. Birinci şablon parametresi true olursa derleyici kod üretimi için bu şablonu kullanacak. Diğer durumlarda ilkini kullanacaktır. Peki bu bize nasıl bir kullanım olanağı sağlıyor? Aşağıdaki örneği inceleyelim:


Yukarıda göreceğiniz üzere T türü int olursa; enable_if'in template 1. parametresi true olarak açılacak, 2. fonksiyon için false olarak açılacak. Yani implemetasyonda görüleceği üzere type bildirimi olmayan sınıfla ilişkilendirilecek ve doğal olarak failure durumu oluşacak. Bir işlev şablonu derleyici açısından şablon tür parametresinin ne olduğunu bilmek/çıkarım yapmak zorundadır. Şablon tür parametresinin olduğu ya açıkça belirtilmesi gerekir ya da derleyici tarafından bir çıkarım yapabiliyor olması gerekir. Bu anlama işlemi aşıldıktan sonra derleyici şablonda şablon tür parametresinin bulunduğu yerlerde gerçek tür bilgisini kullanmaya başlar. Örneğin T türünün geçtiği her yerde int türünü kullanarak yerine koyma (substituition) işlemi yapar. Bu yer değiştirme işleminde bir başarısızlık olursa (substitution failure) derleyici bu durumu hemen bir sentaks hatası olarak değerlendirip derleme hatası olarak işlemi sonlandırmaz. Önce diğer şablon işlev yüklemelerine de (overloads) bakmak zorundadır. Eğer bir başka yükleme işlev çağrısı için geçerli olursa derleyici bu yüklemeyi seçer ve sentaks hatası oluşmaz. Bu şekilde ilk failure'u error olarak ele almayıp işleme devam edip başarılı olması durumlarına Substitution Failure Is Not An Error denilmektedir. Sonuç olarak yukarıdaki örneğimizde programnımız doğru bir şekilde derlenecek ve ekranda "Integral" yazısı görülecektir. 


Yukarıdaki örnekte görüleceği üzere enable_if'i daha basite indirgeyerek anlatmak istersek bizim için compile time template switch diyebiliriz. Belirli şartlar sağlanırsa ilgili fonksiyonun çağrılıp çağrılmamasına karar verme mekanizması diyebiliriz. Ve yukarıdaki örnek için bizim fonksiyonumuz sadece integral türler için çalışacak şekilde yazılmış fakat main içinde bu fonksiyonu double türüyle kullanmaya çalıştığımızda hata verecektir.


Yukarıdaki örnekte ise geri dönüş türü üzerinden enable_if'in kullanılmasına bir örnek verilmiştir. Sınıfın 2 tane check fonksiyonu Car sınıfı hangi türden template açılım yapıldı ise açılım yapılan türün V6Engine türünde ise true dönen fonksiyona açılım yapılacak diğer durumlarda false'a geri dönen fonksiyonun açılımı yapılacak şekilde özelleştirilmiştir.