25 Ağustos 2016 Perşembe

__cdecl Calling Convention

__cdecl - C Dili
Şöyledir. Metod çağrısı yapan stack'i eski haline getirir.
push b;
push a;
call fnAdd;
add esp, 8    # restore stack.
Bu calling convention'da value olarak geçilen bir sınıf, metod'dan çıkarken yok edilir. Şöyle bir kod olsun.
#include <stdio.h>

struct Foo {
    Foo() { puts("created"); }
    Foo(const Foo&) { puts("copied"); }
    ~Foo() { puts("destroyed"); }
};

void __cdecl x(Foo f) { }

int main() {
    Foo f;
    x(f);
    return 0;
}
x'in assemly koduna bakarsak Foo f parametresi için destructor çağrısı yapıldığını görebiliriz.
x:
    mov     qword ptr [rsp+8],rcx
    sub     rsp,28h
    mov     rcx,qword ptr [rsp+30h]
    call    module!Foo::~Foo (00000001`400027e0)
    add     rsp,28h
    ret
__stdcall - Windows 
Şöyledir. Metod kendisi stack'i eski haline getirir.
push b;
push a;
call fnAdd;    # stack is restored by the callee. with ret 8
Bu Windows'ta kullanılan calling convention. Windows'ta DLL metodları şöyle tanımlanır.
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif

TESTAPI int __stdcall myadd(int a, int b);
Bazı Win32 metodlarının imzası şöyledir.
WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...);
Burada APIENTRY aslında __stdcall için macro'dur. Bazen de WINAPI __stdcall için macro olarak kullanılır.





18 Ağustos 2016 Perşembe

filebuf Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <fstream>
Constructor
Şöyle yaparız.
std::filebuf tempfilebuf;
close metodu
Şöyle yaparız.
tempfilebuf.close();
open metodu
Şöyle yaparız.
tempfilebuf.open("/tmp/extmpfile", std::ios::binary|std::ios::out);
Daha sonra bu sınıf ostream ile kullanılabilir. ostream yok olunca dosya kapatılmaz. Şöyle yaparız.
{
  std::ostream tempfile(&tempfilebuf);
  ...
}


15 Ağustos 2016 Pazartesi

dynamic_cast

Giriş
Açıklaması şöyle
dynamic_cast can only be used with pointers and references to classes (or with void*). Its purpose is to ensure that the result of the type conversion points to a valid complete object of the destination pointer type.
This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base), in the same way as allowed as an implicit conversion.
But dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type.
Upcast
Özel bir durum yok.

Downcast

1. Downcast yaparken dynamic_cast ve static_cast arasında fark vardır. static_cast herhangi bir kontrol uygulamaz. dynamic_cast ise işlemin başarılı olup olmadığını kontrol eder.
Yani dynamic_cast derleme esnasında değil de çalışma esnasında kontrol için kullanılır.
A* p = new B(); 
B* pB = static_cast<B*>(p); // Checks if B is related to A in an inheritance 
     // ^^^^^^^^^^^^^^^^^^^    hierarchy. Fails to compile if not.
Şöyle yaparız.
A* pA = new B();
B* pB = dynamic_cast<B*>(pA); // Checks if pA actually points to an instance of B
     // ^^^^^^^^^^^^^^^^^^^^     at runtime, and returns nullptr if not
if(pB) {
  // do stuff with B
}
dynamic_cast kullanabilmek için RTTI seçeneği ile derlemek gerekir. dynamic_cast deference edilen bellek alanı geçersiz ise undefined çalışır.

Visual Studio ile RTT desteğini kapatmak için projeye sağ tıklayıp Properties / C/C++ / Language / Enable Run-Time Type Information seçeneği değiştirilmeli.

2. Multiple inheritance olduğu durumda (Base, Derived1,Derived2 olsun) Derived1'i Derived2'ye döndürmek için kullanılır.

Downcast Yaparken Ata Sınıf Polymorphic Olmalıdır
Ata sınıfın en bir tane virtual metodu olmalıdır. Şöyle yapabiliriz.
class Base
{
   virtual ~Base() {}
};

Downcast Yaparken Reference Olarak Kullanmak
Eğer reference döndürülecekse ve dönüşüm başaralı olmazsa dynamic_cast bad_cast exception atar.

Downcast Yaparken Pointer Olarak Kullanmak
Eğer pointer döndürülecekse ve dönüşüm başaralı olmazsa dynamic_cast NULL değeri döner. Şöyle yaparız.
Base *base = ...;
Derived *derived = dynamic_cast<Derived*>(base);
if(derived) {  // do stuff
}

8 Ağustos 2016 Pazartesi

std::bind1st

Giriş
Lambda çıktıktan sonra bu algoritmalara gerek kalmadı. Bu metod binary bir function ile çalışır.
Şöyle yaparız. greater metodunun ilk parametresi 10 olacaktır. 10 > x true ise aslında 10'dan küçük elemanları sayarız
vector<int> v1; 
// Count the number of integers < 10 in the vector 
count_if( v1.begin(), v1.end(), bind1st(greater<int>(), 10 ) ); 


3 Ağustos 2016 Çarşamba

std::mem_fn

Giriş
Şu satırı dahil ederiz.
#include <functional>
std::mem_fn işlev olarak std::bind ile hemen hemen aynı şey.

Alana Erişmek
Şöyle yaparız.
#include <algorithm>
#include <functional>
#include <iterator>    
#include <iostream>

struct Obj { int a, b, c; };

int main() {

  Obj o[3] = {{1, 2, 3}, {11, 22, 33},{111, 222, 333}};

  int a[3];

  std::transform(std::begin(o), std::end(o),
                 std::begin(a),
                 std::mem_fn(&Obj::a));

  for (auto e : a)
    std::cout << e << ' ';

  std::cout << std::endl;
};
Çıktı olarak şunu alırız.
1 11 111