C++11 – Üye fonksiyonlarda ‘default’ ve ‘delete’ manipülasyonu

C++03 standartlarına göre boş bir sınıf tanımlasanız bile derleyici tarafından bir tane default constructor, copy ctor(constructor) ve atama operatörünü (operator=) sizin için oluşturuyordu.

C++11 standartlarıyla beraber direkt olarak derleyicinin bu tarz davranşlarını manipüle etme şansına hakim oluyorsunuz. C++ programlama dilini işte en çok bu yüzden seviyorum, yazılımcıya olabildiğince fazla hareket alanı sağlıyor.

Tipik bir örnek olarak eğer sınıfınıza herhangi bir ctor tanımladığınızda derleyici sizin için ctor tanımlamayacaktır. Aşağıdaki kodu inceleyelim;


#include <iostream>

using namespace std;

class herbibk
{
public:
    herbibk(int a) {};
};

int main(int argc, char**argv)
{

    herbibk hbk(5); //ok
    herbibk hb; //hata derleyici default ctor oluşturmadığı için:
                      //main.cpp:23:13: error: no matching function for call to ‘herbibk::herbibk()’

    return 0;
}

C++11 ile gelen yeni özellikle beraber derleyiciye kardeşim sen yine bana default ctor üret diyebiliyoruz;

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5); //ok    
    herbibk hb; //ok
    

 
    return 0;
}

Görüldüğü üzere artık derlerken hata almıyoruz.

herbibk()  = default;

İfadesini sadece sınıfın tanımına ekleyerek derleyici tarafından oluşturulan default ctor’un her zaman oluşturulmasını sağladık.

Başka bir kullanımı ise, daha önce C++03 zamanıda : ) bir sınıfı kopyalanamaz yapmak için copy ctor’unu ve atama operatörünü private yapılırdı. Şimdi bizim ‘delete’ imiz var hatta operator new’ i de ‘delete’ edebiliriz, Şöyle ki;

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
    herbibk(const herbibk&) = delete;
    herbibk& operator=(const herbibk&) = delete; 
    void* operator new(std::size_t) = delete;
    void* operator new[](std::size_t) = delete; 
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5); //ok    
    herbibk hb(hbk); //hata  derleyiciye copy ctor fonksiyonunu oluşturma demiştik : main.cpp:21:19: error: use of deleted function ‘herbibk::herbibk(const herbibk&)’
    
    hb = hbk; // hata derleyiciye atama operatörü fonksiyonunu oluşturma demiştik 🙂  : main.cpp:23:8: error: use of deleted function ‘herbibk& herbibk::operator=(const herbibk&)’
    
    herbibk *pHbk = new herbibk[4]; // hata main.cpp:25:34: error: use of deleted function ‘static void* herbibk::operator new [](std::size_t)’
    herbibk *pHbk = new herbibk; // hata main.cpp:26:25: error: use of deleted function ‘static void* herbibk::operator new(std::size_t)’

    return 0;
}

‘delete’ anahtar kelimesi otomatik tür dönüşümünü engellemek amacıyla tüm üye fonksiyonlara uygulanabilir, Örneğin;

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
    herbibk(const herbibk&) = delete;
    herbibk& operator=(const herbibk&) = delete;
    void f(int a) {};
    void f(double &) = delete;
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5); //ok    
    herbibk hb;
    
    hb.f(5); // ok sorun yok
    hb.f(5.); // ok sorun yok, çünkü otomatik olarak 5.0 int türüne dönüştürüldü.
    
    return 0;
}

Ayrıca bu kullanımı fonksiyon şablonlarını (function template) kullanarak genelleştirebiliriz; Örneğin f fonksiyonunu integer türü haricindeki hiçbir argümanla çağıramayalım:

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
    herbibk(const herbibk&) = delete;
    herbibk& operator=(const herbibk&) = delete;
    void f(int a) {};
    template<typename T> void f(T) = delete;
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5);  
    herbibk hb;
    
    hb.f(5); // ok sorun yok 
    hb.f(5.00); // hata: main.cpp:26:14: error: use of deleted function ‘void herbibk::f(T) [with T = double]’
    
    return 0;
}
Advertisements

Standart string kütüphanesi fonksiyonlarında geri dönüş değeri olarak “unsigned int”

Birçok yerde denk geldiğim için bununla ilgili bir blog yazısı yazmanın iyi olacağını düşünüyorum. Şimdi aşağıdaki koda bir bakmanızı rica ediyorum, ekrana ne yazılmasını bekliyorsunuz ?

#include    <iostream>
#include    <string>

using namespace std;

int main()
{
    string s("cppturkey");

    unsigned int index = s.find_last_of(".");

    if (index == string::npos)
        cout << "Nokta namevcut" << endl;
    else
        cout << "Nokta mevcut" << endl;

    return 0;

}

Aslında bu sorunun bir cevabı yok, sistemden sisteme değişebilir. string operasyonları geri dönüş değeri “size_t” türündendir. size_t ise standartlarda mevcut sistemin en yüksek pozitif alabileceği değerdir(pozitif -1). Aşağıdaki örneğe göz atabilirsiniz.


#include <iostream>
#include <string>

using namespace std;

int main()
{
unsigned int x = -1;
size_t y = -1;

cout << x << endl;
cout << y << endl;
return 0;

}

 

Türler arasındaki bağlantı C++ standartların aşağıdaki şekilde tanımlanmıştır ve garanti altındadır:

sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) = sizeof(size_t) <= sizeof(long long)

Dolayısıyla kullandıgınızda sistemde sizeof(unsigned int), sizeof(size_t)'dan farklı olabilir. Küçük olduğu durumlarda integer overflow olduğundan 'index == string::npos' ifadesi doğru olmayacak ve ekrana "Nokta mevcut" yazacaktır.

Garantili yol ise index değişkenini size_t türünden;

size_t index = s.find_last_of(".");

şeklinde tanımlamak olacaktır.

Smart Pointers History – from 03 to 17

Smart pointerların anlatıldıgı C++03 ten C++17 standartlarına kadar nelerin değiştiğinin anlatıldıgı söyleşimize herkes davetlidir.

Smart Pointers – from 03 to 17

Friday, Mar 27, 2015, 3:00 PM

Yıldız Teknopark
İkitelli- Başakşehir Istanbul, TR

1 C++’ers Attending

Kat 1 No: 101

Check out this Meetup →

GDB Remote Debug (Windows makinesinden Linux Makinesindeki binariyi debug etme)

This is a document which I prepared at work. That why I needed to prepare it in Turkish. If people show interest I will add translation.

GDB çok faydalı bir tool. Özellikle gdbtui olarak kullanınca bizim vazgeçilmez silahlarımızdan biri oluyor . Fakat diyelimki debug etmek istediğimiz structure: “ntplInfo.u.errorData.errBuffer[0]” gibi birşey. Bu structure ‘in içine bakmak için yazıcağımız gdb komutu o kadar uzun oluyorki, gdb konsolununda pek kullanıcı dostu olmamasından dolayı çalışmak imkansız hale geliyor . Bunun için user interface desteği almamız gerekiyor. Ben aşağıda eclipse araçılığıyla linux binarisini nasıl debug ederiz anlatmaya çalışacağım.

Şimdi adımları tarifi vermeden önce kullanıcağımız malzemelerden bahsedelim .

1- Linux makinesinde gdb ve gdbserver , versiyonlar 7.6 veya üstü olmalıdır.

2 – Windows makinesinde gdb’nin aynı versiyonun kurmalıyız. Bunun için mingw indirmemiz lazım. Yanı sıra derleyebilmemiz için expat isimli projeyi de manuel derlememiz lazım . Bunlardan sonra gdb yi derleyebiliriz .

3 – Eclipse ve eclipse pluginleri . Eclipse ‘in remote connection ile ilglli bütün core pluginlerine sahip olmamız lazım . Pluginler default geliyor zaten çok merak etmeyin .

Şimdi Gelelim Tarife:

1 – Zaten sistem takımımz tarafından GDB ve gdb server linux makinelerine kuruluyor . Siz yinede kontrol edin .

2- GDB yi linuxde default çalıştırın , x86_64-unknown-linux-gnu gibi bir banner görüceksiniz. Bunu note edin ileride kullanıcağız.

3- Mingw ‘yi indirin cvgwin ile denemeyin sorun çıkıyor .

4 -Expat source kodunu inidirin. Ve mingwden indirdiğin folder’A gidip ./configure , make , make install yapın.

5- GDB 7.7 nin source kodunu indirin  .”./gdb-7.4/configure –with-expat –target=x86_64-unknown-linux-gnu –host=i686-pc-mingw32″ ile konfigure edin .Ve sonra make ve make install yapın.

Şimdi gelelim ,manuel testte acaba bu adıma kadar herşeyi yaptıkmı . Ben burada yaklaşık 3-4 saat kaybettim umarım siz bu yazının sayesinde kaybetmezsiniz.

6 – Linux makinesinde dummy bir proje oluşturalım ismide hello olsun . Hello ‘u g++47 -g -o hello hello.cpp diyerek derleyelim.

7 – Linux makinesinde gdbserver ‘ı çalıştıralım : “gdbserver –debug localhost:10000 hello”, ben 10000 portunu seçtim sizin keyfiniz bilir

8 – 10000 portunu açalım yoksa OS reject ediyor (3-4 saat burda kaybettim)

[root@tux ~]# iptables -I INPUT -p tcp –dport 10000 –syn -j ACCEPT
[root@tux ~]# iptables -I INPUT -p tcp –sport 10000 –syn -j ACCEPT

9 – Windows makinesine hello binarisini ve hello.cpp’yi kopyalıyalım.

10 – Mingw ‘den hello ‘nun bulunduğu dizine gidip “./gdb  hello” ile çalıştıralım. Ve sonrada “target remote 172.16.42.244:10000” komutu ile linux makinemizdeki(172.16.42.244) gdbserver ‘a bağlanalım.

image2014-6-4 14-6-56  console’dan testlerimizi yaptık. Ama asıl amaçımız eclipseden bir GUI yardımı ile bunu başarmak.

11  –  Eclipse ‘e geçmeden önce son olaraki global variable ‘lara mingw/bin path ini ekleyelim(sizin mingw niz nerdeyse ona göre ayarlayın). Ve yukardaki adımları windows cmd ‘den deneyin global variable ‘ı doğru set ettiyseniz herşey yukardaki gibi çalışacaktır .

Geldik eclipse kısmına, eclipse bir sürü butonlar ve opsiyonlar koymuş fakat bir çoğu bizim konumuzla alakasız ve kafa karıştırıcı.

12 – Eclipse ‘de projenizi seçin, benim bu örnekte anlataçağım artık hello değil napa_project olacak. run–>debug_configurations penceresini açın. Burda sol menüde “C/C++ attach to application”  opsiyonun seçin diğerleri benim gibi zaman kaybetmenize neden olacaktır.

13 – C/C++ application kısmına debug etmek istediğiniz binariyi şeçin, project olarak debug etmek istediğiniz projeyi şeçin. Benim için ekran çıktısı:

image2014-6-4 20-18-52

14 – Aynı tabde şimdi debugger ‘a gelin, debugger olarak gdbserver şeçin , gdb olarak windows ‘a yeni kurduğumuz gdb binarisini seçin . GDB command file ‘I .gdbinit olarak bırakın .

image2014-6-4 20-21-52

15 – GDBSERVER seçtiğinizde debugger tab’ında  yukarda gözüktüğü gibi Connection sekmesi açılacaktır . host ip yi(linux ip si) ve gdbserver ‘in dinlediği portu(10000) buraya yazın .

image2014-6-4 20-23-11
16 – .gdbinit dosyasının içine aşağıdaki satırları kendinize uygun olarak girin

file test
b main
set solib-absolute-prefix /root/erdemdem/napa_project/
set solib-search-path /lib64

17 – Eğer warning: Could not load shared library symbols for 11 libraries, e.g. /opt/napatech3/lib/libntapi.so.

gibi bir warning alıyorsanız

set solib-search-path /opt/napatech3/lib/ , gibi gdbinit dosyasına eklendi yapın buraya bir kere koymanız gerekecek her gdb çalıştığında her zaman otomatik çalışacaktır.

18 – Linux tarafında gdbserver ayakta ve listening modda olduğunda emin olun ,

19 – Debugı başlatın , gdbinit ‘e b main koyduğumuzdan main ‘de duracaktır .

20 – GUI den break point, next ,continue gibi testleri yapın

Sonuç : unlimited debugging powerrrr

image2014-6-4 20-29-40

SharpEar Multi Channel Acoustic Camera Simulation

SharpEar is a open source “Microphone array” simulation project.
SharpEar simulates a “Microphone Array” and “Room”.
User can add voice, noice, moving voices in to the Room. After User selects a .wav file and a position for this sound in the room; user can trigger beamforming . According to the position of the “Microphone Array” and “Sound Sources” beamforming will color the room. User can choose a “Sound” as “Noice”, “Voice” or even a Moving “Voice”.

Features

  • Room Simulation For Microphone Array
  • Wav files will be read and could be attached any point in the room
  • Sounds could be categorized by User as noice,sound or moving sound.
  • Beamforming and Room Coloring according to beamforming result in each point
  • Speaker Identification
  • Adaptive Beamforming according to speaker identification

Links :

https://sourceforge.net/projects/sharpear/

https://github.com/kerdemdemir/sharpEar

sharpEarOutput

Macro’s vs Variadic Templates – 2

Former article was visited by C++ fans from around the world. Therefore i decided to publish my article in english. Thanks for visiting web site.

More Generic Design
You know templates provide more generic design than function overloading. And now with C++11, you can even design more generic templates than templates, so variadic templates.

I want to write a function that gives me size of all containers in STL(even if they almost all have a size function 🙂 ). You know STL has two main container types:
– Sequence Containers
– Associative Containers

Sequence containers take 2 arguments ValueType and mainly Allocator:

template<class T,
         class Allocator = std::allocator<T>
         > class SeqContainer;

I will try to implement my function-template for sequence containers.

template < template <typename, typename> class ContainerType, typename ValueType, typename Alloc>
size_t sizeOfContainers(ContainerType<ValueType, Alloc> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

As you see first template parameter “template class ContainerType” is a template class as template parameter. Second and third one are template parameters of first parameter.

But that function template will not work for std::array type. We will look that problem later. Mainly this function satisfies our needs.

#include <vector>
#include <iostream>
#include <memory>
#include <map>
#include <forward_list>
#include <unordered_set>
#include <array>

using namespace std;

template < template <typename, typename> class ContainerType, typename ValueType, typename Alloc>
size_t sizeOfContainers(ContainerType<ValueType, Alloc> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}



int main()
{
    vector<int> v({1, 4, 5, 3, 5, 6});
    forward_list<int> fl ({ 34, 99, 10, 71});
    
    cout << sizeOfContainers(v) << endl;
    cout << sizeOfContainers(fl) << endl;

   
  return 0;
}

Associative containers take 3 or 4 arguments for example:

std::set

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

std::map

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

std::unordered_set

 
template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_set;

Therefore we need two more overload for our function to handle this containers. Let’s try to write them :


template < template <typename, typename, typename> class ContainerType, typename FirstType, typename SecondType, typename AllocType>
size_t sizeOfContainers(ContainerType<FirstType, SecondType,  AllocType> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

template < template <typename, typename, typename, typename> class ContainerType, typename FirstType, typename SecondType, typename ThirdType, typename AllocType>
size_t sizeOfContainers(ContainerType<FirstType, SecondType, ThirdType, AllocType> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

As you see for that functions can handle this issue for different type.

But now we have three overloads, can we reduce it to one function with variadic functions ? Lets try it:

template <template <typename, typename...> class ContainerType, typename FirstType, typename... Types> 
size_t sizeOfContainers(ContainerType<FirstType, Types...> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

Now we can handle all 2,3,4 parameter containers. Except one std::array. std::array takes two parameter:

template< 
    class T, 
    std::size_t N 
> struct array;

Remember, we discussed variadic template function creation at first article. In that example our variadic function will not create function that we need for std::array. Actually second type of std::array is not a type, it is a constant. And it is not allowed in C++, also compile time error. Function overloading take responsibility for us :

template <template <typename, size_t> class ContainerType, typename FirstType, size_t S> 
size_t sizeOfContainers(ContainerType<FirstType, S> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

That overload will handle our issue. Sometimes we need partial specialization overloads to resolve problems.

At the end of the day score is on the board:

Variadic templates 3 – 1 Function overloading

Full Source Code:

#include <vector>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <map>
#include <forward_list>
#include <unordered_set>
#include <array>
#include <set>
#include <deque>

using namespace std;


template <template <typename, typename...> class ContainerType, typename FirstType, typename... Types> 
size_t sizeOfContainers(ContainerType<FirstType, Types...> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}


template <template <typename, size_t> class ContainerType, typename FirstType, size_t S> 
size_t sizeOfContainers(ContainerType<FirstType, S> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

template < template <typename, typename> class ContainerType, typename ValueType, typename Alloc>
size_t sizeOfContainers(ContainerType<ValueType, Alloc> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

template < template <typename, typename, typename> class ContainerType, typename FirstType, typename SecondType, typename Alloc>
size_t sizeOfContainers(ContainerType<FirstType, SecondType,  Alloc> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}

template < template <typename, typename, typename, typename> class ContainerType, typename FirstType, typename SecondType, typename ThirdType, typename Alloc>
size_t sizeOfContainers(ContainerType<FirstType, SecondType, ThirdType, Alloc> &c)
{
    size_t s = 0;
    for (auto element : c) {
        s++;
    }
    return s;
}



int main()
{
    vector<int> v({1,2,3,4,5,6});
    map<int, int> m({ {2,3},  {4, 5}});
    set<int> s({8, 7});
    deque<int> d = {10,20,30};
    forward_list<int> fl ({ 34, 77, 16, 2 });
    array<int,10> a = { 2, 16, 77, 34, 50};
    unordered_set<string> us = {"C++", "UG","ISTANBUL","69736c616d"};
    

    cout << sizeOfContainers(v) << endl;
    cout << sizeOfContainers(m) << endl;
    cout << sizeOfContainers(fl) << endl;
    cout << sizeOfContainers(us) << endl;
    cout << sizeOfContainers(s) << endl;
    cout << sizeOfContainers(a) << endl;
    cout << sizeOfContainers(d) << endl;
    
  return 0;
}

Debugging with GDB – C++ UG Meetup

28 Kasım Cuma günü saat 15:00’de “Debugging with GDB” adlı seminerimize herkes davetlidir.

Debugging with GDB

Friday, Nov 28, 2014, 3:00 PM

Teknopark Istanbul Konferans Salonu
Teknopark Istanbul Pendik Istanbul, TR

3 C++’ers Attending

Check out this Meetup →

Macro’s vs Variadic Templates – 1

Variadic fonksiyonlar istenilen sayıda değişken almaları sayesinde bir çok işi kolaylaştırmışlardır. C++11 den önce C de bu ihtiyaç “…” elipsis operatörü ve va_* makrolarıyla çözülüyordu. Fakat bu çözüm çalışma zamanında işlediğinden yanlış kullanım veya beklenmedik durumlarda çalışma zamanı hataları veya seg fault dahi alınabiliyordu.

Örneğin;

int a ;

printf("%s", a);

Bu kod örneği derleme zamanında (compile time) hata vermez. Fakat çalışma zamanında seg fault alırsınız. C++11 de bu problem variadic templatelerle çözülüyor. Üstelik derleme zamanında çözüldüğü için yanlış kullanım durumunda hemen müdahale edebiliyorsunuz.

Variadic templates

Basit bir önekle devam edelim;

#include <iostream>

using namespace std;

template<typename T>
void println(T v) //A
{
    cout << v << endl;
}

template<typename T, typename... Types>
void println(T first, Types... values) //B
{
    println(first);
    println(values...);
}

int main()
{
   println("islam", "cppistanbul", 1299); //1
   println(6, 1, 0, "c++UG", 5, 7, 1); //2
  
  return 0;
}

“typename… Types” şablon parametre paketi(template parameter pack), “Types… values” ise fonksiyon parametre paketi (function parameter pack) şeklinde adlandırılıyor. template parameter packteki Types aslında bir tür listesi. Örneğin “1” durumunda bu liste “const char *, const char *, integer” şeklindedir.Function parameter pack ise bir değer listesidir. Yine “1” durumunda bu liste “islam, cppistanbul, 1299” şeklindedir. Elipsis (…) operatörüyle de bu değerler ve türler açılır(expand). Burda dikkat ederseniz iki tane println fonksiyonu var, basitçe bir oveload aslında. Bu overload ile aslında kısmi bir rekürsiv çağrı yapıyoruz. Daha iyi anlaşılması için adım adım ilerleyelim.

1.iterasyon:

“1” durumunda println fonksiyonu 3 tür ie çağırılmış. Template argument deduction yaparak B deki overload çağrılacak ve:

void println(T, Types ...) [with T = const char*; Types = {const char*, int}]

parametre bu şekilde belirlenecek. Derleyici bir tane yukarıdaki imzaya sahip bir fonksiyon oluşturacak. Ve dikkat edin A durumundaki tek parametreli template de şu şekilde derleyici tarafından yazılacak:

void println(T) [with T = const char*]

2. iterasyon:

B template fonksiyonu:

void println(T, Types ...) [with T = const char*; Types = {int}] 

şeklinde, A template fonksiyonu ise yine aynı imzaya sahip olacağından tekrar yazılmayacak.

3. iterasyon

Bu durumda ise sadece tek tür kaldıgından direkt olarak A template fonksiyonu tercih edilecek(argument deduction). Ve aşağıdaki imzaya sahip bir fonksiyon derleyici tarafından yazılacak:

void println(T) [with T = int]

Bu sayede println fonksiyonuna verdiğimiz değerlere uygun overload edilmiş println fonksiyonu çağıralarak ekrana bu değerler yazılmış olacak.

To be continued :))

C++11 R-value References and Move Semantics

17 Ekim Cuma Günü C++11 Sağ değer referansları ve Move semantiği hakkında Teknopark İstanbul teknoloji geliştirme ofisinde saat 15:00-17:00 arasında seminerimiz vardır. Etkinlik herkese açık ve ücretsizdir.

Edit: Daha önce 2 Ekim olarak duyurduğumuz etkinlik tarihi 17 ekime alınmıştır.