Decltype vs Auto: Template Kodda Tür Çıkarımında Doğru Aracı Seçmek
C++'ta template kod yazarken auto ve decltype ikisi de tür çıkarımı yapıyor, ama aynı işi yapmıyorlar. Bu farkı anlamadan yazılan kod ya referans kaybediyor, ya da beklenmedik const/volatile özellikleri taşıyor.
autobir değişken bildirimidir. Derleyici sağ tarafı değerlendirir ve uygun türü atanır. Ama referans ve const bilgisini atıyor:
1int x = 5;2int& ref = x;34auto a = ref; // int, referans kayboldu5auto& a2 = ref; // int&, referans korundudecltype ise tam olarak ne gördüğünü rapor eder. Referans, const, hepsi korunur:
1decltype(ref) d = ref; // int&, referans korundu2decltype(x) d2 = x; // intFark önemli mi? Evet. Bir template'de yanlış tür seçimi, beklenmedik kopya oluşturabilir, performans düşürebilir veya kodun çalışmasını durdurabilir.
Bir generic forward fonksiyonu düşün:
1template<typename T>2void process(T&& arg) {3auto result = some_function(arg);4// result'ün türü ne?5}Eğer some_function bir referans döndürüyorsa ve siz auto kullandıysanız, referans kaybolur. Sonra result üzerinde değişiklik yaparsanız, orijinal nesneyi etkilemezsiniz. Hata bulunması zor.
decltypekullanırsanız:
1decltype(some_function(arg)) result = some_function(arg);Bu, some_function'ın döndürdüğü türü tam olarak alır. Referans varsa korunur.
Modern C++'ta sık karşılaşılan bir pattern, trailing return type'tır:
1template<typename T, typename U>2auto add(T a, U b) -> decltype(a + b) {3return a + b;4}Burada decltype(a + b) dönüş türünü dinamik olarak belirler. auto tek başına bunu yapamaz; derleyici a + b'nin türünü tahmin etmeye çalışır ama template parametreleri tam net değilse başarısız olabilir.
C++14+ ile auto dönüş türü de mümkün ama her durumda güvenli değildir. decltype daha açık ve niyeti belirtir.
auto kullan:
- Basit, yerel değişkenlerde (int, string gibi)
- Referans kaybı sorun değilse
- Kod okunabilirliği önemli ve tür açık ise
decltype kullan:
- Template'lerde, özellikle generic kod yazıyorsan
- Referans, const, volatile gibi nitelikler önemli ise
- Dönüş türü başka bir ifadenin türüne bağlı ise
- Trailing return type pattern'de
auto rahat ve kısa, ama decltype daha kesin. Template kod yazıyorsan, ki bu C++'ta kaçınılmaz, decltype'ın ne yaptığını bilmek zorunlu. Referans kaybı, sessiz hata olur; çoğu zaman runtime'da fark edersin. Başlangıçta biraz verbose görünse de, decltype template kodunda güvenilir ve kasıtlıdır. Onu anlamak, C++ template mastery'nin ilk adımı.
4 yorum
offf aynen kodun çalışması seni aldatıyor işte hata da vermediği için iki saat sonra performans profilinde görüyorsun çok fazla kopyalama olduğunu
İki saat harcaman tamamen haklı auto ile referans kaybı fark etmesi gerçekten zor çünkü kod çalışıyor sadece yavaş decltype öğrenince açılıyor abi
Ayy evet ben de bunu yaşadım auto kullanıp da referans kaybolunca değişken kopyalanıyor sonra niye yazı yavaş diye iki saat harcamıştım decltypeı
Referans kaybetme sorunu gerçekten insanı şaşırtabiliyor Perfect forwarding yapan bir