18 Mart 2016 Cuma

codecvt

Giriş
Şu satırı dahil ederiz.
#include <codecvt>
codecvt farklı encoding'ler arasında dönüşüm yapmak için kullanılır.

UTF-16 <-> UTF-8
UTF-32 <-> UTF-8
UTF-8 <-> UTF-16

için kullanılabilir.

consume header
Byte Order Mark (BOM) karakterini atlar. Şöyle yaparız. UTF-8 BOM karakteri 0xEF, 0XBB, 0xBF sayılarıdır.
std::ifstream file("UTF8.txt");
    file.imbue(std::locale(file.getloc(),
        new std::codecvt_utf8<char,0x10ffff,std::consume_header>));


17 Mart 2016 Perşembe

InputIterator

Giriş
Açıklaması şöyle
An InputIterator is an Iterator that can read from the pointed-to element. InputIterators only guarantee validity for single pass algorithms: once an InputIterator i has been incremented, all copies of its previous value may be invalidated.
STL içindeki InputIterator ve OutputIterator kullanan algoritmalar şunlar.

Okuma İşlemi
File, stream, network gibi bir yerden veri okumak i çin kullanılır.

Okuma işlemi sadece bir kere yapılabilir. Iterator ilerletilmese bile ikinci okuma işleminde aynı değeri okumayız.
"Input iterators can read elements only once"

Diğer İşlemler
Bu iterator dereference, equality, pre-increment ve post-increment işlemlerini destekler.

Input iterators can read elements in a sequence. They must provide the following operators - equality (==), inequality (!=), dereference (*), postfix & prefix increment (++) and the arrow operator (->). Input iterators may be used only sequentially. We are guaranteed that *it++ is valid, but incrementing an input iterator may invalidate all other iterators on that stream. As a result there is no guarantee that we can save the state of an input iterator and examine an element through that saved iterator



std::atomic_thread_fence

memory_order_release - Sıralama İçin Kullanılır
Şöyle yapılır. std::atomic_thread_fence metoduna memory_order_release parametresi geçildiği için fence çağrısının üstündeki tüm atomic işlemler çağrının altındaki atomic işlemler'den önce yapılmak zorundadır. Yani önce x işlemi yapılmalıdır daha sonra y işlemi yapılır.

std::atomic<bool> x,y;
std::atomic<int> z;
void write_x_then_y()
{
 x.store(true,std::memory_order_relaxed);
 std::atomic_thread_fence(std::memory_order_release);
 y.store(true,std::memory_order_relaxed);
}
memory_order_acquire
Şöyle yapılır.
std::atomic<int> flag { 0 };

bool poll1() {
    return (flag.load(std::memory_order_acquire) == 1);
}
memory_order_relaxed
Şöyle yapılır.
std::atomic<int> flag { 0 };


bool poll2() {
    int snapshot = flag.load(std::memory_order_relaxed);
    if (snapshot == 1) {
        std::atomic_thread_fence(std::memory_order_acquire);
        return true;
    }
    return false;
}



13 Mart 2016 Pazar

std::begin ve std::end

Giriş
std::begin ve std::end C++11 ile geldiler. Şu satırı dahil ederiz.
#include <iterator>
std::begin
Şöyle kullanırız.
int myint[] ={1,2,3,4,5,6,7,8,9};
std::find(begin(myint),end(myint),9);
Bu metodun container ve array için özelleşmiş halleri var. container için şöyledir.
template< class C > 
auto begin( C& c ) -> decltype(c.begin());
Array için C++11 ile şöyledir.
template <typename T, std::size_t N>
T* begin(T (&ar)[N]) {
  return ar;
}
C++14 ile metod imzası değişmiştir.
template< class T, std::size_t N >
constexpr T* begin( T (&array)[N] );
std::end
Bu metodun container ve array için özelleşmiş halleri var. container için şöyledir.
template< class C > 
auto begin( C& c ) -> decltype(c.end());
Array için C++11 ile şöyledir.
template <typename T, std::size_t N>
T* end(T (&ar)[N]) {
  return ar + N;
}
C++14 ile metod imzası değişmiştir.
template< class T, std::size_t N >
constexpr T* begin( T (&array)[N] );



10 Mart 2016 Perşembe

Pair ve Tuple

Giriş
std::pair ve std::tuple birbirlerine çok benziyorlar ancak std::tuple<A,B> ile std::pair<A,B> farklı tiplerdir.

pair ve tuple STL ile mecburen kullanılıyor çünkü algoritmaların genel (generic) olması gerekiyor. Kendi kodumda ise pair ve tuple yerine daha anlamlı struct veya class'lar kullanmayı tercih ediyorum.

std::pair
std::pair yazısına taşıdım.

make_pair
Örnek:
#include <vector>

using namespace std;

int main(){

    vector<pair<int,int>> v;

    for (int var = 0; var < 100000000; ++var) {
        v.push_back(make_pair(var, var));
    }
}
make_pair const, volatile, & gibi qualifier'ları düşürür.


6 Mart 2016 Pazar

isatty

Giriş
POSIX sistemlerde çıktının terminale gittiğini anlamak için şöyle yaparız.
if (isatty(STDOUT_FILENO)) {
   /// handle the stdout is terminal case
 }
isatty FILE * alır.

4 Mart 2016 Cuma

static_assert

static_assert
static_assert derleme zamanında hatanın yakalanmasını sağlar. İstenirse hatayı açıklayıcı bir mesaj da verilebilir. C++11 ile gelen bu özellik sayesinde aşağıdaki gibi Boost kullanmaya gerek kalmadı.
BOOST_STATIC_ASSERT((std::is_same<T,U>));
Nerede Tanımlanır
Açıklaması şöyle
A static assert declaration may appear at block scope (as a block declaration) and inside a class body (as a member declaration)
Block scope nedir anlamadım ama şöyle kullanılabilir. Bu kodu bir şekilde block içinde kabul ediyor.
struct foo_t
{
  ...
};
static_assert(...);

Nasıl Çalışır
Çalışması şuna benzer. Eğer expr false ise büyüklüğü -1 olan bir array yaratılmaya çalışılır. Tabiki derleyici bunu derlemez ve hata verir.
// A compile-time assertion.
template <bool>
  struct CompileAssert {
};

#define COMPILE_ASSERT(expr, msg) \
  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
Kullanım Örnekleri

static_assert genellikle std::is_same ile beraber kullanılır.
std::is_same<T,T>::value false ise mesajı derleme hatası olarak verir.

Container'ın içerdiği eleman ile ikinci parametre T ile aynı olması
Örnek.
template<typename Container, typename T> 
bool    contains (const Container & theContainer, const T & theReference) {
     static_assert(  std::is_same<typename Container::value_type, T>::value,
                    "Invalid container or type" );
     // ...
}

Metodun signature kontrolu
Şöyle bir template metodumuz olsun
template<typename TCallable>
void Fun(TCallable c){
...
}
TCallable nesnesinin int(double, double) imzasına sahip olduğu şöyle kontrol edilir.
static_assert(std::is_same<decltype(c(0.0,0.0)), int>::value, "c must take two doubles and return int")

Aritmetik Karşılaştırma
#include <cstring>

inline float
int_bits_to_float(const int bits)
{
  static_assert(sizeof(int) >= sizeof(float), "too few bits");
  float target;
  std::memcpy(&target, &bits, sizeof(float));
  return target;
}






String Algoritmaları

Giriş
Eğer kendi algoritmamızı yazıyorsak template şeklinde kodlamaya dikkat etmek gerekir. Parametremiz std::basic_string olmalı. Template olarak char, wchar kullanılabilir.

template<class T>
inline void myalgorithm(std::basic_string<T>& strInOut)
{...}
Trim
Trim string'in sağındaki ve solundaki boşlukları siler.
template<class TString>
static inline TString &trim_left(TString &s)
{
    s.erase(std::begin(s), std::find_if(std::begin(s), std::end(s),
                           std::not1(std::ptr_fun<int, int>(std::isspace))));
    return s;
}

template<class TString>
static inline TString &trim_right(TString &s)
{
    s.erase(std::find_if(s.rbegin(), s.rend(),
            std::not1(std::ptr_fun<int, int>(std::isspace))).base(), std::end(s));
    return s;
}

template<class TString>
static inline TString &trim(TString &s)
{
    return trim_left(trim_right(s));
}
Trim Right şöyle yazılabilir.
template<class T>
inline void removeOuterWhitespace(std::basic_string<T>& strInOut)
{
  constexpr auto delim[] = {T(' '),T('\t'),T('\n'),T(0)};
  const auto uiBegin = strInOut.find_first_not_of(delim);

  if (uiBegin == std::basic_string<T>::npos)
  {
    // the whole string is whitespace
    strInOut.clear();
    return;
  }

  const auto  uiEnd   = strInOut.find_last_not_of(delim);
  strInOut = strInOut.substr(uiBegin, uiEnd - uiBegin + 1);
}