25 Mayıs 2021 Salı

destroying operator delete - C++20 İle Geliyor

Giriş
Açıklaması şöyle
Prior to C++20, objects' destructors were always called prior to calling their operator delete. With destroying operator delete in C++20, operator delete can instead call the destructor itself.
Örnek
Elimizde şöyle bir kod olsun
#include <iostream>
#include <new>

struct Foo {
    ~Foo() {
        std::cout << "In Foo::~Foo()\n";
    }

    void operator delete(void *p) {
        std::cout << "In Foo::operator delete(void *)\n";
        ::operator delete(p);
    }
};

struct Bar {
    ~Bar() {
        std::cout << "In Bar::~Bar()\n";
    }

    void operator delete(Bar *p, std::destroying_delete_t) {
        std::cout << "In Bar::operator delete(Bar *, std::destroying_delete_t)\n";
        p->~Bar();
        ::operator delete(p);
    }
};

int main() {
    delete new Foo;
    delete new Bar;
}
Çıktı olarak şunu alırız
In Foo::~Foo()
In Foo::operator delete(void *)
In Bar::operator delete(Bar *, std::destroying_delete_t)
In Bar::~Bar()

30 Nisan 2021 Cuma

std::in_place

Örnek
Şöyle yaparız
struct Things
{
    Things(const char* msg1, const char* msg2) : one(msg1), two(msg2) {}
    Unmovable one;
    Unmovable two;
};

int main()
{
    std::optional<Things>{std::in_place, "jadda", "neida"};
}

28 Nisan 2021 Çarşamba

std::endian

Örnek
Şöyle yaparız
void convertBigToLittleEndianIfNecessary(uint32_t& code) {
  if constexpr (std::endian::native == std::endian::little) {
  code = ((code & 0xFF000000) >> 24) |
         ((code & 0x00FF0000) >> 8)  |
         ((code & 0x0000FF00) >> 8)  |
         ((code & 0x000000FF) >> 24);
    }
}

21 Nisan 2021 Çarşamba

std::bit_width

Giriş
Açıklaması şöyle
std::bit_width finds minimum bits required to represent an integral number x as 1+floor(log(x))

22 Mart 2021 Pazartesi

POSIX stat metodu

Giriş
stat(), lstat(), fstat(), atexit() gibi metodlar libc_nonshared.a kütühanesinde tanımlı. Bu static kütüphane de gidip bir .so dinamil kütüphanesini çağırıyor.

11 Mart 2021 Perşembe

std::map [] operator

Giriş
Bu operator eğer aranan key yoksa default constructor kullanarak bir value ile doldurur. Açıklaması şöyle
T& operator[](const key_type& x);
1 Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.
Eğer value tipinin default constructor metodu yoksa hata alırız. Aşağıdaki kod derlenmez!
std::map< int, std::reference_wrapper< foo > > my_map;
foo a;
my_map[ 0 ] = std::ref( a );
Örnek - primitive tip
Şöyle yaparız
std::map<std::string,std::size_t> counters;
//...
counters[key]++;
Açıklaması şöyle
++counters[key]; is completely valid. std::map::operator[] inserts a value-initialized element if the key does not exist in the map. This is the idiomatic way of doing what you explained.

std::merge metodu

Giriş
merge ile sıralı olan iki dizi yeni bir dizi olarak birleştirilir. Yani merge sort (birleştirmeli sıralama) yapılır. std::merge yerine std::map kendi merge() metodunu sunuyor.

Örnek
a ve b veriyapıları c içinde birleştirmek için şöyle yaparız
decltype(a) c;
std::merge(a.begin(), a.end(),
           b.begin(), b.end(),
           std::back_inserter(c));
Örnek
Klasik array kullanılacaksa nihai dizinin yeterince büyük olması gerekir. Örnekte nihai dizi için 100 elemanlık yer ayrılıyor.
int A[50];
int B[50];
int C[100];

std::merge(std::begin(A), std::end(A), std::begin(B), std::end(B), std::begin(C));
Örnek
std::array kullanılsa da nihai dizi için 100 elemanlık yer ayrılıyor.
std::array<int, 50> A;
std::array<int, 50> B;
std::array<int, 100> C;

std::merge(A.begin(), A.end(), B.begin(), B.end(), C.begin());
Örnek
Java'da pseudo kod için buraya bakılabilir. C ile verilen bir örnek
void merge(int **a, int **b, int **c)
{
    while(*a || *b)
        *c++ = !*a || *b && **b < **a
            ? *b++
            : *a++;
}
merge - yanlış kullanım
Eğer kullanılan veri yapısı elemanları sıralı saklamıyorsa std::merge yapmanın bir anlamı yoktur. Elimizde 3 tane unordered_map olsun.
unordered_map<int,int> map1 ,map2, map3;
map1 ve map2'yi map3'te şöyle birleştirebiliriz.
map<int,int>::iterator it   = map3.begin();
std::merge(map1.begin(),map1.end(),map2.begin(),map2.end(),inserter(map3,it));
Ancak unordered_map zaten sırasız olduğu için sonuç anlamsızdır.