C++17 Göze Çarpanlar

c17

#1

Yalın static_assert

Derleme zamanında assertion (sağlama) yapılmasını sağlayan static_assert C++11 ile gelen bir özellikti. Fakat mesaj olmadan kullanılamıyordu. C++17 ile beraber bu eksiklikte giderilmiş oldu.

    constexpr  int params = 2;
    static_assert(params == 3, "not enough parameters");
    static_assert(params == 3);

//error: static_assert failed "not enough parameters"
//error: static_assert failed

İfade değerlendirme sırasındaki yenilik

Ifadelerin değerlendirme sırasında bazı garantiler verildi. Fonksiyon çağrı zincirleri konusunda C++11 standartlarında herhangi bir sıralama garantisi standartlarda belirtilmemişti. Örneğin The C++ Programming Language, 4th edition, Stroustrup kitabında bu duruma örnek olarak aşağıdaki kod bloğunu vermiştir.

void func()
{
    std::string s = "but I have heard it works even if you don't believe in it" ;
    s.replace(0, 4, "" ).replace( s.find( "even" ), 4, "only" )
        .replace( s.find( " don't" ), 6, "" );

    assert( s == "I have heard it works only if you believe in it" ) ;
}

Fakat fonksiyon parametrelerinin değerlendirme sırası konusunda yine bir garanti yoktur.

func ( f(), g() );

gibi fir fonksiyon çağrısında f() fonskyion çağrısının g() fonksiyonun önce çağrılmasının herhangi bir garantisi yoktur. Fakat herhangi bir parametre tam olarak işlenmeden bir diğerine geçmemek standartlarda garanti altına alınmıştır.

Üstteki örneğe benzer şekilde,

std::cout << f() << g() << h() ;

f, g, h fonksiyonlarının sırasıyla çalışması şeklinde bir garanti verilmemişti C++17 ile beraber bu sıra da garanti altına alınmış oldu.

Guaranteed Copy Elision

C++11 ile beraber gelen move semantiği ile ciddi oranda performans kazanımı elde edebiliriz. Fakat bu durum herhangi bir standart altında değildi. Bazı derleyiciler sadece bu konuda destek veriyordu, örneğin bir fonksiyon içerisinde return edilen yerel değişken kopyalama ile değilde move edilerek değişkene atanırdı.

C++17 ile sadece return edilen değerlerin move edilmesi garanti altına alınmış oldu. Bu konuda C++20 ile beraber genişletilmesini bekliyorum açıkçası.

Structured Binding

Evet C++ gitgide pythona benzemeye başladı sentaks olarak :slight_smile: Birden fazla return değeri elde edildiği zamanlarda bu değerleri std::tie ile almak yerine artık daha şık bir şekilde almanın bir yoludur.

Örneğin,

    std::map<int, std::string> students;
    std::map<int, std::string>::iterator iter;
    bool is_inserted;
    std::tie(iter, is_inserted) = students.insert(std::pair<int, std::string>(24, "Ahmet"));

    if (is_inserted)
        std::cout << "Student " << iter->second << " saved succesfully\n";

Insert fonksiyonunun overloadlarından bir tanesi geri dönüş değeri olarak bir pair nesnesi dönmektedir. Bu nesnenin bir objesi eklenmeye çalışılan nesnenin başarılı bir şekilde enlenip eklenmediğini diğeri ise bu objeyi gösteren bir iteratördür. C++17 ile üstteki kod bloğunun ne kadar sadeleştiğine bakalım,

    std::map<int, std::string> students;

    const auto &[iter, is_inserted] = students.insert(std::pair<int, std::string>(24, "Ahmet"));

    if (is_inserted)
        std::cout << "Student " << iter->second << " saved succesfully\n";

Bu özellik yine aynı şekilde kullanıcı tanımlı yapıların (user-defıned types) kullanıldığı geri dönüş değerlerinde de benzer şekilde kullanılabilir.

if ve switch Blokları İçerisinde Başlangıç Değeri Atama

Dili kullanımını kolaylaştıran sentaks değişikliklerinden biri. Aşağıdaki koda bakalım;

    std::map<int, std::string> students;

    students.insert(std::pair<int, std::string>(24, "Ahmet"));


    auto it = students.find(24);

    if (it != std::end(students)) {
        cout << "found" << endl;
    }

C++17 ile sadeleşerek ve bence daha şık bir hale gelerek

    std::map<int, std::string> students;

    students.insert(std::pair<int, std::string>(24, "Ahmet"));
    

    if (auto it = students.find(24); it != std::end(students)) {
        cout << "found" << endl;
    }

burdaki it değişkeni if ve else blokları sonlanana kadar hayatta kalır. Benzer şekilde switch deyimi için de geçerlidir.

Inline Değişkenler
C++17 den önce fonksiyonları inline olarak tanımlayabilirdik. Şimdi ise sınıf üyelerini de inline olarak tanımlama şansına sahibiz.

struct Server
{
    inline static const int  port = 1514;
};

Nested Namespaces

Önceden bir namespace tanımlaman istediğimizde her defasında namespace anahtar sözcüğünü kullanmak gerekiyordu. Şimdi ise sadece çözünürlük operatörünü kullanmak yeterli.

    namespace Network {
        namespace Tcp {
            namespace Smtp {
                
                class Headers 
                {

                };
                
                class Body 
                {

                };
            } 
        } 
    } 

C++17 ile beraber bu görüntü yine şık bir hale geldi;

    namespace Network::Tcp::Smtp 
    {
        class Headers 
        {

        };
        
        class Body 
        {

        };
    }