auto geri dönüş değeri türü (auto return type)

C++11‘de işlevlerin geri dönüş değerlerinin türünün ne olduğu konusunda derleyiciler belirli durumlarda çıkarım yapabiliyordu. C++14 standartları ile gelen yeni özellikleri anlamadan önce C++11‘de durum neydi bir bakalım.
Aşağıdaki  gibi bir işlev şablonumuz olsun:

İşlevin geri dönüş değerinin türünün yazılması gereken yere bir soru işareti koydum. Aslında işlevin geri dönüş değerinin

ifadesinin türünden olması gerekiyor. Ama bu türün ne olacağı derleyicinin bu şablondan bir işlev kodu üretmesi sırasında belli olacak. Akla gelen ilk çözüm şu:

Neden bu mümkün değil? Çünkü işlev şablonunun parametre değişkenleri isimleri, geri dönüş değerinin türünün yazıldığı yerde bilinmiyor. C++11‘in standartlarıyla oluşturulan çözüme “sonradan yazılan geri dönüş değeri” (trailing return type) deniyor:

İşlevin geri dönüş değerinin türünün yazıldığı yere auto belirtecini yazdık. Parametre parantezinin kapanmasından sonra gelen -> (ok) atomundan sonra ise işlevin geri dönüş değerinin türünü yazıyoruz. Parametreler burada biliniyor kabul edildiğinden artık sorun yok.
Şimdi de aşağıdaki örneği inceleyelim:

func isimli işlev şablonununda “sonradan yazılan geri dönüş değeri türü” kulanılmış. İşlevin geri dönüş değeri türü olarak

türü seçilmiş. decltype işlecinin terimi olan ifadenin yapılmadığını hatırlatalım.

Sonradan yazılan geri dönüş değeri işlev şablonlarıyla sınırlı değil. Şablon olmayan işlevlerde de bu özellik kullanabiliyor olsa da bu durumda bir fayda sağladığını söylemek pek mümkün değil:

C++14 ile geri dönüş değerinin türünün ne olması gerektiğinin çıkarımının derleyici tarafından yapılmasına yönelik olanaklar artırıldı. Artık derleyici, tüm işlevler için return deyimine bakarak bir işlevin geri dönüş değeri türünün çıkarımını yapabiliyor. Bunun için işlevin geri dönüş değerinin türü yerine yine auto anahtar sözcüğü yazılıyor. Hepsi bu kadar:

Derleyici şablondan bir işlev ürettiğinde (template instantiation) return deyiminin ifadesi olan

ifadesinin türünün ne olduğuna bakacak ve işlevin geri dönüş değerini bu türden kabul edecek.

Derleyicinin işlevin geri dönüş değerinin türü için bir çıkarım yapabilmesi için işlevin tanımını görmesi gerekiyor. Yani bu özellik inline işlevler, işlev şablonları ve aynı kaynak dosyada yer alacak yardımcı (helper) işlevler için kullanılabiliyor.

Geri dönüş türleri için çıkarım yapılacak işlevlere ilişkin ön bildirimler yapılabiliyor. Ancak bu işlevler tanımlanmadan kullanılamıyorlar:

Yukarıda bildirilen func işlevinin geri dönüş değerinin türünün ne olduğu çıkarımını derleyici işlevin tanımında kullanılan return deyiminden çıkaracak. Ancak derleyicinin işlevin tanımını görmediği bir noktada func işlevi çağrılmış. Kod geçersiz.

Böyle bir bildirim çoğu zaman gereksiz olsa da sınıf kütüphanelerine yönelik bazı kodlama stilleri için fayda sağlayabiliyor:

Geri dönüş türlerine ilişkin verilen bilgiler çelişmedikçe aynı işleve ilişkin yeniden bildirimler (redeclaration) ve tanımlama bir arada bulunabiliyor.

Aynı durum işlev şablonları için de geçerli. Geri dönüş değeri türü auto olarak belirtilmiş bir işlev şablonu bildirimi ve tanımı bir arada bulunabiliyor:

auto geri dönüş değeri türü kodda değişikli yapmayı kolaylaştırırken değişiklik sürecinde söz konusu olabilecek kodlama hatası riskini de azaltıyor. Aşağıdaki sınıf tanımına bakalım:

Myclass sınıfının begin ve itemAt isimli üye işlevlerinin geri dönüş değerleri türleri auto olarak belirlenmiş. Sınıfın private bölümünde yapılan typedef bildirimi değiştirildiğinde bu işlevlerin geri dönüş değerleri türleri de veri öğesi (data member) olarak kullanılan kabın (container) ne olduğuna bağlı olarak değişecek.

auto
geri dönüş değeri türünün sağladığı faydalardan biri de yazım kolaylığı. Eğer işlevin geri dönüş değerinin türünu yazmak uzun ve zahmetli ise aynı zamanda yanlış yazma riski de söz konusu demektir. Aşağıdaki işlev tanımına bakalım:

func işlevinin geri dönüş değeri

türünden. Oysa işlevin geri dönüş değeri türü olarak auto belirteci kullanılsaydı derleyici işlevin geri dönüş değerinin türünün ne olduğu çıkarımını return ifadesi olan expr’nin türüne bakarak gerçekleştirecekti.

Bu tür işlevlerde özyinelemeli (recursive) bir yapı kullanılabiliyor. Ancak özyinelemeli çağrı en az bir return deyiminden sonra yer almalı. Aşağıdaki koda bakalım:

Yukarıda tanımlanan func isimli işlevde geri dönüş değeri türü yerine auto anahtar sözcüğü yazılmış. İşlevin geri dönüş değerinin türünün ne olduğunu derleyici işlevin içinde kullanılan return deyiminden anlayacak. İşlevin tanımında kullanılan ilk return deyimi işlevin kendisini çağırmasından önce yer alıyor. Derleyicinin çıkarım yapmasını engelleyen bir durum söz konusu değil. Kod geçerli.
Şimdi de aşağıdaki koda bakalım:

Yukarıdaki kodda ise derleyicinin ilk olarak gördüğü return deyimi özyinelemeli işlev çağrısını içeriyor. Kod geçersiz.

Geri dönüş değerinin türünün auto olarak bildirilmesi durumunda işlev tanımındak tüm return deyimlerinin aynı türden ifadelere sahip olması gerekiyor. Farklı türlerden geri dönüş değeri üreten return bir arada bulunması sentaks hatası:

Yukarıda tanımlanan func işlevi içinde yer alan birinci return deyimine bakıldığında işlevin geri dönüş değeri türünün int olması ikinci return deyimine bakıldığında ise işlevin geri dönüş değeri türünün double olması gerekiyor. Derleyici kodu geçersiz kabul edecek:

İşlevin geri dönüş değeri olarak auto belirteci kullanılmış ancak işlevin içinde hiçbir return deyimi kullanılmamış ise, işlevin geri dönüş değeri türü void kabul ediliyor:

auto belirteci ile tür çıkarımın yapılmasına ilişkin kurallar auto geri dönüş değeri türü için de geçerli. Aşağıdaki örneklere bakalım:

Yukarıdaki kodda derleyici
f1 isimli işlevin geri dönüş değeri türünü int
f2 isimli işlevin geri dönüş değeri türünü const int & kabul edecek.

Share

Necati Ergin

C ve Sistem Programcıları Derneğinde eğitmen olarak çalışıyor.

Bunlar da ilginizi çekebilir

Kod Eklemek İçin Okuyun
Eklemek istediğiniz kodları lütfen aşağıdaki “pre” kodları arasında yazınız.
<pre class="lang:c++ decode:true ">
--yazacağınız kodlar--
</pre>
(buradan kopyalayarak kullanabilirsiniz)