std::bind function adaptor (std::bind fonksiyon uyumlandırıcısı) - 1


C++11 ile standart kütüphaneye eklenen bind fonksiyon şablonu genel amaçlı bir fonksiyon (function adapter) uyumlandırıcısıdır.  Bir fonksiyonun istenildiği sekilde çağrılma kalıbına uygun bir obje oluşturarak saklamamızı sağlayan şablon sınıfıdır. Aşağıda objenin oluşturulma biçimini daha net görebiliriz.
std::bind, standart kütüphanede önceden beri var olan, kullanımı daha zahmetli ve biraz da sorunlu olan ptr_fun, mem_fun, mem_fun_ref, bind1st ve bind2nd fonksiyon uyumlandırıcılarının yerine gelmiştir. Ve bu uyumlandırıcılar standartlar tarafından deprecated kabul edilmiştir. std::bind'ın kökeni boost::bind'a dayanmaktadır. Lambda'lar olmadan önce önemli bir eksikliği gidermesi öngörülürken lambdalarla aynı zamanda standart hale gelmiş olması biraz kıyıda/köşede kalmasına sebep olmuştur. Kullanım kolaylığından dolayı daha çok lambda'lar tercih edilmektedir. std::bind bizi doğrudan function pointer karmaşasında kurtarmakta ve std::placeholder ile parametrelerini manipüle etmemize olanak sağlamaktadır. Şimdi sırayla kullanım senaryolarına ve bize sağladığı faydaları/kolaylıkları inceleyelim.

std::bind | function pointer olarak kullanımı

std::bind fonksiyon pointer tanımlama karmaşasına girmeden kolaylıkla bir fonksiyonu sarmalamamıza olanak sağlamaktadır.

Yukarıdaki örnekte isGreater fonksiyonu gönderilecek parametreleri ile beraber sarmalanmış ve fonksiyon pointer biçiminde çağrılabilmiştir.

std::bind | partial function olarak kullanımı

Parçalı fonksiyon biçiminde kullanımdan kasıt fonksiyon argumanlarından bazılarının sabitlenmesi anlamına gelmektedir.
Yukarıdaki örnekte isGreater fonksiyonunun birinci parametresi placeholders ile dış dünya ile ilişkilendirilmiş ikinci parametre ise sabit bir değere ayarlanmıştır.

placeholders değişkenleri

std::bind'a geçilen bağlanmış placeholders::x 'lar bize 'bind' edilen fonksiyona, çağrılma esnasında çeşitli parametrelerle çağırma esnekliği sağlamaktadır. Bu sayede fonksiyonun sarmalanması sırasında tüm parametrelerin girilmesine gerek kalmamaktadır. Bir placeholder değişkenin ismi, bağlanacak argüman listesinde hangi sırada kullanılmış ise, fonksiyon nesnesi ile yapılan çağrıda bu ismin işaret ettiği x numaralı parametre, sarmalanan fonksiyonun bu sıradaki parametresine argüman olarak geçileceği anlamına gelir. Daha açıklayıcı olması için:
auto f = std::bind(func, _3, _2, _1);
f(2,4,6) 
biçimindeki örneği inceleyelim:
  • placeholders::_1 ismi bind‘a geçilen bağlanacak argümanlar listesinde üçüncü sırada kullanılmış ise oluşturulan fonksiyon nesnesi ile yapılan çağrıda kullanılan birinci argüman sarmalanan fonksiyonun üçüncü parametresine aktarılır.
  • placeholders::_2 ismi bind‘a geçilen bağlanacak argümanlar listesinde ikinci sırada kullanılmış ise oluşturulan fonksiyon nesnesi ile yapılan çağrıda kullanılan ikinci argüman sarmalanan fonksiyonun ikinci parametresine aktarılır.
  • placeholders::_3 ismi bind‘a geçilen bağlanacak argümanlar listesinde birinci sırada kullanılmış ise oluşturulan fonksiyon nesnesi ile yapılan çağrıda kullanılan üçüncü argüman sarmalanan fonksiyonun birinci parametresine aktarılır.
Şimdi yukarıdaki bilgilere göre f(2,4,6) nasıl çağrılacak dersek;
tabiki func(6,4,2) şeklinde olacaktır.

std::bind | value  & reference semantics olarak kullanımı

std::bind value semantics çalıştığından dolayı dışarıdan geçilen parametreleri value type olarak  kullanır. Yukarıda örneğin dikkat çektiği nokta fonksiyon ne kadar referans yoluyla parametre alıyor olsa da std::bind bu ival1 ve ival2 değişkenlerini referans yoluyla aktarmadığını ve program çalıştırılırsa ekrana 7, 9 sayılarının yazılacağı ilişkindir. Referans yoluyla aktarım yapabilmek için yapılması gereken aşağıdaki örnekte açıklanmıştır.
std::bind'ın referans semantics çalışmasını istiyorsak std::ref'i kullanmamız ve bu sayede ival1 ve ival2 değişkenlerini referans yoluyla aktarılacağı ve program çalıştırılırsa ekrana 49, 81 sayılarının yazıldığı görülecektir.

Note:

  • place_holders nesneleri bağlanacak argümanlar listesinde birden fazla yerde de kullanılabilir:

std::bind(squareof, std::placeholder::_1, std::placeholder::_1)