C++ 17

C++ 11 ile birlikte Modern C++ olarak adlandırılan C++ diline C++ 17 ile eklenen yeni özelliklerle ilgili bilgiler örneklerle yer alıyor.

C++ 17 nedir?

C++ 17, C++ 11 ile birlikte Modern C++ olarak adlandırılan C++ diline yeni özelliklerin eklendiği bir sürümdür.

C veya C++ ile yazılım geliştirirken bazı işlemler sıklıkla tekrar edilir.

Dosya işlemlerinin yapıldığı bir uygulamada dosyanın var olup olmadığı, dosyanın açılıp açılmadığı gibi işlemler örnek olarak verilebilir.

Bu işlemleri sürekli yapmak yerine kendi fonksiyonlarımızı yazabilir veya hazır kütüphane kullanabiliriz.

Ancak belirli bir standardı olmayan kodlar büyük çaplı projelerde yazılımcılar arasında sorun olacaktır.

Dosya işlemleri için A yazılımcısı kendi fonksiyonunu, B yazılımcısı bir kütüphaneyi kullanabilir.

C++ bu ve bunun gibi işlemler için C++ 17 ile birlikte filesystem adında bir kütüphaneyi C++ standardına getirdi.

Benzer şekilde C++ birçok kütüphane ile kullanılan özellikleri C++ 17 ile birlikte standart haline getirdi.

C++ 17 ile gelen yeni özelliklere bakmadan önce C++ 14 yazıma bakmanızda fayda var.

Nasıl çalıştırılır?

C++ 17 ile gelen özellikler bir çok derleyici (GCC 6, Clang 4, MSVC 19.14) tarafından kullanıma hazır hale getirilmiştir.

C++ 17 özelliklerinin kullanmak için derleyici parametresine (flags) -std=c++1z veya -std=c++17 eklemek yeterli olacaktır.

1. Template argument deduction

C++ 17 ile birlikte artık Template sınıfları için veri türünü belirlemeden de kullanabilir hale geldi.

#include<iostream>
#include<vector>

using namespace std;

int main(){

    // C++ 17 öncesi
    vector<int> sayilar {5, 9, 77, 37, 133};

    cout << sayilar.size() << endl;

    // C++ 17
    vector sayilar1 {5, 9, 77, 37, 133};

    cout << sayilar1.size() << endl;

    return 0;
}

Bana göre bu özellik kod yazımını daha esnek hale getirse de kod okunurluğunu azaltmış gibi görünüyor.

2. auto

C++ 11 ile birlikte gelen auto anahtar kelimesinin kapsamı genişletildi.

#include<iostream>

using namespace std;

// C++ 17 öncesi
template <typename Type, Type value> void f() { cout << value << endl; }

// C++ 17
template <auto value> void f() { cout << value << endl; }

int main(){

    // C++ 17 Öncesi
    f<int, 10>();

    // C++ 17
    f<10>();

    return 0;
}

Bu özellikte kod okunurluğunu azalmakta ancak sınıf ve fonksiyon kullanımında oldukça faydalı görünüyor.

Ayrıca auto anahtar kelimesi uniform initialization ile kullanımında ortaya çıkan sorun ortadan kaldırıldı.

3. Folding expressions

C++ 11 ile birlikte gelen Variadic Template özelliği Template ile hazırlanmış sınıf veya fonksiyonlara sınırsız parametre aktarma özelliği kattı.

Variadic Template özelliğin kullanımı C++ 17 ile birlikte gelen folding expression ile daha esnek hale geldi.

#include<iostream>

using namespace std;

// C++ 17 öncesi
auto SumCpp11(){
    return 0;
}

template<typename T1, typename... T>
auto SumCpp11(T1 s, T... ts){
    return s + SumCpp11(ts...);
}

// C++ 17
template<typename ...Args>
auto sum(Args ...args) 
{ 
    return (args + ...); 
}

int main(){

    // C++ 17 Öncesi
    cout << SumCpp11(1, 2, 3, 4, 5) << endl;

    // C++ 17
    cout << sum(1, 2, 3, 4, 5) << endl;

    return 0;
}

4. constexpr

C++ 11 ile birlikte gelen C++ 14 ile özelliği genişleyen constexpr anahtar kelimesi temel olarak derleme zamanında işlem yapan bir terimdir.

C++ 17 ile birlikte constexpr anahtar kelimesinin kullanımı daha da genişletildi.

#include<iostream>

using namespace std;

// C++ 17 öncesi
template<int  N>
constexpr int fibonacciEski() {return fibonacciEski<N-1>() + fibonacciEski<N-2>(); }
template<>
constexpr int fibonacciEski<1>() { return 1; }
template<>
constexpr int fibonacciEski<0>() { return 0; }

// C++ 17
template<int N>
constexpr int fibonacci()
{
    if constexpr (N >= 2)
        return fibonacci<N-1>() + fibonacci<N-2>();
    else
        return N;
}

int main(){

    // constexpr lambda
    auto identity = [](int n) constexpr { return n; };
    cout << identity(123) << endl;

    // constexpr if
    cout << fibonacci<10>() << endl;

    return 0;
}

5. Lambda capture

C++ 11 ile birlikte gelen lambda fonksiyonları veya anonim fonksiyonlar temel olarak kod karmaşıklığını azalttı.

C++17 ile birlikte lambda kullanımı sırasında fonksiyon kapsamı dışındaki elemanlar erişim biçimi daha da genişletildi.

#include<iostream>

using namespace std;

struct MyObj {
  int value {123};
  auto getValueCopy() {
    return [*this] { return value; };
  }
  auto getValueRef() {
    return [this] { return value; };
  }
};

int main(){

    MyObj mo;
    auto valueCopy = mo.getValueCopy();
    auto valueRef = mo.getValueRef();
    mo.value = 321;
    cout << valueCopy() << endl;  // 123
    cout << valueRef() << endl;  // 321

    return 0;
}

C++ 17 ile birlikte artık lambda fonksiyonları *this anahtar kelimesini referans olarak parametre alıyor.

6. Inline variables

C++ 17 ile birlikte artık sınıf içinde inline değişken tanımlama imkanı getirildi.

#include<iostream>

using namespace std;

// C++ 17 öncesi
struct MyClass
{
    static const int sValue;
};

inline int const MyClass::sValue = 777;

// C++ 17
struct MyClass1
{
    inline static const int sValue = 777;
};

int main(){

    cout << MyClass::sValue << endl;

    cout << MyClass1::sValue << endl;

    return 0;
}

7. Nested Namespace

C++ 17 ile birlikte kod karmaşıklığını indiren bir diğer özellik olan ise nested namespace özelliğidir.

#include<iostream>

using namespace std;

// C++ 17 öncesi
namespace A {
  namespace B {
    namespace C {
      int i;
    }
  }
}

// C++ 17
namespace A::B::C {
  int j;
}

int main(){

    return 0;
}

8. Structured bindings

C++ 17 ile gelen güzel bir özellik ise structured bindings özelliğidir.

Özellik Dizi, Pair, Tuple gibi birden fazla değer içeren elemanlardaki verileri kolayca başka değişkenlere aktarmayı sağlıyor.

#include<iostream>
#include<tuple>

using namespace std;

int main(){

    tuple<int, string, string> bilgiler(1, "Yusuf", "SEZER");

    // C++ 17 öncesi
    int bid = get<0>(bilgiler);
    string badi = get<1>(bilgiler);
    string bsoyadi = get<2>(bilgiler);
    //tie(bid, badi, bsoyadi) = bilgiler;
    cout << bid << " " << badi << " " << bsoyadi << endl;

    // C++ 17
    auto [id, adi, soyadi] = bilgiler;
    cout << id << " " << adi << " " << soyadi << endl;

    return 0;
}

Bu özelliğin tie özelliğinden farkı değişkenlerin önceden oluşturulmasına ihtiyaç duymamasıdır.

9. init-statements if ve switch

C++ 17 ile birlikte if ve switch ifadelerinin kullanımı genişletildi.

#include<iostream>

using namespace std;

int kare(int x) { return x * x;};

int main(){

    // C++ 17 öncesi
    int sonuc = kare(3);

    if(sonuc == 9)
        cout << "Dogru";
    else
        cout << "Yanlis";

    // C++ 17 öncesi
    if(int sonuc = kare(3); sonuc == 9)
        cout << "Dogru";
    else
        cout << "Yanlis";

    return 0;
}

Aslında gereksiz bir özellik gibi görünse de C++ STL gibi nesne döndüren sınıflarda kullanımı oldukça yararlıdır.

Ayrıca if ve switch içerisinde tanımlanan değişkenler if ve switch işlemi yapıldıktan sonra silineceğinden gereksiz bellek kullanımını azalacaktır.

10. UTF-8 Character Literals

C++ 11 ile birlikte gelen String Literals özelliğinde kullanılan ifadelerin kullanım alanı genişletildi.

#include<iostream>

using namespace std;

int main(){

    char a = u8'x';
    char b = u'x';
    char c = U'x';
    char d = L'x';

    cout << a << b << c << d << endl;

    return 0;
}

11. static_assert

C++ 11 ile birlikte gelen ve derleme zamanında değerleri test etmeye yarayan static_assert fonksiyonu artık mesaj yazmadan da kullanılabiliyor.

#include<iostream>
#include<cassert>

using namespace std;

int main(){

    // C++ 17 öncesi
    static_assert(sizeof(int) == 3, "Bir hata olustu.");

    // C++ 17
    static_assert(sizeof(int) == 3);

    return 0;
}

12. variant

Boost kütüphanesinde yer alan variant, optional, any özelliği C++17 ile dilin standartlarına eklendi.

#include<iostream>
#include<variant>

using namespace std;

int main(){

    variant<int, double> v{ 12 };
    get<int>(v); // == 12
    get<0>(v); // == 12
    v = 12.0;
    get<double>(v); // == 12.0
    get<1>(v); // == 12.0

    return 0;
}

optional özelliğinin kullanımı aşağıdaki gibidir.

#include<iostream>
#include<optional>

using namespace std;

optional<string> sonuc(bool x)
{
    return x ? "Doğru" : nullptr;
}

int main(){

    cout << sonuc(true).value() << endl;  // Doğru
    cout << sonuc(false).value_or("Yanlış") << endl;  // Yanlış
    //cout << sonuc(false).value() << endl;  // nullptr

    return 0;
}

13. Diğer

C++ 17 temel olarak C++ 11 ve C++ 14 ile gelen özelliklerde bulunan hataları düzeltmiş ve bazı özelliklerin daha esnek kullanımını sağlamıştır.

C++ 17 ile birlikte Boost gibi C++ kütüphanelerinde yer alan çeşitli özellikleri standart haline getirmiştir.

C++ Modern C++ ile birlikte artık Modern programlama dillerinden yer alan birçok özelliği dilin standardı olarak belirlemiştir.

Yeni güncellemeler ve dil hakkında detaylı bilgi için isocpp.org adresine bakabilirsiniz.

Hayırlı günler dilerim.

Yusuf SEZER

Yusuf SEZER

Computer Engineer who interested about web technologies, algorithms, artificial intelligence and embedded systems; constantly exploring new technologies.


Bunlara'da bakmalısın!