30 Aralık 2015 Çarşamba

std::tuple_cat

Giriş
Şu satırı dahil ederiz
#include <tuple>
Bir veya daha fazla tuple'ı birleştirerek yeni bir tuple oluşturur. Genelde std::make_tuple ile kullanılır. 

Örnek
Çok basitleştirilimiş bu örnekte önce bir pair yaratılıyor. pair make_tuple() ile tuple haline getiriyor ve diğer tuple nesneleri ile birleştiriliyor.
return std::tuple_cat(std::make_tuple(std::make_pair(...,...)),...);
Örnek
Şöyle yaparız. Bu örnek çok daha karışık.  std::make_index_sequence ile n tane tekrar eden elemanlı yapı yaratılıyor ve bu bir tuple'a çevriliyor. Daha sonra tüm tuple nesneleri std::tuple_cat ile birleştirilip yeni bir tuple yaratılıyor.
template <typename T,size_t reps>
struct repeated_type {
    using type = T;
    static const size_t N = reps;
};

template <typename T,std::size_t...n>
auto n_tuple_impl(std::index_sequence<n...>){ 
    return std::make_tuple( (n,T{})...); 
}

template <typename repT>
using n_tuple_single = decltype( n_tuple_impl<typename repT::type>(
std::make_index_sequence<repT::N>() )
);

template <typename...repT>
using n_tuple = decltype( std::tuple_cat( ( n_tuple_single<repT>() )... ) );

int main() {
    using two_ints = repeated_type<int,2>;
    using three_doubles = repeated_type<double,3>;
    using my_tuple = n_tuple<two_ints,three_doubles>;
    static_assert(std::is_same<std::tuple<int,int,double,double,double>,my_tuple>::value);
}

29 Aralık 2015 Salı

Exposition

Giriş
Tam olarak ne işe yaradığını anlamadım ancak bazı alanlar exposition only olarak işaretli.
std::error_code::val_
std::wstring_convert::byte_err_string
std::array::elems
std::move_iterator::current
std::reverse_iterator::current
std::ostream_iterator::delim
// And a lot of others


27 Aralık 2015 Pazar

C++ Smart Pointer

Observer Pointer
Bu sınıfın C++14 ile standarda girmesi bekleniyor. Sınıfın sadece marker interface gibi kullanılması düşünülüyor.


25 Aralık 2015 Cuma

Strict Weak Ordering

Strict Weak Ordering Nedir?
Strictk Weak Ordering key değerlerinin karşılaştırılması için "<" işlemini kullanması anlamına gelir.

Hangi Veri Yapıları Kullanır?
std::map ve std::set elemanların eşitliği için bu yöntemi kullanır. Tüm veri yapıları için Compare kavramına bakmak gerekir.

Hangi Algoritmalar Kullanır?
std::sort sıralama için bu yöntemi kullanır. Tüm veri yapıları için Compare kavramına bakmak gerekir.

Java'da Nasıldır?
Java'da elemanların eşitliğ için nesnenin equals() metodu kullanılır.

Strict Weak Ordering Tablosu
Bir tablo haline dökersek şöyle gösteririz
For all a, comp(a,a)==false
If comp(a,b)==true then comp(b,a)==false
if comp(a,b)==true and comp(b,c)==true then comp(a,c)==true

veya şöyle gösteririz
X    a;
X    b;

Condition:                  Test:     Result
a is equivalent to b:       a < b     false
a is equivalent to b        b < a     false

a is less than b            a < b     true
a is less than b            b < a     false

b is less than a            a < b     false
b is less than a            b < a     true
En Çok Yapılan Hata - İki Nesne Eşitse
Kural şudur. Yani kısaca iki nesne eşitse false dönmek gerekir.
they are equivalent if !comp(a,b) && !comp(b,a)
Aynı kuralın bir başka şekilde ifade edilişi de şöyle
In imprecise terms, two objects a and b are considered equivalent (not unique) if neither compares less than the other: !comp(a, b) && !comp(b, a)
Şöyle de ifade edilebilir.
Two objects x and y are equivalent if both f(x, y) and f(y, x) are false. Note that an object is always (by the irreflexivity invariant) equivalent to itself. 
Örnek - Yanlış Kullanım
Şu kod yanlış. Çünkü comp(a,a) false döneceğine true dönüyor.
bool comp (string s1, string s2) {
  if (s1.size() < s2.size())
    return false;
  else
    return true;
}

sort ile comparator sınıfı kullanmak
Örneğin yeni bir b key değerini eklerken mevcut a key değeri ile karşılaştırma yapılır. a < b ifadesinin false olması a'nın b'den küçük olmasını garanti etmek için yeterli değildir. Aynı zamanda b < a ifadesinin de false olması gerekir. Eğer bu ikinci karşılaştırma da false dönerse a = b sonucu çıkarılır ve map insert() metodu yeni girdiyi kabul etmez.

Yani < karşılaştırması map'e yeni bir değer eklerken biraz daha fazla karşılaştırma yapılmasına sebep olur.

< Nasıl Kodlanır
Normalde kalıtım kullanmaya pek ihtiyaç olmaz. Ancak kalıtım kullanan bir örnek göstermek istedim. Şöyle yaparız.
class Base
{
public:
  virtual bool operator<(Base & other) const
  {
    std::cout << "Base";
  }
};

class Derived : public Base
{
public:
  bool operator<(Base & other) const override
  {
    std::cout << "Derived";
  }
};

int main()
{
  Derived a;
  Derived b;
  a < b; //prints "Derived"
  a.Base::operator <(b); //prints "Base"
}




18 Aralık 2015 Cuma

std::set_terminate

Eğer yakalanmamış exception'lar varsa ve de temizlik yaparak uygulamadan çıkmak istiyorsak aşağıdaki gibi bir yöntem izleyebiliriz.
terminate_handler old_terminate_handler = nullptr;

void new_terminate_handler() {
    std::cerr << "terminate due to error" << std::endl;
    if( old_terminate_handler != nullptr ) {
        old_terminate_handler();
    } else {
        exit (-1);
    }
}

int main(int, char**) {
    old_terminate_handler = get_terminate();
    set_terminate(new_terminate_handler);
}
std::set_terminate() metodu ile yakalanmamış exceptionları kendimiz yakalar ve std::exit() metodunu çağırırsak, programımız düzgün bir şekilde çıkar. Hem static destructorlar işletilir, hem de std::atexit() metodu ile atanan metotlar çağırılır ve de en önemlisi I/O streamleri boşaltılır (flush) .



7 Aralık 2015 Pazartesi

Callable

Callable Nedir
C++17 ile gelen bir kavram. Açıklaması şöyle
Callable applies only to object types, and include everything from pointer-to-members to types with an overloaded operator() to types with an implicit conversion to function pointers to function pointers themselves.
Yani basitçe "operator ()" metodunu sağlayan sınıf, struct gibi düşünülebilir. Bir function Callable değildir !