Variadic Şablonlar
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 67 / 104.
Her türden, herhangi bir sayıda bağımsız değişken kabul eden bir işleve ihtiyacınız olursa ne yaparsınız? Geleneksel şablonlar, tam olarak kaç tür parametresine ihtiyaç duyduğunuzu belirtmenizi gerektirir. Değişken sayıda bağımsız değişken alan şablonlar, şablonların isteğe bağlı sayıda şablon bağımsız değişkeni kabul etmesine olanak tanıyarak bu sorunu çözer.
Sözdizimi, bir parametre paketi oluşturmak için ... (üç nokta) kullanır:
template <typename... Args>
void printAll(Args... args) {
// Args bir şablon parametre paketidir
// args bir fonksiyon parametre paketidir
}Bağımsız değişkenleri işlemek için genellikle temel durumla birlikte özyineleme kullanırsın. Parametre paketi, hiçbiri kalmayana kadar her seferinde bir bağımsız değişkeni genişletir:
// Temel durum: argüman kalmadı
void print() {
std::cout << std::endl;
}
// Özyinelemeli durum: ilk argümanı işle, kalanıyla özyinele
template <typename T, typename... Rest>
void print(T first, Rest... rest) {
std::cout << first << " ";
print(rest...); // Kalan argümanları genişlet
}
print(1, 3.14, "hello", 'x'); // Çıktı: 1 3.14 hello xDaha basit işlemler için açık özyineleme kullanmadan katlama ifadelerini (C++17) de kullanabilirsiniz:
template <typename... Args>
auto sum(Args... args) {
return (args + ...); // Fold ifadesi: tüm argümanları toplar
}
std::cout << sum(1, 2, 3, 4) << std::endl; // Çıktı: 10Değişken bağımsız değişkenli şablonlar, std::make_unique, std::tuple ve std::function gibi birçok standart kitaplık özelliğine güç verir. Her türden bağımsız değişken türü ve sayısının herhangi bir birleşimiyle çalışan, tür güvenli işlevler oluşturmalarını sağlar.
Görev
KolayHerhangi sayıda bağımsız değişken içeren iletileri işlemek için değişken sayıda parametreli şablonları kullanan esnek bir günlük kaydı sistemi oluşturalım. Değerleri birleştirebilen, bağımsız değişkenleri sayabilen ve biçimlendirilmiş çıktı yazdırabilen yardımcı programlar oluşturacaksınız: bunların tümünü parametre paketlerini kullanarak yapacaksınız.
Kodunuzu iki dosya arasında düzenleyeceksiniz:
Variadic.h: Değişken sayıda parametre alan şablon işlevlerinizi burada tanımlayın.Tüm bağımsız değişkenlerini aralarında boşluk olacak şekilde ve ardından yeni satır yazdıran bir
printAllişlevi oluşturun. Yalnızca yeni satır yazdıran bir temel durum ve ilk bağımsız değişkeni, bir boşluğu yazdırıp kalan bağımsız değişkenlerle yinelemeli olarak devam eden bir özyinelemeli durum kullanın.İşleve geçirilen bağımsız değişkenlerin sayısını döndüren bir
countArgsişlevi oluşturun. Parametre paketinin boyutunu elde etmek içinsizeof...kullanın.Tüm sayısal bağımsız değişkenleri toplayıp sonucu döndüren bir
sumişlevi oluşturun.+işleciyle birlikte bir katlama ifadesi kullanın.Tüm sayısal bağımsız değişkenleri çarpıp sonucu döndüren bir
productişlevi oluşturun.*işleciyle birlikte bir katlama ifadesi kullanın.main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):- Bir tamsayı
- Bir double
- Bir dize
- Bir karakter
Değişken sayıda parametreli şablonlarınızı şu şekilde gösterin:
- Dört girdinin tümüyle
printAllişlevini çağırın ve sonucu yazdırın countArgsişlevini tamsayı, double ve karakterle çağırırken bağımsız değişkenlerin sayısını yazdırın:Argument count: <count>- Tamsayıyı, double'ı ve 10 ile 5 değerlerini toplayın, ardından şunu yazdırın:
Sum: <result> - Tamsayı ile 2 ve 3 değerlerini çarpın, ardından şunu yazdırın:
Product: <result> printAllişlevini yalnızca dizeyle (tek bağımsız değişken) çağırınprintAllişlevini bağımsız değişken olmadan çağırın (yalnızca yeni satır yazdırmalıdır)
Örneğin girdiler 5, 2.5, Hello ve X olduğunda:
5 2.5 Hello X
Argument count: 3
Sum: 22.5
Product: 30
Hello
printAll işlevinin dört bağımsız değişkenden sıfıra kadar, farklı türlerdeki herhangi bir sayıda bağımsız değişkeni nasıl işlediğine dikkat edin. sum ve product işlevleri, tüm değerleri açık bir özyineleme olmadan zarif bir şekilde birleştirmek için katlama ifadelerini kullanır. countArgs işleviniz, sizeof... ifadesinin paket boyutunu derleme zamanında nasıl verdiğini gösterir.
Kendin dene
#include <iostream>
#include <string>
#include "Variadic.h"
using namespace std;
int main() {
// Girdileri oku
int intVal;
double doubleVal;
string strVal;
char charVal;
cin >> intVal;
cin >> doubleVal;
cin >> strVal;
cin >> charVal;
// TODO: printAll'ı dört girdiyle çağır
// TODO: Print argument count using countArgs with intVal, doubleVal, and charVal
// Format: "Argument count: <count>"
// TODO: intVal, doubleVal, 10 ve 5'in toplamını hesapla ve yazdır
// Biçim: "Sum: <result>"
// TODO: intVal, 2 ve 3'ün çarpımını hesapla ve yazdır
// Biçim: "Product: <result>"
// TODO: printAll'ı sadece string ile çağır
// TODO: printAll'ı argümansız çağır
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic KonteynerKendi başına pratik yap: Online C++ derleyicisi