ilk değer vermeli if deyimi (if statement with initializer)

Derleyiciler C++17 ile gelecek yeni özellikleri artık yavaş yavaş gerçekleştirmeye başladılar. C++11, C++14 derken C++17 de giderek daha fazla kodlama hayatımıza girecek gibi görünüyor. Öğrenecek çok şey var diye endişe etmeyin. Standartların bir sonraki sürümü 2020 yılında yayımlanacak. En az 3 sene var olan standartlarla idare edeceğiz.
İlk değer vermeli if deyimi doğrudan dil çekirdeğine yapılan bir ekleme (core language feature). Bu yeni if deyiminin sözdizimine geçmeden önce ihtiyaç noktasını bir anlamaya çalışalım. Aşağıdaki kodu inceleyelim:

main işlevi içinde tanımlanan mymap nesnesinin tuttuğu değerler içinde 20 anahtar değeri (key) aranıyor. Eğer aranan anahtar değeri bulunursa bu anahtara ilişkin isim (value) değiştiriliyor. find üye işlevinden alınan geri dönüş değerinin yalnızca bu if deyiminde kullanılacağını, kodun başka bir yerinde bu değere gereksinim duyulmayacağını düşünelim. Kodda kullanılan if deyiminden sonra da iter ismi bilinir, değil mi? Yani iter ismini yalnızca atama işleminde ve if deyimi içinde kullanmamıza karşın, iter ismi main işlevinin sonuna kadar her yerde bilinecek. Bir ismin kullanıldığı kod alanının dışında bilinmesi (scope leakage), kodu değiştirmeyi zorlaştırdığı gibi kodlama hatalarına da davetiye çıkartıyor.
Yukarıdaki kodda iter isminin bilinirlik alanını yalnızca kullanıldığı yerle sınırlamak için yapay bir blok oluşturabilirdik:

Bir kontrol deyimine bağlı olmayan böyle bloklar hem çirkin bir görüntü oluşturuyor hem de kodun okunmasını zorlaştırıyor.

C++17 standartları ile birlikte if deyimi parantezi içinde bir değişken tanımlayabiliyor, bu değişkene ilk değer verebiliyor ve bu değişkeni yine if parantezi içindeki koşul ifadesinde (conditional expression) kullanabiliyoruz. Bu şekilde tanımlanan bir değişken yalnızca if deyiminin kendi kapsamında (scope) biliniyor.

if parantezi içinde kullanılan “;” atomuna dikkat edin.

Deyimin genel sözdizimi şöyle:

if parantezi içindeki “;” atomunun if parantezini iki kısma ayırdığını düşünelim. Kodumuzda if parantezinin birinci kısmında auto belirteci ile iter isimli bir değişken tanımlanıyor ve bu değişken map sınıfının find işlevinin geri dönüş değeriyle başlatılıyor. if parantezinin ikinci kısmında yer alan koşul ifadesi ile iter değişkenin değerinin mymap.end() değeri olup olmadığı sınanıyor. iter ismi yalnızca bu if deyiminin bilinirlik alanında kullanılabiliyor.

Standartlarda bu değişikliğe ilişkine verilen öneride geçen örneklere bakalım:

“ilk değer vermeli if deyimi” terimini kullanmış olsak da if parantezi içinde tanıtılan değişkene ilk değer vermek zorunlu değil:

Yukarıdaki kodda yer alan if deyiminin parantezi içinde ismi buf olan 10 öğeli bir char dizi tanımlanıyor. if parantezi içindeki koşul ifadesi, yani “;” atomundan sonra yer alan ifade olarak, standart bir C işlevi olan fgets‘e yapılan bir çağrı kullanılmış. Çağrılan fgets işlevi standart giriş akımının tamponunda okuyacak karakter bulamaz ise NULL gösterici döndürecek ve bu değer lojik “yanlış” olarak yorumlanacak. Bu durumda kodun akışı if deyiminin doğru kısmına girmeyecek. fgets işlevi başarılı olursa if‘in doğru kısmı yapılacak. if bloğunda if parantezi içinde tanımlanan buf dizisinin kullanıldığını görüyorsunuz. if parantezinin birinci kısmında tanıtılan buf ismi yalnızca if deyiminin bloğunda kullanılabilecek.

Şimdi de aşağıdaki örneğe bakalım:

Yukarıdaki kodda ise if parantezi içinde tanımanan lock isimli nesne

türünden. Koşul ifadesi olarak ise gloabal alanda extern bildirimi yapılmış olan bool türden shared_flag isimli değişken kullanılmış. if parantezi içinde tanımlanan lock ismi yalnızca if deyiminin bloğu içinde bilinecek.

C++03’de de if parantezi içinde farklı bir sentaks yapısı ile ilk değer verilerek bir değişken bildirimi yapılabiliyor ve bildirilen değişken if deyiminin koşul ifadesinde doğrudan lojik yorumlamaya tabi tutulabiliyordu. Aşağıdaki örneğe bakalım:

func işlevi içinde yer alan if deyimi parantezi içinde, dynamic_cast işlecinin ürettiği değer ile başlatılarak tanımlanan Der * türünden pDer isimli gösterici değişken lojik olarak yorumlanıyor. dynamic_cast işleci aşağı doğru dönüşüm (down casting) işleminde başarısız olursa üretilen nullptr değeri hem pDer‘e ilk değerini verecek hem de lojik yanlış olarak yorumlanacak. if parantezi içinde tanımlanan pDer ismi yalnızca bu if deyiminde kullanılabilir. C++17’de geçmişten gelen bu sentaks özelliği ilk değer vermeli if deyimi ile birleştirilebiliyor. Örneğe bakalım:

Kodumuzda if parantezinin birinci kısmında int türden isimli bir değişken tanımlanmış. if parantezinin ikinci kısmında tanımlanmış count isimli değişken de ReadBytesWithSignal işlevine yapılan çağrının geri dönüş değeri ile hayata başlatılmış. Çağrılan işleve parantezin birinci kısmında tanımlanan s değişkeninin adresinin argüman olarak gönderildiğini görüyorsunuz. count değişkenine verilen ilk değer 0 değilse programın akışı if deyiminin doğru kısmına girecek. if parantezinin birinci kısmında tanımlanan s isminin hem if deyiminin ikinci kısmında hem de if deyiminin bloğu içinde kullanılabildiğini görüyorsunuz. Koşul ifadesinde tanımlanan count ismi de yalnızca if deyiminin bloğunda bilinecek. Bir başka örnek:

Bu kez ilk değer vermeli if deyimi parantezinin birinci kısmında auto belirteci kullanılarak

türünden bir nesne tanımlanıyor. if parantezinin ikinci kısmında çağrılan std::any_of şablon işlevi “true” değer döndürürse programın akışı if deyiminin doğru kısmına girecek. keywords ismi yalnızca bu if deyiminin kapsamında bilinecek.

Aşağıdaki örnek biraz daha ilginç:

Kodda tanımlanan foo işlevinin içinde yer alan her iki if deyiminin parantezlerinin birinci kısmında da status_code türünden c isimli değişkenler tanımlanmış. Bu isimler farklı bilinirlik alanlarında olduğundan aynı ismin birden fazla varlığa verilmesi dilin kurallarını çiğnemiyor.

Necati Ergin

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

Bunlar da ilginizi çekebilir

ilk değer vermeli if deyimi (if statement with initializer)” için bir yorum

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Kod Eklemek İçin Okuyun