Cpp17 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Cpp17 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Metaprogramming | Variadic Templates & Fold Expressions - 1

C++11 değişken parametreli şablonları desteklemektedir. Dile gelen bu araçla birlikte hem sınıf şablonları (class templates) hem de fonksiyon şablonları (function templates) artık istenen sayıda parametreye sahip olabiliyor. Değişken sayıda parametreye "parametre paketi" (parameter pack) deniyor. Bir şablon parametre listesinde typename anahtar sözcüklerini izleyen üç nokta atomundan (ellipsis) sonra gelen isim, söz konusu şablon parametresinin sıfır ya da daha fazla sayıda türe karşılık geldiğine işaret etmektedir. Bu syntax'ta "typename… Types" şablon parametre paketi (template parameter pack), "Types… values" ise fonksiyon parametre paketi (function parameter pack) olarak isimlendirilmektedir. C++17'den önce variadic template yazılırken recursive bir yapıda yazma metodolojisi izleniyordu. Aşağıdaki örnekte görüleceği üzere ikinci printer() fonksiyonu recursive çağrı yapacak şekilde yazılmıştır.


Yukarıda tek parametreli bir template specialization yapıldığını görebilirsiniz. Toplamda iki tane fonksiyona ihtiyaç duyulmuştur. Peki C++17'den sonra durum nedir?


Yukarıda ilk dikkatimizi çeken nokta tek bir fonksiyonla işin halledilmiş olması. Peki bu nasıl gerçekleşti? Aşağıda fold (katlı ifadelerin açılımı) expression 'ların açılımı görülmektedir.


Burada belirleyici nokta operandların hangi sıraya göre yapılacağıdır. 
  • (… op pack)                 ---->   ((pack1 op pack2 op …) op packN
  • (init op … op pack)   ---->   (((init op pack1) op pack2) op …) op packN
  • (pack op …)                 ---->    pack1 op (… op (packN-1 op packN))
Aşağıda genelleştirilmiş şekilde ifade edildiği ve bir örnek üzerinde açıklandığını görebilirsiniz.


Aşağıda ise fold expression ifadelerin nasıl bir container içine yerleştirilebileceğine ilişkin örneği bulabilirsiniz.


Aşağıda ise C++17 öncesi variadic bir toplama fonksiyonunun yazılışı görülmektedir.


fold expression ile aynı fonksiyonun yazılışı aşağıdaki gibidir.


Soru1: aşağıdaki örnekte std::forward kullanılmasının bize ne gibi avanatajı veya dezavantajı vardır?


Soru2: Aşağıdaki kodun çıktısı ne olur?




CTAD (Class Template Argument Deduction)

CTAD (Class Template Argument Deduction); template fonksiyonlara ilişkin deduction guide line gibi sınıflar için de benzer şekilde C++17 ile standartlara gelmiştir. Bu sayede sınıflara ilişkin doğrudan explicit olarak belirtmeye gerek kalmadan bu görevi de compiler' a havale edilmesi sağlanmıştır. Ve daha kısa ve anlaşılır kodlar yazılmasına olanak sağlanmıştır. CTAD 'ın daha anlaşılır olması için aşağıdaki iki örneğe bakalım.

C++11 oncesi
C++17 öncesi
Yukarıdaki örnek için C++17 öncesi class template argument 'lerini doğrudan (explicit) olarak bildirmemiz gerekmektedir. Aksi halde hata ile karşılaşılmaktadır. Fakat C++17 ile bu problemler çözülmüştür. 

C++17 sonrası
Şimdi tam bir template class yazalım ve C++ 'in  11 - 14 ve 17 standartlarına göre derlemeye çalışalım.


Yukaridaki örneği C++11 ve C++14 ile derlemeye çalıştığımız zaman aşağıdaki gibi bir hata ile karşılaşılmaktadır. Fakat C++17 ile derledigimiz zaman ise sorunsuz derlenebilmektedir.


C++17 öncesi için yukaridaki problem aşağıdaki şekilde kodu güncelledigimiz zaman ortadan kalkmaktadir.


Fakat C++17 öncesi için de farklı bir workaround bulunmaktadır. Örnegin make_pair fonksiyonu ile yukarıdaki 17. satırdaki işlemi make_pair ile explicit olarak tür belirtmeden yapmak mümkündür.