16 Aralık 2016 Cuma

__func__ Değişkeni

Giriş
__func__ derleyici tarafından sunulan bir değişken. Açıklaması şöyle. C++11 ile geliyor.
The identifier __func__ is implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function. This name is the unadorned name of the function.
Metodu girip çıktıgımızı anlamak için şöyle yaparız.
struct FunctionLogger {
  FunctionLogger(const char* func)
    : m_func(func)
  {
    cout << func <<endl;
  }
  ~FunctionLogger() {
    cout << m_func << endl;
    }
  const char* m_func;
  
};
Kullanmak için şöyle yaparız.
void MyClass::SomeFunc()
{
  FunctionLogger _(__PRETTY_FUNCTION__);
  //Some code
}
Sınıfı macro haline getirip kullanmak için şöyle yaparız.
#define FL FunctionLogger _(__PRETTY_FUNCTION__)
Bu sefer macroyu kullanmak için şöyle yaparız.
void MyClass::SomeFunc()
{
  FL;
  //Some code
}
__FUNCTION__
C++11 desteği olmayan daha eski bir derleyici kullanıyorsak bazı derleyiciler __FUNCTION__  değişkenini sunuyor.

__PRETTY_FUNCTION__ değişkeni
gcc kullanıyorsak, bu derleyici __PRETTY_FUNCTION__ extension değişkenini sunuyor.
Aradaki farkı görmek için şöyle yaparız. gcc sadece metod ismini değil, tüm metod imzasını veriyor.
$ cat test.cpp 
#include <iostream>

int main(int argc, char **argv)
{
    std::cout << __func__ << std::endl
              << __FUNCTION__ << std::endl
              << __PRETTY_FUNCTION__ << std::endl;
}
$ g++ test.cpp 
$ 
$ ./a.out 
main
main
int main(int, char**)
Ayrıca tüm isim alanını da verir. Aradaki farkı görmek için şöyle yaparız.
#include <iostream>

namespace N {
    class C {
        public:
            template <class T>
            static void f() {
                std::cout << __func__ << std::endl
                          << __FUNCTION__ << std::endl
                          << __PRETTY_FUNCTION__ << std::endl;
            }
    };
}

int main() {
    N::C::f<int>();
}
Çıktı olarak şunu alırız.
f
f
static void N::C::f() [with T = int]









14 Aralık 2016 Çarşamba

Dönüşüm Operatörleri - Conversion Operators

Dönüşüm Operatörleri - Conversion Operator Nedir?
Dönüşüm operatörleri C++ dilinde Other Operators sınıfına dahil edilir. Bütün metodlar gibi bu operatörler istenirse virtual olabiliyorlar.

Dönüşüm operatörleri bence tamamen kafa karışıklığına sebep oluyorlar. Getter metodu kullanmak çok daha iyi bir çözüm. C++ dışındaki ana diller arasında Java bu tür dönüşüm operatörlerini desteklemiyor. C# ise destekliyor.

Dönüşüm operatörü en çok sınıfın içindeki bir alan dışarıya açmak veya bir hesaplama yapmak için kullanılır.

1. Dönüşüm operatörünün kopya dönen metod imzası aşağıdaki gibidir.
operator T() const // const olmak zorunda değil!
2. Referans dönen metod imzası ile şöyle.
operator T&();
operator const T&() const;
3. explicit metod imzası şöyle
explicit operator int() const;
Bu durumda static_cast ile şöyle yaparız.
Foo foo;
int i = static_cast<int>(foo);
explicit yazısında da explicit metod konusu mevcut.

Dönüşüm operatörü ne zaman çağırılır?
Cevabı buradan aldım.

1. Bir değişken başka bir tipe cast edilince

Çağırmak için static_cast<> veya C tarzı cast yapmak gerekir.

2. Ya da nesnemizi bir metoda parametre olarak geçerse, dönüşüm öperatörü derleyici tarafından otomatik çağırılır.

3. Değişken başka tipten bir başka değişkene atanınca.

4. Değişkenimiz bir başka tip için copy-construct veya ilklendirme (initialize) amacıyla kullanılınca.

Dönüşüm operatörü ne için kullanılmalı?
Bence mümkünse dönüşüm operatörü yerine getter() metodlar kullanılmalı. Ancak eğer illaki kullanılacaksa sınıfı sadece primitive bir tipe dönüştürmek için kullanılmalı. Mesela sınıfı bool tipine çevirmek için kullanılabilir.

Bazı örnekler
Aşağıda gördüğüm bazı dönüşüm örnekleri var.

double operatörü
Şöyle yaparız:
struct MoreDouble
{
   operator double() { return 42.5; }
};
int operatörü
Şöyle yaparız.
class Foo {
public:
    operator int() const;
    ...
};
Şöyle kullanırız.
Foo foo;
int i = foo;

FILE* operatörü
Örnek:
class File_ptr{
    FILE* p;
public:
    File_ptr(const char* n, const char* a){p = fopen(n, a);}
    File_ptr(FILE* pp) { p = pp; }
    ~File_ptr() {fclose(p);}
    operator FILE* () {return p;} 
};

C++11 ile dönüşüm operatörünün rvalue ile kullanılmamasını sağlamak için aşağıdaki gibi yapılabilir.
operator FILE* () & { return p; }
// Note this -----^

Template Şeklinde Operator
Örnekte degree ve radyan isminde iki sınıf tanımlanmış. static_cast ile bir sınıftan diğerine olan dönüşüm operatörü çağırılıyor.
int main()
{
    using degs = degrees<float>;
    using rads = radians<float>;

    auto d = degs{10};
    auto r = static_cast<rads>(d);

    std::cout << d << std::endl;
    std::cout << r << std::endl;

    return 0;
}

Virtual metod gibi çalışma örneği
Dönüşüm operatörleri aslında dönüşüm fonksiyonları şeklinde isimlendirilselerdi daha iyi olurdu. Çünkü operatörden çok virtual metodlar gibi çalışıyorlar. Örnekte nesnenin dinamik tipi yani B'nin dönüşüm operatörü kullanılıyor.
class B;

struct A {
    virtual operator B() const = 0;
};

struct B : A
{
    public:
        operator B() const{ return B(); } // virtual override

    private:
        int m_i;
};

A const & q = B(); // q has dynamic type B, static type A
B r = q; // Convert A to B using B::operator B()



13 Aralık 2016 Salı

std::slice

std::slice metodu
Birin parametre başlangıç indeksini, ikinci parametres toplam büyüklüğü, üçüncü parametre ise atlanacak elemak sayısnı belirtir. Şöyle yaparız.
std::valarray<int> val {1,2,3,4,5};

auto head = val[std::slice(0, 1, 1)];
auto tail = val[std::slice(1, val.size() - 1, 1)];
Sonuç olarak şunu alırız.
std::vector<int> val {1,2,3,4,5};

//head = [1]
//tail = [2,3,4,5]
Python'daki şu kullanıma benzer
head = Array[0]
tail = Array[1:]

12 Aralık 2016 Pazartesi

std::num_get facet

Giriş
Şu satırı dahil ederiz.
#include <locale>
Açıklaması şöyle
Class std::num_get encapsulates the rules for parsing string representations of numeric values. Specifically, types bool, unsigned short, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, and void* are supported. The standard formatting input operators (such as cin >> n;) use the std::num_get facet of the I/O stream's locale to parse the text representations of the numbers.
Kendi Sınıfım
Şöyle yaparız.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class read_num : public std::num_get < charT > {

public:
  typedef charT char_type;
  typedef InputIterator iter_type;

protected:
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
    ios_base::iostate& err, double& val) const {
   
    return in;
  }
};

9 Aralık 2016 Cuma

STL Filtering Algoritmaları

Giriş
STL algoritmalarını işlevlerine göre gruplamak anlamayı çok daha kolaylaştırıyor. Aşağıdaki algoritmalar sıralı dizileri yine sıralı olarak birleştirme algoritmalarını gösteriyor.

unique
std::unique metodu yazısına taşıdım

unique_copy
Örnek ver

6 Aralık 2016 Salı

Visual Assist

Editör
VAssist > Tools > Edit VA Snippets.
1. New'e bas
2. Title gir.
3.Shortcut gir. Kısayol olarak "co" kullanırsak VS Editor içinde "co" yazınca girdiğimiz Title değerini ihtiva eden küçük bir menü açılır. Böylece VA Snippet'ın devreye girdiğini anlarız.
4. 1 ile başlayan satırdan itibaren VA macro'sunu yaz.

Editör Macroları
$end $ : İmleç bu macro'nun olduğu yere gelir.

4 Aralık 2016 Pazar

Variadic Inheritance

Elimizde çoklu kalıtım olsun. He bir ata sınıfın bir metodunu çağırmak isteyelim. Şöyle yaparız.
template<typename... Policies>
struct ComposedType : Object, Policies...
{
  virtual void loadData() override {
    int arr[] = {
      ((void)Policies::loadData(), 0)...
    };
    (void)arr;
  }
};

using FlyingCar = ComposedType<Drivable, Flyable>;
C++17 ile şöyle yaparız.
virtual void loadData() override {
  ((void)Policies::loadData(), ...);
}
Sınıfı tanımlamak için şöyle yaparız.
using FlyingCar = ComposedType<Drivable, Flyable>;