29 grudnia 2013

[python] Dekoratory

Python ma wbudowany mechanizm pozwalający na implementowanie dekoratorów (wzorzec projektowy), dla istniejących metod. W skrócie, przed wywołaniem pożądanej funkcji wołana jest wcześniej zdefiniowana funkcja dekoratora, której argumentem jest pierwotna funkcja. Dekorator zwraca nową funkcję, która ma być wołana w miejsce pierwotnej.

Poniżej przykład dla funkcji obliczającej rekurencyjnie silnię. Stworzone zostały dwa dekoratory. Pierwszy zajmuje się zapamiętywaniem obliczonych już wartości. Druga metoda drukuje na ekranie parametry wywołania funkcji. Fajny sposób na zapewnienie single responsibility principle.
def cache(fun):
    cache_map = {}
    def _f(*args):
        try:
            if args in cache_map:
                return cache_map[args]
            cache_map[args] = result = fun(*args)
            return result
        except:
            # some element of args can't be a dict key
            return fun(args)
    return _f

def log(fun):
    def _f(*args):
        print('log: ' + fun.__name__ + '(' + str(*args) + ')')
        return fun(*args)
    return _f

@cache
@log
def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n-1)

assert factorial(3) == 6
assert factorial(1) == 1
Wynik:
log: factorial(3)
log: factorial(2)
log: factorial(1)
log: factorial(0)

22 grudnia 2013

Digital certificate

Rozglądam się w temacie certyfikatów cyfrowych podpisujących strony. Kilka linków i prost zabawa z OpenSSL.
Informacje o certyfikacie i sprawdzenie czy jest wystawiony przez zaufane źródło
# Informacje na temat certyfikatu wyeksportowanego z Firefox-a
$ openssl x509 -text -in A-Trust-nQual-03.pem

$ openssl verify A-Trust-nQual-03.pem 
A-Trust-nQual-03.pem: OK

21 grudnia 2013

[C++14] Hello world

Kompilacja z ficzerami dla C++14. Niestety dla clang-3.4 wymagało to trochę zachodu, ale w końcu się udało. Przed kompilacją trzeba było doinstalować "libc++-dev - LLVM C++ Standard library (development files)".
sudo apt-cache search libc
sudo apt-get install libc++-dev
Następnym krokiem była edycja pliku cstdio. Jak przeczytałem pod tym linkiem, ::gets najwyraźniej zostało usunięte ze standardu, a ja przy próbie kompilacje otrzymywałem następujący error:
/usr/include/c++/v1/cstdio:156:9: error: no member named 'gets' in the global namespace
using ::gets;
      ~~^
1 error generated.
Sama poprawka jaką należy wprowadzić do /usr/include/c++/v1/cstdio, czyli otoczyć gets defajnsem:
#if !_ISOC11_SOURCE
using ::gets;
#endif
Kompilacja wygląda następująco:
$ clang++ -std=c++1y -stdlib=libc++ main.cpp
I kod, na którym testowałem
#include <iostream>

using namespace std;

auto fun() {
    return "Hello world";
}

int main() {
    cout << fun() << endl;
    return 0;
}

11 grudnia 2013

[C++11] Dziedziczenie/unhide konstruktora

W nowym standardzie klasa pochodna może odziedziczyć (jest to właściwie mechanizm unhide, jaki był do tej pory dostępny tylko dla metod) swój konstruktor z jednej lub więcej klas bazowych. Jeżeli taki sam konstruktor (z takimi samymi parametrami) pojawi się w kilku klasach bazowych należy zdefiniować własną wersję w klasie pochodnej. Ciekaw linki:
Mechanizm pozwala na niejawne zadeklarowanie wszystkich konstruktorów, które nie są: domyślnymi, copy/move ani konstruktorami o takiej samej sygnaturze jak już istniejące konstruktory z klasy bazowej.

W poniższym przykładzie klasa Derived, dziedziczy z dwóch klas bazowych, dla których zachodzi konflikt dla Base1(int) i Base2(int), powodujący błąd kompilacji. Aby się go pozbyć w klasie pochodnej należało stworzyć własną wersję tego konstruktora. Ponieważ w Derived pojawił się już konstruktor, kompilator nie wygeneruje za nas konstruktora domyślnego (linia 32 - nie działa) - można stworzyć własną wersję.
#include <iostream>
#include <vector>
using namespace std;

struct Base1 {
    Base1() { cout << "Base1" << endl; }
    Base1(std::vector<int>) { cout << "Base1(vector)" << endl; }
    Base1(int) { cout << "Base1(int)" << endl; }
};

struct Base2 {
    Base2() { cout << "Base2" << endl; }
    Base2(int) { cout << "Base2(int)" << endl; }
};

struct Derived : public Base1, public Base2 {
    using Base1::Base1;
    using Base2::Base2;

    // Ta wersja konstruktora znajduje się w Base1 i Base2
    // należy zdefiniować jej własną wersję!
    Derived(int i) : Base1(i), Base2(i) {
        cout << "Derived(int)" << endl;
    }
};

struct SimpleDerived : public Base1 {
   using Base1::Base1;
};

int main() {
//  Derived d1;
    Derived d2(789);
    Derived d3({1, 2});

    SimpleDerived s1;
    SimpleDerived s2(42);
    SimpleDerived s3({1, 2});

    return 0;
}
Wynik:
Base1(int)
Base2(int)
Derived(int)

Base1(vector)

Base2
Base1

Base1(int)

Base1(vector)

7 grudnia 2013

Ubuntu 13.10 - konfiguracja

Kolejna przesiadka tym razem na Ubuntu 13.10.

Układ klawiatury

Niestety w tej wersji wyparowała opcja zmiany układu klawiatury, co w moim przypadku powoduje uciążliwy problem w korzystaniu z klawiszy Shift+Home i Shift+End, które mam na klawiaturze numerycznej. Można skorzystać z rozwiązania jakim jest gnome-tweak-tool.
Znalazłem jeszcze jedno rozwiązanie, które nadaje się do wykorzystanie z fluxbox-em.
Przez wpisanie do .bashrc
# Set numeric keypad behavour so that shift <numeric key> works the same
# as shift <cursor key> when numlock is off.
setxkbmap -option numpad:microsoft

Wyłączenie konta gościa

Trzeba dopisać na koniec pliku /etc/lightdm/lightdm.conf.d/50-unity-greeter.conf
allow-guest=false

Zwalnianie miejsca na dysku

Doszło do tego, że zaczęło mi brakować miejsca, na partycji. Pomocne okazało się kilka opcji dla apt-get
# Czyści lokalne repozytorium, ze ściągniętymi paczkami. Usuwa paczki, 
# których już nie można ściągnąć i są w zasadzie bezużyteczne.
sudo apt-get autoclean

# Usuwa pliki które są cache-owane, kiedy program jest instalowany 
# albo uaktualniany.
sudo apt-get clean

# Usuwa paczki, które zostały zainstalowane w celu nasycenia 
# zależności dla innych  paczek i nie są już potrzebne.
sudo apt-get autoremove

1 grudnia 2013

[C++11] Wyjątki i noexcept

Jeżeli wyjątek wystąpi w konstruktorze, nawet jeżeli obiekt jest tylko częściowo stworzony standard gwarantuje, że stworzone już dotąd obiekty zostaną poprawnie zniszczone. Tak samo w przypadku gdy wyjątek wystąpi w momencie inicjalizacji tablicy albo kontenera.

Jeżeli destruktor działa na operacji, która może zniszczyć obiekt, powinien on z-wrapować taką operację w blok try i obsłużyć wyjątek lokalnie. Destruktory nie powinny rzucać wyjątków! Jeżeli podczas zwijania stosu destruktor rzuci wyjątkiem którego sam nie złapał program zostanie zterminowany.
#include <iostream>
using namespace std;

struct MyClass {
    ~MyClass() /* noexcept */ {
        throw std::exception();
    }
};

int main() {
    MyClass a;
    return 0;
}
Wynik:
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
The program has unexpectedly finished.
Kilka zasad dotyczących tworzenia, rzucania i łapania wyjątków:
  • Obiekty wyjątków, które są rzucane, muszą mieć dostępny destruktor, a także konstruktor kopiujący lub konstruktor move.
  • Najbardziej wyspecjalizowany catch musi pojawić się jako pierwszy.
  • Aby wyrzucić wyjątek wyżej, trzeba podać throw bez wyrażenia (throw;).
  • Aby złapać wyjątek każdego typu trzeba skorzystać z catch(...), który powinien zawsze pojawiać się jako ostatni.
#include <iostream>
#include <typeinfo>
#include <stdexcept>
using namespace std;

void old() {
    throw std::runtime_error("old()");
}

void young() {
    try {
        old();
    } catch(const std::bad_cast& e) {
        cout << e.what() << endl;
    } catch(...) {
        cout << "unknown, rethrow" << endl;
        throw;
    }
}

int main() {
    try {
        young();
    } catch(const std::runtime_error& e) {
        cout << "in main: " << e.what() << endl;
    }

    return 0;
}
Wynik:
unknown, rethrow
in main: old()

Lista inicjalizacyjna konstruktora

Konstruktor nie może złapać wyjątków rzuconych z listy inicjalizacyjnej. Aby się przed tym ustrzec, blok try musi znajdować się przed dwukropkiem. Zachowanie jest podobne w działaniu do zwykłych try-catch, z tą różnicą że złapany wyjątek zostanie ponownie wyrzucony z bloku.
#include <iostream>
#include <stdexcept>
using namespace std;

struct Member {
    Member() { }
    Member(Member& m) {
        throw std::runtime_error("Constructor");
    }
};

struct BadCalss {
    Member member;
    BadCalss(Member& m) try : member(m) {
        // body
    } catch(...) {
        cout << "some bug" << endl;
    }
};

int main() {
    Member m;
    BadCalss bc(m);
    return 0;
}
Wynik:
some bug
terminate called after throwing an instance of 'std::runtime_error'
  what():  Constructor
The program has unexpectedly finished.

noexcept

W nowym standardzie pojawił się specjalny specyfikator noexcept. Jeżeli wiemy, że funkcja nie będzie rzucać wyjątku, może z tej informacji skorzystać i programista i kompilator. Wspominał o tym również Scott Meyers w swoim wykładzie na Going Native 2013. Kompilator w takim przypadku wygeneruje znacznie mniej kodu, który będzie bardziej optymalny w działaniu.
#include <iostream>
#include <stdexcept>
using namespace std;

void fun() noexcept {
    throw std::runtime_error("fun()");
}

// gun() ma taki sam specyfikator rzucanych typów jak fun()
void gun() noexcept(noexcept(fun())) {
    cout << "gun()" << endl;
}

int main() {
    fun();
    return 0;
}
Wynik:
terminate called after throwing an instance of 'std::runtime_error'
  what():  fun()
The program has unexpectedly finished.
W rezultacie noexpect powinno być stosowane w dwóch przypadkach. Kiedy jesteśmy przekonani, że funkcja nie rzuci wyjątku albo/i gdy nie chcemy obsługiwać błędu. Jeżeli z funkcji (oznaczonej jako noexcept) zostanie jednak rzucony wyjątek, natychmiast zawołane zostanie std::terminate().

Inny przykład, w którym wyjątek przelatuje przez funkcję z noexcept, co powoduje zterminowanie programu.
#include <iostream>
#include <stdexcept>

using namespace std;


void fun_a() {
    throw std::runtime_error("bug");
}

void fun_b() noexcept {
    fun_a();
}

void fun_c() {
    try {
        fun_b();
    } catch(...) {
        cout << "Exception caught" << endl;
    }
}

int main() {
    fun_c();
}
Wynik:
terminate called after throwing an instance of 'std::runtime_error'
  what():  bug
The program has unexpectedly finished.
Niektóre kontenery jak np. std::vector, sprawdzają (podczas realokacji wektora), czy "move konstruktor" jest oznaczony jako noexcept. Jeżeli tak nie jest zostanie zwołany zwykły konstruktor kopiujący, co jest operacją dużo wolniejszą. Odpowiedni eksperyment stworzyłem w innym artykule.
Poza "move konstruktorem" noexcept standardowo powinno znaleźć się również w deklaracji destruktora.

Stare - throw()

W poprzedniej wersji standardu istniało słowo kluczowe throw(), które obecnie jest uznawane za przestarzałe. Można było za jego pomocą wyspecyfikować jakiego rodzaju wyjątki mogą być wyrzucone z funkcji, albo (odpowiednik noexpect) że funkcja nie rzuci żadnego wyjątku.
int fun(std::string& b) throw();

30 listopada 2013

[C++11] Wskaźniki na metody i pola klasy

Wskaźniki na funkcje, a co dopiero na metody klas zawsze sprawiały mi problemy. Nowy standard oferuje kilka narzędzi, dzięki którym praca z nimi staje się trochę łatwiejsza. Dużo fajnych opisów znalazłem pod poniższym linkiem.
Możemy stworzyć wskaźnik na pola lub metody, korzystając z auto bądź decltype, zamiast pisać skomplikowaną deklarację (w starym stylu). Analogicznie do operatorów odwołujących się do zmiennych obiektu (. oraz ->) istnieją dwa mechanizmy do odwołania się do pola (zmiennej lub metody) przez wskaźnik: .* oraz ->*.

Poniżej ptr_name, jest wskaźnikiem na pole MyClass::name. Dla ptr_name2 skorzystałem z auto dzięki czemu deklaracja znacznie się skróciła.
#include <iostream>
using namespace std;

struct MyClass {
    std::string name;
};

int main() {
    MyClass m;

    std::string MyClass::*ptr_name = &MyClass::name;

    m.name = "tekst";
    MyClass *d = &m;
    cout << d->*ptr_name << endl;
    cout << m.*ptr_name << endl;

    m.*ptr_name = "blow";
    cout << m.name << endl;

    auto ptr_name2 = &MyClass::name;
    m.*ptr_name2 = "blow up";
    cout << m.name << endl;

    return 0;
}
Wynik:
tekst
tekst
blow
blow up

Wskaźnik do metody w klasie

Na początek prosty przykład z wołaniem metody bezargumentowej. Standard wprowadza dodatkowe trzy mechanizmy pozwalające na odwołanie się to metody klasy. Są to std::function (klasa szablonowa), std::mem_fn oraz std::bind pozwalająca na wygenerowanie wołanego obiektu ze wskaźnika na funkcję. Ponieważ działam na metodach klasy spodziewam się, że std::mem_fn jest do tego najlepszym mechanizmem (z racji przeznaczenia), ale nie wiem, czy jest jakaś istotna różnica w porównaniu do dwóch pozostałych.
#include <algorithm>
#include <functional>
#include <iostream>

struct MyClass {
    MyClass(std::string s) : name(s) { }
    std::string info() {
        std::cout << "info " << name << std::endl;
        return name;
    }
    int fun(char*) {
        std::cout << "fun " << name << std::endl;
        return 8;
    }

    std::string name;
};

int main() {
    using namespace std::placeholders;
    std::vector<MyClass> vec {MyClass("a"), MyClass("b"), MyClass("c")};

    std::function<std::string (MyClass&)> pinfo1 = &MyClass::info;
    std::for_each(begin(vec), end(vec), pinfo1);

    std::for_each(begin(vec), end(vec), std::mem_fn(&MyClass::info));

    auto pinfo2 = std::bind(&MyClass::info, _1);
    std::for_each(begin(vec), end(vec), pinfo2);

    return 0;
}
Następny przykład to wołaniem metody (MyClass::fun) posiadającej jeden argument. Na początku deklaracja wskaźnika na funkcję w starym dobrym stylu (pfun1) i jej uproszczona wersja korzystająca z auto (pfun2). Korzystanie z std::function oraz std::mem_fn jest już trochę bardziej skomplikowane i wymaga zastosowania lambdy (nie jestem pewien, czy można sobie to jeszcze jakoś bardziej ułatwić).

Najbardziej przejrzyste rozwiązanie powstało z std::bind dzięki placeholder-om. Warto pamiętać, że korzystając ze wskaźników na funkcję (tak przy deklaracji jak i wywołaniu), należy użyć dodatkowych nawiasów, ponieważ operator nawiasowy ma wyższy priorytet niż operator wskaźnika-na-pole (.*). Ogólne postać:
(Class::*fun)(param) (obj.*fun)(arg)
Pełny przykład:
#include <algorithm>
#include <functional>
#include <iostream>

struct MyClass {
    MyClass(std::string s) : name(s) { }
    std::string info() {
        std::cout << "info " << name << std::endl;
        return name;
    }
    int fun(char*) {
        std::cout << "fun " << name << std::endl;
        return 8;
    }

    std::string name;
};

int main() {
    using namespace std::placeholders;
    std::vector<MyClass> vec {MyClass("a"), MyClass("b"), MyClass("c")};

    int (MyClass::*pfun1)(char*) = &MyClass::fun;
    std::for_each(begin(vec), end(vec), [&](MyClass& c){ (c.*pfun1)(nullptr); });

    auto pfun2 = &MyClass::fun;
    std::for_each(begin(vec), end(vec), [&](MyClass& c){ (c.*pfun2)(nullptr); });

    std::function<int(MyClass&, char*)> pfun3 = &MyClass::fun;
    std::for_each(begin(vec), end(vec), [&](MyClass& c){ pfun3(c, nullptr); });

    std::for_each(begin(vec), end(vec),
                  [&](MyClass& c){ std::mem_fn(&MyClass::fun)(c, nullptr); });

    std::for_each(begin(vec), end(vec), std::bind(&MyClass::fun, _1, nullptr));

    return 0;
}
A teraz problem, który od dawna chodził mi po głowie, czyli stworzenie funkcji hash-ującej dla unordered_map, bez wrapera w postaci free function. Ponieważ getHash() jest metodą const-ową, std::function musi to uwzględniać w parametrze.
#include <functional>
#include <iostream>
#include <unordered_map>

struct Color {
    Color(size_t v) : value(v) {}
    size_t getHash() const {
        std::cout << "getHash() " << value << std::endl;
        return value;
    }
private:
    size_t value;
};

int main() {
    using namespace std::placeholders;
    constexpr size_t bucket_count = 42;

    auto equalOp = [] (const Color& l, const Color& r)
                    { return l.getHash() == r.getHash(); };

    std::function<size_t(const Color&)> hashFun1 = &Color::getHash;
    std::unordered_map<Color,
            std::string,
            decltype(hashFun1),
            decltype(equalOp)> m1(bucket_count, hashFun1, equalOp);

    m1[Color(1)] = "blue";

    auto hashFun2 = std::mem_fn(&Color::getHash);
    std::unordered_map<Color,
            std::string,
            decltype(hashFun2),
            decltype(equalOp)> m2(bucket_count, hashFun2, equalOp);

    m2[Color(2)] = "red";

    auto hashFun3 = std::bind(&Color::getHash, _1);
    std::unordered_map<Color,
            std::string,
            decltype(hashFun3),
            decltype(equalOp)> m3(bucket_count, hashFun3, equalOp);

    m3[Color(3)] = "green";

    return 0;
}

27 listopada 2013

[C++11] virtual, final, override

Klasa, która zawiera czysto wirtualną funkcję (= 0) jest klasą abstrakcyjną (nie da się stworzyć obiektu z takiej klasy).

Często klasy dziedziczące po klasie abstrakcyjnej zaczynały się od słowa virtual, choć nie jest to konieczne. Była to konwencja stosowana przez programistów, aby oznaczyć metody, narzucone przez interfejs.
#include <iostream>
using namespace std;

struct Interface {
    virtual void show() = 0;
    virtual void show2() {
        cout << "Interface" << endl;
    }
};

struct Father : public Interface {
    void show() {    // nie ma virtual i działa
        cout << "Father" << endl;
    }
};

struct Child : public Father {
    void show() {    // nie ma virtual i działa
        cout << "Child" << endl;
    }
};

int main() {
    Child c;
    c.show(); // "Child"
    return 0;
}
Nowa wersja języka, bardzo tą kwestię ułatwia. Aby mieć pewność, że przesłaniamy metodę z klasy bazowej nowy standard wprowadził słowo kluczowe override (za nazwą metody). Przesłonięcie będzie działać i dla tej klasy i dla wszystkich z niej dziedziczących. Kompilator ostrzeże nas, jeżeli popełniliśmy jakiś błąd i zamiast przesłonić stworzyliśmy coś nowego.
#include <iostream>
using namespace std;

struct Interface {
    virtual void show() = 0;
    virtual ~Interface() noexcept { }
};

struct MyClass : public Interface {
    void show() override {
        cout << "MyClass" << endl;
    }
};

int main() {
    MyClass c;
    c.show();
    return 0;
}
Choć jest możliwa inicjalizacja zmiennych klasy bazowej w klasie pochodnej, należy trzymać się zasady:
Każda klasa w momencie konstrukcji, powinna inicjalizować tylko swoje zmienne składowe.

Czasami tworzymy klasy, z których nie chcemy by ktoś inny dziedziczył, albo nie wiemy czy nadaje się ona na klasę bazową. W nowym standardzie możemy oznaczyć taką klasę słówkiem final - dziedziczenie zostanie zabronione.
struct NoDerived final {
};

struct Inher1 : NoDerived { // ERROR
};

struct Derived {
};

struct Base final : public Derived { // To jest OK
};
Przesłanianie metod (czyli tylko wirtualnych), oznaczonych jako final, zakończy się error-em.
#include <iostream>
using namespace std;

struct Interface {
    virtual void show() = 0;
};

struct Base : public Interface {
    void show() final {
        cout << "Base" << endl;
    }
};

struct Derived : public Base {
    void show() override {     // ERROR!
        cout << "Derived" << endl;
    }
};

26 listopada 2013

[C++11] Enumeratory

Nowy standard pozwala na istnienie zakresu dla enumeratorów (scope enumeration). Nazwę takiego enumeratora trzeba poprzedzić słowem "class" lub "struct".
#include <iostream>
using namespace std;

enum class EnumType {
    one,
    two,
    three
};

int main() {
    EnumType e = EnumType::two;
    return 0;
}
Enum zawsze jest reprezentowany przez wewnętrzny typu (domyślnie dla enum-ów z zakresem jest to int). W nowym standardzie typ ten można także podać po dwukropku.
#include <iostream>
using namespace std;

enum Song : unsigned long long {
    raz,
    dwa,
    trzy
};

enum class Colors : unsigned long long {
    white,
    green,
    blue
};

int main() {
    Colors c = Colors::green;
    Song s = Song::dwa;
    return 0;
}
Dopuszczalne jest także tworzenie forward deklaracji dla enum-ów. Ponieważ nie ma domyślnego rozmiaru dla niezakresowych enum-ów każdy z nich musi określać typ, przez jaki jest reprezentowany. Dla zakresowych jest to prostsze, ponieważ domyślnym typem jest tam int.
//enum EnumType;      // ERROR - brakuje słówka class, lub typu
enum class EnumType;
enum class Colors : unsigned long long;
enum OldEnum : int;

25 listopada 2013

[C++] RTTI - typeid

Mechanizm RTTI (Run Time Type Identification) wspierany jest w języku przez dwa mechanizmy:
  • typeid - który zwraca typu danego wyrażenia
  • dynamic_cast - który bezpiecznie konwertuje wskaźnik/referencję do klasy bazowej na wskaźnik/referencję do klasy pochodnej.
RTTI powinno być stosowany z ostrożnością. Kiedy to jest możliwe powinien być raczej stosowany mechanizm funkcji wirtualnych niż zarządzanie typami. Tutaja tylko mała właściwość typeid.
#include <iostream>
#include <typeinfo>
using namespace std;

struct Base {
};

struct Derived : public Base {
};

int main() {
    int tab[24];
    std::string s;
    Derived d;
    Base *b = &d;

    cout << typeid(42).name() << endl;
    cout << typeid(tab).name() << endl;
    cout << typeid(s).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(*b).name() << endl;
    cout << typeid(d).name() << endl;
    return 0;
}
Wynik:
i
A24_i
Ss
P4Base
4Base
7Derived

24 listopada 2013

[C++11] Budowaniu szablonów

Szablony i ich specjalizacje powinny być deklarowane w tym samym pliku nagłówkowym. Na początku powinny wystąpić wszystkie szablony ogólne, a następnie ich specjalizacje. Możemy częściowo wyspecjalizować tylko klasę. Nie można częściowo wyspecjalizować funkcji szablonowej [1].

Wewnątrz klasy szablonowej kompilator traktuje referencję do tego samego szablonu tak jakby był podany argument dla tego szablonu.
#include <iostream>
using namespace std;

template <typename T>
struct Single {
    Single& me_one() {
        return *this;
    }
    Single<T>& me_two() {
        return *this;
    }
    std::string show() {
        return "chain call";
    }
};

int main() {
    Single<int> s;
    cout << s.me_one().me_two().me_two().show() << endl;
    return 0;
}
Wynik:
chain call
W nowym standardzie, możemy uczynić typ parametryczny przyjacielem klasy.
#include <iostream>
using namespace std;

template <typename Type>
struct Bar {
    friend Type;
protected:
    std::string show() {
        return "protected show()";
    }
};

struct FriendType {
    void run(Bar<FriendType>& b) {
        cout << b.show() << endl;
    }
};

int main() {
    FriendType fry;
    Bar<FriendType> bar;
    fry.run(bar);
    return 0;
}
Wynik:
protected show()
Kompilator domyślnie zakłada że nazwa do której się odwołujemy przez operator zakresu (namespace) nigdy nie jest typem dlatego w takich przypadkach należy używać słowa typename.
template <typename T>
typename T::value_type fun(const T& c) {
    return c.res();
}
Wczesne wersje standardu dopuszczały domyślne parametry tylko dla szablonów klasy, w nowym standardzie, można stosować je także dla funkcji.
#include <iostream>
using namespace std;

template <typename T, typename F = less<T> >
int cmp(const T& a, const T&b) {
    F func = F();
    return func(a, b);
}

int main() {
    cout << cmp(1, 3) << endl;
    cout << cmp<int, greater<int>>(1, 3) << endl;
    return 0;
}
Wynik:
1
0
W dużych systemach, koszt inicjowania tego samego szablonu w wielu plikach, może być bardzo duży. Nowy standard pozwala uniknąć tego narzutu dzięki "explicit instantiation" ~ jednoznaczna konkretyzacja. Kiedy kompilator napotka deklarację szablonu jako extern, nie wygeneruje kodu dla tej konkretyzacji w danym pliku - taka deklaracja obiecuje, że gdzieś w programie będzie użyta non-extern konkretyzacja. Może być kilka deklaracji typu extern, ale zawsze musi być jedna definicja dla tej konkretyzacji.
// kompilator nie wygeneruje kodu w tym pliku
extern template class Blob<string>;
// kod tej szablonowej metody zostanie wygenerowany w obecnym pliku .o
template int compare(const int&, const int&);

23 listopada 2013

python(3) - mock-i w testach jednostkowych

Python - czasami dziwie się jak coś z tak chujową dokumentacją może istnieć, no ale ... gdyby problemy nie istniały nie było by czego rozwiązywać. Swoje eksperymenty oparłem na tym linku:
Bawiłem się jedynie MagicMock-iem, chociaż w bibliotece istnieje coś takiego jak Mock. Poniżej trzy, testy do trzech metod, których przetestowanie sprawiło mi problemy. Na początku ważna kwestia, MagicMock jest klasą, więc tworząc obiekt mock-a, należy pamiętać o nawiasach, aby wywołać konstruktor! Za pomocą parametru spec, wskazujemy też klasę, z które zaczerpnięty zostanie interfejs mock-owanej klasy.

Pierwszy z testów (test_show), miał wykazać sekwencyjne zawołanie metody Deciratir.rich(). Robi się to za pomocą dziwnego obiektu call, którego nasyca się atrybutami z jakimi zostanie wywołana mock-owana metoda. Inna kwestia to wartość zwracana. Za pomocą pola return_value, można ustalić jaka wartość będzie zawsze zwracana z mocka.

Drugi test, pokazuje w działaniu jedną z metod (asercji), dostarczoną przez bibliotekę. Tutaj oczekujemy, że metoda zostanie zawołana tylko raz z określonym parametrem (assert_called_once_with).

Trzeci test, również bada, czy mock-i zostały zawołane z określonymi parametrami, ale tym razem, każdy z nich zwraca inną wartość, aby przetestować bardzo specyficzną ścieżkę wykonania programu. Służy temu pole side_effect, z którego pobierane są kolejne zwracane wartości (można też podobna włożyć tam metody, które zostaną zawołane).
#!/usr/bin/env python3
# python -m unittest discover --pattern=test_unittest.py

import unittest
from unittest.mock import MagicMock
from unittest.mock import call

class TestPrinter(unittest.TestCase):
    def setUp(self):
        self.decorMock = MagicMock(spec=Decorator, name='decorator')()

    def test_show(self):
        self.decorMock.rich.return_value = True

        sut = Printer(self.decorMock)
        sut.show('asdf')
        expected = [call.decorMock.attribute.rich('asdf'),
                    call.decorMock.attribute.rich('xxx')]
        self.assertTrue(self.decorMock.rich.mock_calls == expected)

    def test_show_once(self):
        sut = Printer(self.decorMock)
        sut.show_once()
        self.decorMock.rich.assert_called_once_with('once')

    def test_show_comlicated(self):
        self.decorMock.rich.side_effect = [False, True]

        sut = Printer(self.decorMock)
        self.assertEqual(sut.show_complicated(), 2)
        expected = [call.decorMock.attribute.rich('a'),
                    call.decorMock.attribute.rich('b')]
        self.assertTrue(self.decorMock.rich.mock_calls == expected)

class Decorator():
    def rich(self, descr):
        raise Exception()

class Printer():
    def __init__(self, decorator):
        self._decorator = decorator

    def show(self, descr):
        self._decorator.rich(descr)
        if self._decorator.rich('xxx'):
            return True
        return False

    def show_once(self):
        self._decorator.rich('once')

    def show_complicated(self):
        if self._decorator.rich('a'):
            return 1
        if self._decorator.rich('b'):
            return 2
        return 0
Z otwartych kwestii, wciąż nie wiem jak testować dowolne parametry przekazywane do mock-a. Testowanie biblioteki do testów trwa nadal.

17 listopada 2013

[C++11] Przeciążenia operatorów

Zbiór notatek które zebrałem studiując tematykę operatorów po lekturze "C++ Primer". Najczęściej przeciążanym (overload) operatorem, jest chyba operator nawiasowy () który stosuje się w celu tworzenia funktorów. C++11 sprawi, że w jego miejsce częściej będzie pojawiać się lambda. W wielu przypadkach nadal, warto korzystać z obiektów funkcyjnych dostarczonych wraz z biblioteką standardową (pozytywnie wypowiadał się na ten temat także Stephan T. Lavavej na GoingNative 2013 - Don’t Help the Compiler). Nie tylko potrafią być krótsze od lambd, ale potrafią też poprawnie pracować ze wskaźnikami.

Kiedy tego nie robić?

Przeciążenie (overload) operatora ma tylko sens, jeżeli programista nie będzie zaskoczony jego działaniem.
Standard nie gwarantuje w jakiej kolejności będą wołane operandy. Np. dla f() + g(), nie wiemy, która z funkcji zostanie zawołana jako pierwsza. Mamy za to pewność że priorytety operatorów będą zachowane (czyli np. mnożenie będzie przed dodawaniem) [C++Prime, s. 138].
Nie należy przeciążać operatora kropki (.), pobrania adresu (&), logicznego AND (&&) oraz logicznego OR (||).
#include <iostream>

using namespace std;

struct Num {
    Num(int v) : value(v) { }
    Num() : Num(0) { }

    int value;
};

Num operator+(const Num& first, const Num& second) {
    return Num(first.value + second.value);
}

Num operator*(const Num& first, const Num& second) {
    return Num(first.value * second.value);
}

int main()
{
    Num a(2);
    Num b(2);
    Num c(2);

    cout << (a + b).value << endl;
    cout << (a * b).value << endl;
    cout << (a * b + c).value << endl;
    cout << (a + b * c).value << endl;
}
Wynik:
4
4
6
6

Gdzie tworzyć deklaracje?

Kiedy już decydujemy się na przeciążenie operatora, stajemy przed dylematem, czy stworzyć go jako element składowy klasy, czy jako funkcję poza klasą. Pomocne mogą być poniższe wskazówki:
  • operatora przypisania (=), nawisu kwadratowego ([]), zawołania (()) oraz strzałki (->) muszą być zdefiniowane jako składniki klasy
  • operatory mieszane z przypisaniem (+=, -=, *=, /= itp.) generalnie powinny być składowymi klasy, ale w przeciwieństwie do samego operatora przypisania (=) nie jest to wymagane
  • operatory które zmieniają stan obiektu, albo są z nim ściśle powiązane np. inkrementacja (++), dekrementacja (--), dereferencja (*) zazwyczaj powinny być składowymi klasy
  • operatory symetryczne (takie które mogą konwertować którykolwiek z operandów) tj. arytmetyczne (+, -), równości (==), relacji (<, >, <=, <=) i bitowe (|, &, ^, <<, >>), zazwyczaj powinny być definiowane jako funkcje poza klasą

Szczegóły dla konkretnych operatorów

Operatory I/O - wejścia, wyjścia - (<<, >>), powinny być funkcjami poza klasą i powinny drukować zawartość z bardzo minimalnym formatowaniem. Jako, że czasami muszą mieć dostęp do niepublicznych danych, powinny być zadeklarowane jako przyjaciele (friend) klasy. Operator wejściowy powinien radzić sobie z sytuacją, gdy "wejście" zawiedzie, operator wyjściowy generalnie się tym nie przejmuje.

Dla operatora nawiasu kwadratowego ([]) warto zrobić wersję const oraz non-const

Dla operatorów inkrementacji (++) i dekrementacji (--) istnieją dwie wersje: prefiksowa i postfiksowa. Wersja postfiksowa dla rozróżnienia bierze jako argument dodatkowy nieużywany parametr typu int, kompilator wstawia tam zero.
#include <iostream>
using namespace std;

struct Counter {
    double d;
    Counter() : d(0.12) { }
    Counter operator++() {
        d += 1.0;
        cout << "prefix:  ++obj" << endl;
        return *this;
    }

    Counter operator++(int) {
        Counter tmp = *this;
        d += 1.0;
        cout << "postfix: obj++" << endl;
        return tmp;
    }
};

int main() {
    Counter c;
    c++;
    ++c;
}
Wynik:
postfix: obj++
prefix:  ++obj

Konwersje typów

Konwersje z jednego typu na drugi mogą być bardzo mylące. Czasami lepiej stworzyć odpowiednią metodą, która lepiej poinformuje nas o intencji danej konwersji. Operatory konwersji powinny być składowymi klasy, nie powinny określić typu zwracanego i posiadać pustą listą parametrów. Funkcja zazwyczaj powinna być const-owa.

We wcześniejszej wersji języka konwersja na typ bool była problematyczna, ponieważ bool jest typem arytmetycznym. Obiekt klasy która pozwala na konwersję na bool, mógł zostać użyty we wszystkich miejscach, gdzie wymagany jest typ arytmetyczny. Gdyby std::cin dało się konwertować na typ bool, możliwa była by operacja "std::cin << 34" - w rezultacie doszło by do przesunięcia bitowego (bool zostałby jeszcze skonwertowany na int).

Nowy standard wprowadza konwersje explicit. Powinna się ona ograniczyć raczej tylko do bool i zazwyczaj z intencją sprawdzania wyniku w jakimś warunku.
Jeżeli konwersja jest explicit, możemy jej używać ale tylko z rzutowaniem. Wyjątkiem jest niejawne (implicit) korzystanie z konwersji dla:
  • warunków w if, while oraz do-while
  • warunków w for
  • operatorów dla logicznego NOT (!), OR (||) oraz AND (&&)
  • warunków dla ?:
#include <iostream>
using namespace std;

struct SmallInt {
    double val;
    SmallInt(double v) : val(v) { }

    explicit operator int() {
        return val;
    }

    explicit operator bool() {
        return val > 3.0;
    }
};

int main() {
    SmallInt si(3.14);
//  cout << si + 1 << endl; // ERROR wymagana jest niejawna konwersja,
                            // ale operator rzutowania na int jest explicit
    cout << static_cast<int>(si) + 1 << endl;

    if (si)
        cout << "Bigger than PI" << endl;

    return 0;
}
Wynik:
4
Bigger than PI

12 listopada 2013

include-what-you-use, podejście drugie

W sierpniu include-what-you-use doczekał się aktualizacji, a ja postanowiłem podjąć kolejną próbę kompilacji tego narzędzia. Wszystko wykonałem jak za ostatnim razem. Tym razem zaczęło działać! Dodatkowo zapisałem zmiany w llvm/tools/clang/tools/CMakeLists.txt ...
add_subdirectory(diagtool)
add_subdirectory(driver)
add_subdirectory(include-what-you-use)
if(CLANG_ENABLE_REWRITER)
  add_subdirectory(clang-format)
endif()

if(CLANG_ENABLE_ARCMT)
  add_subdirectory(libclang)
  add_subdirectory(c-index-test)
  add_subdirectory(arcmt-test)
  add_subdirectory(c-arcmt-test)
endif()
if(CLANG_ENABLE_STATIC_ANALYZER)
  add_subdirectory(clang-check)
endif()

# We support checking out the clang-tools-extra repository into the 'extra' ...
add_llvm_external_project(clang-tools-extra extra)
... oraz llvm/tools/clang/tools/Makefile
CLANG_LEVEL := ..

include $(CLANG_LEVEL)/../../Makefile.config

DIRS := include-what-you-use
PARALLEL_DIRS := driver diagtool

ifeq ($(ENABLE_CLANG_REWRITER),1)
  PARALLEL_DIRS += clang-format
endif

ifeq ($(ENABLE_CLANG_STATIC_ANALYZER), 1)
  PARALLEL_DIRS += clang-check
endif

ifeq ($(ENABLE_CLANG_ARCMT), 1)
  DIRS += libclang c-index-test c-arcmt-test
  PARALLEL_DIRS += arcmt-test
endif

# Recurse into the extra repository of tools if present.
OPTIONAL_PARALLEL_DIRS := extra

ifeq ($(BUILD_CLANG_ONLY),YES)
  DIRS := libclang c-index-test include-what-you-use
  PARALLEL_DIRS := driver
  OPTIONAL_PARALLEL_DIRS :=
endif

include $(CLANG_LEVEL)/Makefile
Poniżej plik, z którym eksperymentowałem.
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <boost/optional.hpp>

using namespace std;

int main()
{
    cout << "Hello World!" << endl;
    return 0;
}
Niestety nie udało mi się zmusić CMake, aby wygenerował dla mnie odpowiedni plik Makefile z ustawionym include-what-you-use jako kompilator.
Najpierw próbowałem ustawić CMAKE_CXX_COMPILER w CMakeLists.txt (set dla CMAKE_CXX_COMPILER musi znaleźć się przed project!). Trzeba było też wyczyścić cały projekt (został kod i CMakeLists.txt) i zrestartować QtCreator-a, żeby pojawił się jakiś efekt. CMake poskarżył się tylko, że tym się nie da kompilować.
set(CMAKE_CXX_COMPILER "~/poligon/build/Debug+Asserts/bin/include-what-you-use")
project(include_test)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
Drugie podejście z linii komend, efekt niestety taki sam.
cmake CMakeLists.txt \
  -DCMAKE_CXX_COMPILER="~/poligon/build/Debug+Asserts/bin/include-what-you-use"
Skończyło się na własnej wersji Makefile.
make -k CXX=~/poligon/build/Debug+Asserts/bin/include-what-you-use
A oto wynik.
main.cpp should add these lines:

main.cpp should remove these lines:
- #include <stdio.h>  // lines 3-3
- #include <boost/optional.hpp>  // lines 4-4
- #include <cstring>  // lines 2-2

The full include-list for main.cpp:
#include <iostream>                     // for operator<<, basic_ostream, etc
---
make: *** [main] Error 1

3 listopada 2013

[C++11] Współbieżność

Pierwsze podejście do współbieżności, wprowadzonej do biblioteki standardowej wraz z nowym standardem.
#include <thread>
#include <iostream>

void hello()
{
    std::cout << "Hello World!" << std::endl;
}

int main()
{
    std::thread t(hello);
    t.join();
    return 0;
}
Było trochę kłopotów przy próbie kompilacji (gcc - 4.7.3, clang - 3.2-1). gcc potrzebuje dodatkowej flagi w postaci pthread, natomiast clang w wersji 3.2 jeszcze nie radzi sobie z wątkami, ale i na to znalazł się sposób.
Budowanie z linii poleceń:
$ g++ -pthread --std=c++11 main.cpp
$ clang++ -pthread --std=c++11 \
     -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \
     -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \
     -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \
     -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 main.cpp
Poniżej ustawienie dla CMakeList.txt (cmake):
project(thread_hello)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")

28 października 2013

Going Native 2013

Zakończyłem oglądanie udostępnionych wykładów z GoingNative 2013. Pojawiło się na niej kilka slajdów z nowościami z C++14, ale żadne wykład nie był mu w całości zadedykowany. Z najfajniejszych (moim zdaniem) wykładów warto wymienić.
  • Writing Quick Code in C++, Quickly - sztuczki z optymalizacją kodu w bibliotece folly rozwijanej przez Facebook-a. Mam nadzieje, że nie będę musiał się nigdy kłopotać takimi szczegółami, nie mówiąc o przykładach, które nie do końca rozumiem. Kilka wniosków z prezentacji
    • Inżynierowie którzy znają architekturę swojego sprzętu piszą lepszy kod
    • "Mierz wszystko!". Aby sprawdzić wydajność programu wynikowego, trzeba badać go z każdej strony: czas wykonani, zużycie pamięci, zużycie energii, ...
    • Jeżeli dobrze zrozumiałem, czas kompilacji kodu może zostać skrócony, przez stosowanie final tam gdzie to możliwe. Niestety gcc i clang nadal nad tym pracują.
  • Don’t Help the Compiler - jak dla mnie tytuł troszkę mylący bo wykład opowiada o najczęstszych błędach jakie popełniają programiści. Garść notatek z prezentacji:
    • Jeżeli zwracamy wynik przez wartość, stosowanie const może wyłączyć move semantic. Nie korzystać z const dla wartości.
    • Wartości zwracane przez rvalue lub rvalue reference np. string& i string&& są tym samym. Czyli referencją do wartości.
    • Nie korzystać z move(), dla obiektów lokalnych które chcemy zwrócić. Jeżeli dobrze rozumiem, gdy zwracamy lokalną zmienną mogą zadziać się dwie rzeczy. Albo kompilator przeniesie (zoptymalizuje) konstrukcje tego obiektu do kodu wywołującego, albo zadziała move semantic (nie trzeba mu pomagać używając move).
    • Czasami korzystanie ze standardowych funktorów z STL-a tworzy bardziej elegancki kod, niż lambda np. std::plus<> itp.
  • An Effective C++11/14 Sampler - dużo ciekawych informacji na temat wątków oraz std::move i std::forward - sam jeszcze eksperymentuje z tym więc będzie osobny wpis.
    • Jeżeli chcemy szybkości (w postaci move semantic), przekazując przez wartość należy zrezygnować z const. To samo dotyczy zwracania. const wymusza kopiowanie!
    • Warto stosować noexcept, gdy to tylko możliwe generowany jest wtedy bardziej zoptymalizowany kod.
  • The Care and Feeding of C++’s Dragons - bardzo ciekawy wykład na temat rozszerzeń do clang-a mających na celu ułatwienie pracy programistom. Poeksperymentuje jak tylko uda się przekompilować clang-a.
  • rand() Considered Harmful - przestroga przed stosowaniem rand() z biblioteki C. Do C++11 trafiła biblioteka służąca do generowanie wartości losowych, bardzo podobna do Boost.Random.
  • C++ Seasoning - jak znajomość algorytmów standardowych (STL), może usprawnić refactoring kodu.
  • Inheritance Is The Base Class of Evil - trudne do zakumania, ale przykład działa na wyobraźnie. Może będzie kiedyś czas, by nad tym spokojnie pokontemplować. 

27 października 2013

[C++Now] Interactive, Introspected C++ at CERN

Fajny wykład (z konferencji C++Now 2013) na temat pracy w CERN, oraz narzędzie/oprogramowania jakie się tam wytwarza: iterpreter C++ (projekt cling), oraz bibliotekę ROOT na potrzeby fizyków.

6 października 2013

[Win] Redmond Path - edycja ścieżek przeszukiwania

Kolega pokazał mi bardzo fajne narzędzie, pozwalające na edycję ścieżek przeszukiwania w Windows. Wraz z kolejnymi wersjami systemu, problem miniaturowego okienka, w którym można tego dokonać jakoś nie jest rozwiązywany. Redmond Path jest tutaj wspaniałym udogodnieniem:

5 października 2013

[C++] Debugowanie metaprogramów - Templight 2.0

Na tegorocznej (2013) konferencji C++Now, pojawił się bardzo interesujący wykład na temat debugowania/profilowania metaprogramów z wykorzystaniem Templight 2.0 (patch-a na kompilator clang).
Strona projektu:
Nakładania patch-a jest proste, aczkolwiek kompilacja trochę trwała. Na samym początku miałem problem związany z błędem podczas linkowania clang-a. Rozwiązaniem okazało się zwiększenie pamięci do 2GB dla mojej wirtualnej maszyny (VritulBox). Poniżej wszystkie kroki (skopiowane ze strony projektu).
svn co http://llvm.org/svn/llvm-project/llvm/branches/release_32 llvm

cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/branches/release_32 clang
cd ../..

cd llvm/tools/clang/tools
svn co http://llvm.org/svn/llvm-project/clang-tools-extra/branches/release_32 extra
cd ../../../..

cd llvm/projects
svn co http://llvm.org/svn/llvm-project/compiler-rt/branches/release_32 compiler-rt
cd ../..

cd llvm/tools/clang
patch -p0 -i ~/templight.diff
cd ../../..

mkdir build (for building without polluting the source dir)
cd build
../llvm/configure
make
Aby skompilować narzędzie (wykorzystuje Qt oraz graphviz) trzeba było doinstalować kilka paczek:
sudo apt-get install graphviz
sudo apt-get install libgraphviz-dev
sudo apt-get install qt-sdk

# Ścieżki do bibliotek
export QTDIR=/usr/share/qt4
export MANPATH=$QTDIR/doc/man:$MANPATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
PATH=$QTDIR/bin:$PATH

# Budowanie
cd ProfileDataViewer
qmake
make
Jeżeli w programie korzystamy z szablonów np. dostarczonych przez bibliotekę standardową wyników może być całkiem sporo (może być tu przydatny breakpoint - program Templar). Na początku pojawił się także problem z brakiem widoczności "bits/c++config.h" przez mojego clang-a (ponieważ korzystałem z iostream). Rozwiązaniem było dodanie dodatkowej flagi dla kompilatora:
Proces kompilacji:
# Problem
~/poligon/build/Debug+Asserts/bin/clang++ -templight main.cpp
/usr/lib/gcc/i686-linux-gnu/4.7/../../../../include/c++/4.7/iostream:38:10: fatal error: 'bits/c++config.h' file not found

# Fix
~/poligon/build/Debug+Asserts/bin/clang++ -I/usr/include/i386-linux-gnu/c++/4.7/ -templight main.cpp
Kompilator wygeneruje dla nas plik xml, którym należy nakarmić jeden z programów go analizujących np. Templar (debugger). Przykład, prosty program na obliczanie silni - 5!.
template <int N>
struct factorial
{
    enum { value = N * factorial<N-1>::value };
};

template <>
struct factorial<1>
{
    enum { value = 1 };
};

template <>
struct factorial<0>
{
    enum { value = 1 };
};

int main()
{
    factorial<5>::value;
    return 0;
}
A poniżej graf wygenerowany podczas analizy. Break na factorial<3>::value.

28 września 2013

[gdb] - debugowanie wyjątków w C++

Kiedy wyjątek zostanie rzucony (i złapany), wszystkie zmienne na stosie zostaną zniszczone [link]. Może się to okazać kłopotliwe, jeżeli chcemy skorzystać z debuggera i odnaleźć przyczynę. GDB oferuje przydatną komendę "catch throw", która zatrzymuje program w momencie rzucenia wyjątku. W ten sposób można podglądnąć oryginalne zmienne na stosie.
#include <iostream>

void test() {
    int a = 5;
    throw std::exception();
}

int main() {
    test();
    return 0;
}
Program niespodziewanie zakończył swoje działanie.
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
The program has unexpectedly finished.
Deguggowanie za pomocą GDB.
$ g++ -g main.cpp
$ gdb a.out

(gdb) catch throw
Catchpoint 1 (throw)
(gdb) r
Starting program: /home/beru/cpp_throw_test/a.out 
Catchpoint 1 (exception thrown), 0xb7f247c0 in __cxa_throw ()
   from /usr/lib/i386-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0xb7f247c0 in __cxa_throw () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#1  0x080486f8 in test () at main.cpp:5
#2  0x08048703 in main () at main.cpp:9
(gdb) f 1
#1  0x080486f8 in test () at main.cpp:5
5     throw std::exception();
(gdb) p a
$1 = 5

24 września 2013

[C++] Usuwanie elementów z mapy o zadanej wartości

Problem nad, którym od dawna się zastanawiałem, a mianowicie jak najlepiej usunąć elementy o zadanej wartości z mapy. Miałem nadzieje na wykorzystanie, jakiegoś wbudowanego w standard mechanizmu/algorytmu, albo chociaż czegoś z biblioteki boost - niestety. Wyniki poszukiwań poniżej.

Na pierwszy ogień poszedł std::remove_if(), niestety problemem jest tu w jaki sposób mapy przechowują swoje elementy. std::map<K,V>::value_type jest parą std::pair<const K, V>. std::remove_if() przesuwa elementy do usunięcia w taki sposób, że zostają one nadpisane. Ponieważ nie można przypisywać do const, std::remove_if() nie nadaje się do zastosowania na mapach. Wykorzystałem go jednak w zwykłej metodzie nib::erase_if() [linia 21], gdyż świetnie nadaje się dla zwykłych kontenerów. Wątek na stackoveflow, który traktuje o tym problemie:
Z tego co udało mi się wyszukać innym, częstym rozwiązaniem jest skorzystanie z std::remove_copy_if(). Tym razem wszystkie elementy, które nie spełniają naszego kryterium są kopiowane do nowej mapy. Jeżeli mapa jest sporych rozmiarów, a elementów do usunięcia jest stosunkowo dużo, to minusem rozwiązaniem będzie niepotrzebne chwilowe zwiększenie zapotrzebowanie na pamięć. Działanie tego algorytmu zostało zawarte w metodzie nib_test::erase_if() [linia 47].

Ostatnie i najbardziej preferowane rozwiązanie - nib::erase_if [linia 27], to napisanie własnego algorytmu, który podejmie się tego zadania. Szkoda, że nie udało się niczego takiego zaadoptować (albo jeszcze nie znalazłem) w bibliotece standardowej albo w innych popularnych bibliotekach (np. boost).
Po odnalezieniu elementów o zadanej wartości zostaną one usunięty za pomocą metody std::map::erase(). Dobra wiadomość jest taka, że std::map::erase(), unieważnia jedynie referencje i iteratory do usuwanego elementu, pozostałe referencje i iteratory w mapie są nadal ważne: Dwa wątki traktujące o tym rozwiązaniu:
Jak informuje autor, jednego z rozwiązań, w przypadku skorzystania z zapisu "erase(it++)", standard gwarantuje, że wszystkie wyrażenia argumentów, będą wykonane przed wywołaniem funkcji. Prosta inkrementacja zostanie wykonany przed wywołaniem funkcji std::map::erase(), a do niej zostanie przekazana wartość jeszcze niezainkrementowana.
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>

template <typename Key, typename Value>
std::ostream& operator<<(std::ostream& out, const std::pair<Key, Value>& p) {
    return out << "[" << p.first << "]" << "=" << p.second;
}

template <typename Container>
void print_container(const Container& container) {
    for(const auto& v : container)
        std::cout << v << std::endl;
}

namespace nib
{

template <typename Container, typename Predicate>
void erase_if(Container& container, const Predicate& predicate) {
    container.erase(std::remove_if(begin(container), end(container), predicate),
                    end(container));
}

template <typename Key, typename Value, typename Predicate>
void erase_if(std::map<Key, Value>& dict, const Predicate& predicate) {
    auto it = begin(dict);
    while(it != end(dict)) {
        if (predicate(*it)) {
            // Standard zapewnia, ze it++ zostanie obliczone, zanim samo "it"
            // zostanie przekazane do funkcji
            dict.erase(it++);
        }
        else {
            ++it;
        }
    }
}

} // namespace nib

namespace nib_test
{

template <typename Key, typename Value, typename Predicate>
void erase_if(std::map<Key, Value>& dict, const Predicate& predicate) {
    typedef typename std::remove_reference<decltype(dict)>::type Map;
    Map tmp;
    std::remove_copy_if(begin(dict), end(dict),
                        std::inserter(tmp, begin(tmp)),
                        predicate);
    dict = tmp;
}

} // namespace nib_test

int main() {
    std::vector<int> vec { 1, 2, 1, 4, 1, 5 };
    auto val_to_erase = [] (int& v) { return v == 1; };
    nib::erase_if(vec, val_to_erase);
    print_container(vec);

    typedef std::map<int, std::string> Dict;
    Dict dict { {1, "a"}, {2, "b"}, {3, "c"}, {7, "b"} };

    auto val_to_erase_in_map = [] (typename Dict::value_type& v) { return v.second == "b"; };
    nib::erase_if(dict, val_to_erase_in_map);
//  nib_test::erase_if(dict, val_to_erase_in_map);
    print_container(dict);

    return 0;
}
Wyniki:
2
4
5
[1]=a
[3]=c
Aby się upewnić co do kosumpcji pamięci przez oba rozwiązania, przeprowadziłem prostą weryfikacją za pomocą valgrinda.
int main() {
    typedef std::map<int, std::string> Dict;
    Dict dict { {1, "a"}, {2, "b"}, {3, "c"}, {7, "b"} };

    for(int i = 0; i < 10000; ++i)
        dict.insert(std::make_pair(5000 + i, "x"));
//      dict.emplace(5000 + i, "x"); - Nie dziala w GCC 4.7!!!

    auto val_to_erase_in_map = [] (typename Dict::value_type& v) { return v.second == "b"; };
//  nib::erase_if(dict, val_to_erase_in_map);
    nib_test::erase_if(dict, val_to_erase_in_map);
    print_container(dict);

    return 0;
}
Wersja nib::erase_if(), odnotowała peak na poziomie 558272 bajtów, natomiast dla nib_test::erase_if() (korzystająca z std::remove_copy_if()) peak ten wynosił 874376 bajty.

5 września 2013

[C++11] std::shared_ptr vs std::make_shared

Od wielu osób, słyszałem o wyższości stosowania dedykowanych metod w celu tworzenia inteligentnych wskaźników. Nadszedł czas przyjrzeć się tym dwóm mechanizmom bliżej, jak zawsze na bazie własnych testów, by ze świadomością móc korzystać z ich dobrodziejstw.

Swoje przemyślenia oparłem na "C++ Primer" oraz na artykule Herba Shuttera:

Kilka punktów, które mogą okazać się pomocne w przyszłości.
  • std::unique_ptr powinien być zawsze preferowany przed std::shared_ptr
  • std::shared_ptr i std::unique_ptr powinno być wybierane, tylko gdy chcemy skorzystać z własnego deletera (std::make_shared tego nie umożliwia), albo gdy adaptujemy stary kod i chcemy zarządzać surowym wskaźnikiem.
  • W innych przypadkach powinno się korzystać z std::make_unique i std::make_shared.
Zalety:
  • Upraszcza to kod. W jednej instrukcji zawarte jest tworzenie inteligentnego wskaźnika i chowany jest new (std::shared_ptr + new), który może rzucać trudne do wykrycia wyjątki. std::make_shared nas przed tym chroni (w C++17 został zmieniony sposób ewaluacji argumentów funkcji i nie jest to już problemem).
  • std::make_shared daje istotne optymalizacyjne usprawnienia. std::shared_ptr jedynie tworzy wskaźnik na zasób którym ma zarządzać (który zostanie stworzony przez new) i nie wie, czy to co mu podlega zostało stworzone specjalnie dla niego, czy ma do czynienia z surowym wskaźnikiem. Zasób taki będzie najprawdopodobniej w innym bloku pamięci + kompilator jak zawsze doda kilka ekstra bajtów, przy alokowaniu.
Wady:
  • Nie testowałem, aczkolwiek ma to sens. Ponieważ std::make_shared stworzy obiekt, a także reference counters w jednym bloku pamięci, pamięć taka będzie zwolniona dopiero, gdy nie będzie już żadnych std::weak_ptr wskazujących na ten obiekt. Tworzenie obiektu za pomocą std::shared_ptr ma tu taką przewagę, że będzie mógł on zwolnić zasób, którym zarządza i pozostawić przy życiu jedynie reference counters dla std::weak_ptr. Jeżeli zarządzany obiekt będzie duży, może się to odbić na wydajności.
std::make_shared zatroszczy się o to by wszystko zostało stworzone po kolei (ładnie to ilustrują obrazki zamieszczone przez Herba Shutter na jego stronie).
Dla dużej ilości małych obiektów, może to istotne przyśpieszyć działanie programu, ponieważ zmniejsza się czas dostępu do cache procesora. Właśnie to chciałem przetestować w swoim teście.
#include <iostream>
#include <memory>
#include <boost/date_time/posix_time/posix_time.hpp>

using namespace boost::posix_time;

struct MyObject {
    MyObject(std::string n): name(n) { }
    std::string name;
};

void fun(const std::shared_ptr<MyObject> &sp) {
    if (sp->name == "xxx")
        std::cout << "xxx" << std::endl;
}

int main() {
    const ptime time_start = microsec_clock::local_time();

    for (int i = 0; i < 100000000; ++i) {
#ifdef TEST_SHARED_PTR
        fun(std::shared_ptr<MyObject>(new MyObject("shared")));
#else
        fun(std::make_shared<MyObject>("make_shared"));
#endif
    }

    const ptime time_stop = microsec_clock::local_time();
    std::cout << "Time: " << time_start - time_stop << std::endl;

    return 0;
}
Kompilacja.
$ g++ main.cpp -std=c++11 -O2 -DTEST_SHARED_PTR
Poniżej zestawienie wyników dla gcc i clang-a. Zrobiłem też testy bez użycia flag optymalizacyjnych (-O2) i co ciekawe wyniki były zupełnie odwrotne! Nie wynikałem już w przyczynę tego stanu rzeczy. Może kiedyś rozwikłam tą zagadkę.

3 września 2013

Lista pomocnych wtyczek do Firefoxa

Aby mi nie wyparowało, postanowiłem stworzyć sobie małą listę przydatnych wtyczek, które może nie ułatwiają codziennej pracy, ale na pewno są pomocne, w szczególnych zastosowaniach.

Dodatek pozwalający oszukać/ustawić wartość, document.referrer (JavaScript).
  • https://addons.mozilla.org/pl/firefox/addon/refcontrol/

  • Bardzo popularny dodatek. Pozwala testować JavaScript, przekopać się w poszukiwaniu interesujących treści na stronie itd.
  • https://addons.mozilla.org/pl/firefox/addon/firebug/

  • Jedna z kilku wtyczek, którą testowałem, ale tylko w tej doszedłem do tego jak można zaciągnąć film z Facebook-a.
  • https://addons.mozilla.org/pl/firefox/addon/netvideohunter-video-downloade/
  • 1 września 2013

    [C++11] Dynamiczna pamięć (new + inteligentne wskaźniki)

    Nowy standard, dostarczy kilka mechanizmów pozwalających lepiej radzić sobie z zarządzaniem obiektami w pamięci dynamicznej. Prócz nowości, opisałem kilka już istniejących mechanizmów, które zawsze wylatują mi z głowy.

    new


    Operator new, umożliwia nie tylko alokowanie pamięci pod nowo tworzone obiekty, ale również pod wskazany przez nas (wcześniej zaalokowany) obszar pamięci.
    #include <iostream>
    
    int main() {
        int int_in_memory = 5;
        std::cout << "Memory (val)  " << int_in_memory << std::endl;
        std::cout << "Memory (addr) " << &int_in_memory << std::endl;
    
        int *ptr = new (&int_in_memory) int(2);
        std::cout << "Ptr    (val)  " << *ptr << std::endl;
        std::cout << "Ptr    (addr) " << ptr << std::endl;
    
        return 0;
    }
    
    W takim przypadku, new zawsze zwróci ten sam adres, który został mu przekazany. Nie można łączyć tego rodzaju inicjalizacji z nothrow (wersja która nie rzuca wyjątku)
    Memory (val)  5
    Memory (addr) 0xbf9c26f8
    Ptr    (val)  2
    Ptr    (addr) 0xbf9c26f8
    
    Każda pamięć jawnie zaalokowana przez nas musi być później zwolniona. W przypadku tablic trzeba użyć specjalnej formy delete [], aby wywołać destruktory obiektów, które się w niej znajdują.
    #include <iostream>
    
    struct MyObject {
        MyObject(std::string n): name(n) { std::cout << "Constructor: " << name << std::endl; }
        ~MyObject() noexcept { std::cout << "Destructor:  " << name << std::endl; }
        std::string name;
    };
    
    int main() {
        MyObject *tab = new MyObject[3] { {"Elem1"},
                                          {"Elem2"},
                                          {"Elem3"} };
    
        delete tab;
    //  delete [] tab;
    
        return 0;
    }
    
    Jeżeli skorzystamy ze zwykłego delete, bez podania pustych nawiasów, zachowanie jest niezdefiniowane.
    Constructor: Elem1
    Constructor: Elem2
    Constructor: Elem3
    Destructor:  Elem1
    The program has unexpectedly finished.
    
    Nowy standard dodaje, wersje operatora new z nothrow i w razie wystąpienia błędu przy inicjalizacji pamięci zamiast wyjątku operator zwróci nullptr, aby poinformować nas o problemie.
    #include <iostream>
    #include <memory>
    
    int main() {
        try {
            int *ptr = new int[1000000000];
        }
        catch (std::bad_alloc& exception) {
            std::cout << "Exception: " << exception.what() << std::endl;
        }
    
        int *ptr = new (std::nothrow) int[1000000000];
        if (ptr == nullptr)
            std::cout << "Not allocated" << std::endl;
    
        return 0;
    }
    
    Poniżej wyniki działania programu, w pierwszej wersji zwracany jest wyjątek, w drugiej jesteśmy informowani przez zwrócenie nullptr.
    Exception: std::bad_alloc
    Not allocated
    
    Co ciekawe, rzadko można w kodzie zauważyć sytuacje, gdy programista próbuje przestrzec się przed tego typu zdarzeniami (blok try-catch). W Linuxie jest to związane z domyślnie włączonym mechanizmem "opportunistic memory allocation", który nie sprawdza, czy pamięć jest dostępna gdy próbujemy ją zaalokować. W momencie, gdy próbujemy się do niej odwołać, a w systemie jej zabraknie program zostaje zterminowany. Ustawienie można sprawdzić przez:
    cat /proc/sys/vm/overcommit_memory
    0
    

    smart pointers


    W standardzie pojawiły się nowe inteligentne wskaźniki, zaczerpnięte z biblioteki boost. Są to unique_ptr (zdaje się odpowiednik boost::scoped_ptr), shared_ptr oraz weak_ptr. Herb Shutter daje kilka porad, odnośnie tego jaki i kiedy je stosować.
    Można to podsumować w ten sposób. W nowoczesnym C++ zawsze powinno się używać inteligentnych wskaźników oraz surowych wskaźników nie posiadających prawa własności. unique_ptr powinno być preferowane nad shared_ptr (zawsze można będzie na niego przejść, jeżeli nasz zasób będzie musiał być współdzielony między komponentami o różnym czasie życia, albo gdy chcemy skorzystać z własnej metody do usunięcia zasobu z pamięci). Poniżej program, w którym m.in. shared_ptr, korzysta z funkcji "usuwającej" zasób z pamięci dostarczonej przez nas.
    #include <iostream>
    #include <memory>
    
    struct MyObject {
        MyObject(std::string n): name(n) { std::cout << "Constructor: " << name << std::endl; }
        ~MyObject() noexcept { std::cout << "Destructor:  " << name << std::endl; }
        std::string name;
    };
    
    void myDeleter(MyObject* p) {
        std::cout << "Deleter:     " << p->name << std::endl;
    }
    
    int main() {
        std::shared_ptr<MyObject> sha(new MyObject("shared"), myDeleter);
    
        std::unique_ptr<MyObject> uni1(new MyObject("unique"));
        std::unique_ptr<MyObject> uni2(uni1.release());
    
        std::cout << "Uni1 -> " << (uni1 ? "exist" : "not exist") << std::endl;
        std::cout << "Uni2 -> " << (uni2 ? "exist" : "not exist") << std::endl;
    
        auto store = std::make_shared<MyObject>("weak");
        std::weak_ptr<MyObject> wea(store);
    
        if (std::shared_ptr<MyObject> sp = wea.lock())
            std::cout << "Locked:      " << sp->name << std::endl;
    
        return 0;
    }
    
    A oto kolejność wywołania destruktorów dla dynamicznie stworzonych zasobów.
    Constructor: shared
    Constructor: unique
    Uni1 -> not exist
    Uni2 -> exist
    Constructor: weak
    Locked:      weak
    Destructor:  weak
    Destructor:  unique
    Deleter:     shared
    
    Shutter (i nie tylko) zaleca tworzenie inteligentnych wskaźników za pomocą metod make_*. Ale to postanowiłem przetestować sobie w innym wpisie.

    std::allocator


    Ostatnią rzeczą, którą testowałem są alokatory. Pozwalają nam one na odseparowanie procesu alokowania od konstruowania. W przykładzie poniżej, szykujemy pamięć pod trzy elementy typu MyObject. Najpierw pamięć jest alokowana, a my uzyskujemy wskaźnik pod adres, gdzie powinien być skonstruowany pierwszy z naszych obiektów. Następnie korzystają z metody construct(), oraz przesuwając wskaźnik następuje proces konstruowania. Aby zniszczyć obiekt, należy skorzystać z metody destroy().
    #include <iostream>
    #include <memory>
    
    
    struct MyObject {
        MyObject(std::string n): name(n) { std::cout << "Constructor: " << name << std::endl; }
        ~MyObject() noexcept { std::cout << "Destructor:  " << name << std::endl; }
        std::string name;
    };
    
    int main() {
        std::allocator<MyObject> alloc;
        std::cout << "Allocate" << std::endl;
        MyObject *ptr = alloc.allocate(3);
    
        std::cout << "Address:     " << ptr << std::endl;
        alloc.construct(ptr, "Elem1");
    
        ptr++;
        std::cout << "Address:     " << ptr << std::endl;
        alloc.construct(ptr, "Elem2");
    
        return 0;
    }
    
    Wynik działania.
    Allocate
    Address:     0x8b2a008
    Constructor: Elem1
    Address:     0x8b2a00c
    Constructor: Elem2
    

    27 lipca 2013

    Firefox - plugin na bazie FireBreath

    Szukam sposobu, na podpięcie się do przeglądarki i dobranie się do źródła wyświetlanej strony - co w konsekwencji jeszcze nie całkiem mi się nie udało. Padło na stworzenie rozszerzenia do przeglądarki. Firefox oferuje interfejs NPAPI (http://en.wikipedia.org/wiki/NPAPI) do takie celów. Projekt FireBreath, umożliwia tworzenie rozszerzeń na różne przeglądarki pod różne systemy. Instalacja frameworka jest bardzo przyjemna.
    #wymagana jest wcześniejsza instalacja libgtk
    sudo apt-get install libgtk2.0-dev
    
    git clone git://github.com/firebreath/FireBreath.git -b firebreath-1.7 firebreath-1.7
    cd firebreath-1.7
    # zaciągane są potrzebne biblioteki np. boost
    git submodule update --recursive --init
    
    # budowanie przykładów dostarczonych z projektem
    ./prepmake.sh examples
    cd buildex/
    make
    
    Autorzy dostarczają także kilka wideo tutoriali, który szybciej pozwalają zapoznać się z architekturą całego projektu.
    Mamy też do dyspozycji odpowiednie skrypty, umożliwiające stworzenie szkieletu pod nasz projekt. Autor nawet zaleca, by nie by tworzyć go zupełnie na zewnątrz, a firebreath podpiąć jako submoduł.
    cd firebreath-1.7
    ./fbgen.py
    # Plugin Name []: BeruPlugin
    # Plugin Identifier [BeruPlugin]: 
    # Plugin Prefix [BPL]: 
    # Plugin MIME type [application/x-beruplugin]: 
    # Plugin Description []: Beru Testing Plugin
    # Plugin has no UI [false]: 
    # Company Name []: NiegodziwyBeru
    # Company Identifier [NiegodziwyBeru]: 
    # Company Domain [niegodziwyberu.com]: nberu.blogspot.com         
    
    # Dobrą praktyk jest rozpoczęcie pracy od stworzenia repozytorium
    mv projects/BeruPlugin/ ../
    cd ../BeruPlugin/
    git init .
    git add .
    git commit -m"Beru Plugin first commit"
    
    # ustawiamy firebreath jako submodułu
    git submodule add git://github.com/firebreath/FireBreath.git firebreath
    git submodule update --init --recursive
    git commit -m"Added firebreath as submodule"
    
    # Budowanie
    ./firebreath/prepmake.sh . build/
    cd build
    make
    
    # Kopiowanie naszego rozszerzenie stamtąd zostanie 
    # automatycznie zaczytany przez Firefoxa
    cp bin/BeruPlugin/npBeruPlugin.so ~/.mozilla/plugins/
    
    Wciąż nie wiem, czy możliwe jest dobranie się całego źródła strony. Poniżej mały eksperyment pokazujący możliwości rozszerzenia , czyli pobranie adresu strony, z której został zawołany (http://www.firebreath.org/display/documentation/Tips+and+Tricks#TipsandTricks-GettingtheURLofthecurrentpage).
    void BeruPlugin::onPluginReady()
    {
        // When this is called, the BrowserHost is attached, the JSAPI object is
        // created, and we are ready to interact with the page and such.  The
        // PluginWindow may or may not have already fire the AttachedEvent at
        // this point.
        const std::string current_url = m_host->getDOMWindow()->getLocation();
        const std::string page_html = m_host->getDOMElement()->getInnerHTML();
    
        std::ofstream f;
        f.open("/home/beru/BeruPluginLog.txt", std::ios_base::out | std::ios_base::app);
        f << current_url << std::endl;
        if (page_html.empty())
            f << "Empty content " << std::endl;
        else
            f << "Content: " << page_html << std::endl;
        f << "-------------------------" << std::endl;
        f.close();
    }
    
    Ładowania rozszerzenia.
    <html>
    <head>
    <title>Test page for object beruplugin</title>
    </head>
    <object id="player" type="application/x-beruplugin" width="300" height="200">
    aaa<i>iii</i></object>
    <br/>
    <b>Hello world application/x-beruplugin</b>
    </html>
    
    I wynik działania:
    file:///home/beru/test.html
    Content: aaa<i>iii</i>
    -------------------------
    

    22 lipca 2013

    Trochę o Unit Testach

    Zbiorczy zestaw linków, traktujących o testach jednostkowych i trochę moich notatek.

    http://www.youtube.com/watch?v=RlfLCWKxHJ0
      Zastosowanie dependeny injection oraz prawo Demeter w testowaniu.

    http://www.youtube.com/watch?v=wEhu57pih5w
      Testy jednostkowy pozwalają nam wykryć błędy w działaniu małych komponentów. Dają przewagę nad testami systemowymi, pozwalając szybko zorientować się gdzie leży przyczyna błędu. Całościowe test, też mogą to wykazać, ale znacznie trudniej jest ustalić, gdzie leży usterka, albo co jest jej przyczyną.
      Mieszanie mechanizmu tworzenie obiektów z business logic sprawia, że bardzo trudno napisać dobry test. Nie można tworzyć obiektów w izolacji. Jedyne co można tworzyć to cały łańcuch zależnych od siebie obiektów. Nie mamy wtedy już do czynienia z testami jednostkowymi (np. test silnika), tylko z testami systemowymi (test działania całego samochodu).

    http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/
      Tutaj autor, przestawia TDD jako proces projektowania (i nie jest procesem testowania). TDD i testy jednostkowe pomagają dostarczyć komponenty oprogramowania, które indywidualnie zachowują się zgodnie z założeniami projektowymi. Jedynym odstępstwem, w którym testy jednostkowe naprawdę potrafią wykryć błędy jest proces refactoringu. Trochę inna wizja niż ta prezentowana na Google Talks.

    Ciekawy pattern do nazywania testów np. ProductPurchaseAction_IfStockIsZero_RendersOutOfStockView()
    • Subject
    • Scenario
    • Result

    http://www.exubero.com/junit/antipatterns.html
      Mowa o antywzorcach, jakie najczęściej pojawiają się podczas tworzenia testów jednostkowych. "Unit testing is the first of a long series of steps to verify that the code works correctly."

    30 czerwca 2013

    C++11 unordered containers

    Nowy zestaw kontenerów asocjacyjnych (unordered_set, unordered_multiset, unordered_map i unordered_multimap), do porównywania używają funkcji hash-ujących i operatora == dla klucza. Są najbardziej użyteczne, kiedy korzystamy z klucza, dla którego nie ma oczywistej relacji porządku. A także w aplikacjach, gdzie koszt przechowywania elementów w porządku nie jest istotny. Zazwyczaj jednak łatwiej i wydajniej jest korzystać ze zwykłych kontenerów asocjacyjnych.

    Kontenery (unordered_*) wkładają wszystkie elementy z takim samym hashem do tego samego kubełka. Wydajność działania zależy od funkcji hash-ującej, która powinna zawsze zwracać ten sam rezultat, dla tych samych argumentów. Idealnie, każda wartość, powinna trafić do innego kubełka. W przypadku wyszukiwania, najpierw odszukiwany jest kubełek, a później sekwencyjnie porównywane są jego elementy.

    Biblioteka dostarcza, kilka metod, które pokazują w jaki sposób zarządzane są nasze obiekty i w ten sposób, pozwalają dowiedzieć się gdzie wydajność może zostać poprawiona.
    #include <iostream>
    #include <unordered_map>
    
    using namespace std;
    
    int main()
    {
        const std::string key = "kilo";
        std::unordered_map<std::string, int> m = {
            {"delta", 7},
            {key, 99},
            {"hotel", 21},
            {"foxtrot", 2},
        };
    
        cout << "Ilosc kubelkow: "     << m.bucket_count() << endl;
        cout << "Max do skorzytania: " << m.max_bucket_count() << endl;
    
        const int bucket = m.bucket(key);
        cout << "Element '" << key << "' jest w kubelku: " << bucket << endl;
        cout << "Elementow w kupelku(" << bucket << "): " << m.bucket_size(bucket) << endl;
    
        cout << "Srednia liczba elem. na kubelek: " << m.load_factor() << endl;
        cout << "Sredni rozmiar kubelka jaki kontener bedzie chcial zachowac: " <<
                m.max_load_factor() << endl;
    
        for(const auto &val: m)
            cout << "map[" << val.first << "] = " << val.second << endl;
    
        return 0;
    }
    
    Dodatkowo mamy do dyspozycji metody rehash(n), która reorganizuje mapę tak, by liczba_kubełków >= n i liczba_kubełków > size/max_load_factor. Oraz metodę reserve(m), która sprawia, że mapa może przechowywać m elementów bez rehash-owania.
    Wyniki:
    Ilosc kubelkow: 11
    Max do skorzytania: 268435455
    
    Element 'kilo' jest w kubelku: 6
    Elementow w kupelku(6): 1
    
    Srednia liczba elem. na kubelek: 0.363636
    Sredni rozmiar kubelka jaki kontener bedzie chcial zachowac: 1
    
    map[foxtrot] = 2
    map[hotel] = 21
    map[kilo] = 99
    map[delta] = 7
    
    Domyślnie tego typu kontenery korzystają z operator ==, by porównać elementy, oraz z obiektu typu hash<key_type> by wygenerować hash. Można jednak wskazać własne metody, które się tym zajmą.
    #include <iostream>
    #include <unordered_map>
    
    using namespace std;
    
    struct Color {
        Color(int v) : value(v) {}
        string getValue() const {
            return "#" + std::to_string(value);
        }
    
    private:
        int value;
    };
    
    size_t hashColor(const Color& c) {
        cout << "hashColor " << c.getValue() << endl;
        return c.getValue().length();
    }
    
    bool equalOp(const Color &l, const Color &r) {
        cout << "equalOp " << l.getValue() << " " << r.getValue() << endl;
        return l.getValue() == r.getValue();
    }
    
    int main()
    {
        std::unordered_map<Color,
                           string,
                           decltype(hashColor)*,
                           decltype(equalOp)*> m(42, hashColor, equalOp);
    
        m[Color(1)] = "red";
        m[Color(2)] = "blue";
        m[Color(3)] = "green";
    
        return 0;
    }
    
    Wyniki:
    hashColor #1
    hashColor #2
    equalOp #2 #1
    hashColor #3
    equalOp #3 #2
    equalOp #3 #1
    
    Na koniec link, do artykułu wgryzającego się w szczegóły implementacyjne unordered_map:

    27 czerwca 2013

    [C++] Trochę o wirtualności (kiedy stosować wirtualne destruktory) i metodach szablonowa

    Szukając informacji na temat stosowania destruktorów wirtualnych natknąłem się na artykuł (http://www.gotw.ca/publications/mill18.htm) Herba Suttera, dotyczący stosowania tego mechanizmu i troszkę więcej. Poniżej moje notatki.

    Metody wirtualne bardzo rzadko powinny być publiczne (jeśli w ogóle). Publiczna wirtualna metoda, robi dwie rzeczy: specyfikuje interfejs i pokazuje detale implementacyjne - pozwalające na zmianę zachowania. Dobrze by było rozdzielić te dwie rzeczy. Sutter zaleca stosowania NVI (Non-virtual interface - wersja wzorca projektowego "metoda szblonowa" - definiuje szkielet algorytmu, który korzysta m.in. z operacji pierwotnych przedefiniowanych przez klasy pochodne). Korzyści: Interfejs staje się stabilny, a wszystkie modyfikacje oddelegowane zostają do klas pochodnych.
    • Porada #1: Preferuj tworzenie interfejsu jako nonvirutal, korzystająć z wzorca projektowego "metoda szablonowa"
    • Porada #2: Preferuj tworzenie metod wirtualnych jako prywatne. Metoda wirtualne stosuje się tylko by umożliwić modyfikacje działania.
    • Porada #3: Jeżeli klasa pochodna, potrzebuje wykonać metodę z klasy bazowej tylko wtedy może być zmieniona na protected.
    Klasa powinna mieć wirtualny destruktor, jeżeli zamierzamy niszczyć (polimorficznie) obiekt korzystając ze wskaźnika na klasę bazową.
    • Porada #4: Destruktor klasy bazowej powinien być publiczny i wirtualny, albo protected i niewirtualny (gdy nie stosujemy polimorfizmu).
    • O ile stosowanie publicznego wirtualnego destruktor do mnie jeszcze przemawia, to nie jestem w stanie w tej chwili znaleźć zastosowania dla protected nonvirtual.
    • Porada #5: Nie dziedzicz po klasach konkretnych - pozostaw klasy nie będące liśćmi jako abstrakcyjne.
    Oczywiście nietrudno znaleźć głosy, które nie do końca się z tym zgadzają. C++FAQ [23.4], zaleca stosowanie chronionych (protected) metod wirtualnych, ponieważ dla wielu deweloperów jest zaskoczeniem to, że prywatne wirtualne metody mogą zostać nadpisane. Marshall Cline, podaje też, dwa przypadki (C++FAQ [23.3]), dla których jego zdaniem wirtualne metody powinny być publiczne.

    Pierwsza jest odwróceniem, metody szablonowej tj. chcemy by główny algorytm, mógł być modyfikowany przez klasy pochodne, natomiast prymitywne metody pozostały stałe w klasie bazowej - nie muszą być one wirtualne, bo i tak klasa pochodna zdecyduje, czy będzie chciała z nich skorzystać, czy z czegoś innego (C++FAQ [23.2]).

    Ze zrozumieniem drugiej (C++FAQ [23.9]) mam niestety problem.

    23 czerwca 2013

    C++11 std::bind

    Poprzednie wersje std::bind1st, std::bind2nd, z powodu swoich ograniczeń w nowym standardzie zostały uznane za przestarzałe i w przyszłości mogą być usunięte. Nowa wersja czerpie dużo z boost::bind. Poniżej ogólna postać tej funkcji:
    auto nowFunkcja = std::bind(funkcja, argumenty);
    std::bind dobrze współgra z lambdami, a czasami można je stosować zamiennie. Jeżeli chcemy przekazać jakiś parametr jako referencję trzeba posłużyć się funkcją std::ref. Przykład:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    void in_range(std::ostream &os, int top, int bottom, int value) {
        if (value > bottom and value < top)
            os << "Value: " << value << std::endl;
    }
    
    int main()
    {
        std::vector<int> vec {1, 3, 2, 6, 2};
        int const myBottom = 2;
        int const myTop = 9;
    
        using namespace std::placeholders;
        auto fun = std::bind(in_range, std::ref(std::cout), myTop, myBottom, _1);
        std::for_each(begin(vec), end(vec), fun);
    
        return 0;
    }
    
    std::for_each karmi naszą funkcję (fun) jednym argumentem przechwytywanym przez std::placeholders::_1. Wynik:
    Value: 3
    Value: 6
    

    22 czerwca 2013

    C++11 lambda

    Funkcje lambda (nie posiadające nazwy) doczekały się swojej wersji w najnowszym standardzie [1]. Ich ogólna postać wygląda następująco:
    [capture list] (parameter list) -> return type { function body }
    • caputre list - najczęściej pusta, zawiera listę lokalnych zmiennych
    • parameter list - można ominąć. Wygląda tak jak w przypadku zwykłych funkcji. Nie ma tu czegoś takiego jak argumenty domyślne
    • return type - można ominąć. Wygląda tak jak w przypadku zwykłych funkcji, jednak cała deklaracja lambda musi korzystać z konstrukcji "trailing return"
    • function body - wygląda tak jak w przypadku zwykłych funkcji
    Lambda może używać lokalnych zmiennych pod warunkiem, że zostały zawarte w "capture list". Inne zmienne np. statyczne lub zdefiniowane poza główną funkcją, są normalnie dostępne. To jakie zmienne i w jaki sposób będą dostępne, informuje poniższa notacja.
    • [ ] - lista pusta, lambda nie może używać zmiennych z głównej funkcji
    • [name1, name2] - nazwy zmiennych oddzielone przecinkami, które będą wykorzystywane w lambdzie (domyślnie wartości są kopiowane), jeżeli jakaś nazwa zostanie poprzedzona &, lambda dostanie ją przez referencję
    • [&] - przed domniemanie (implicit), wszystkie zmienne z głównej funkcji będą dostępne przez referencję
    • [=] - przed domniemanie (implicit), wszystkie zmienne z głównej funkcji będą dostępne przez kopię. Jeżeli lambda jest wewnątrz metody to od C++20 jest to przestarzały zapis i powinien być zastąpiony przez [=, this]
    • [&, id1, id2] - zmienne id1, id2 będą dostępne przez kopię (nie poprzedzać żadnej &!!!), wszystkie inne będą domyślnie dostępne przez referencję
    • [=, &ref1, &ref2] - zmienne ref1 i ref2, będą dostępne przez referencję, wszystkie inne będą domyślnie dostępne przez kopię
    • [this], [&, this], [=, this], [&] - this (od C++17) będzie dostępne przez referencję.
    • [*this], [&, *this], [=, *this] - this (od C++17) będzie dostępne przez kopię
    Pierwszy przykład wykorzystania lambdy w algorytmie std::count_if.
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main()
    {
        vector<int> vec = {1, 4, 7, 2, 3};
        int evens = std::count_if(begin(vec), end(vec),
                                  [](int value) { return value % 2 == 0; });
        cout << "Parzystych: " << evens << endl;
    
        return 0;
    }
    
    Wynik:
    Parzystych: 2
    
    Drugi przykład trochę bardziej rozbudowany. Zliczane są elementy powyżej pewnego progu (threshold), a wynik zapisywany jest do zmiennej znajdującej się w głównej funkcji.
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main()
    {
        std::vector<int> vec = {1, 4, 7, 2, 3};
        int count_above = 0;
        int threshold = 3;
        std::for_each(begin(vec), end(vec),
                      [&, threshold](int &v) { if(v > threshold) count_above++; });
    
        std::cout << "Values above(" << threshold << "): " << count_above << std::endl;
    
        return 0;
    }
    
    Wynik:
    Values above(3): 2
    
    Jeżeli chcemy zmienić wartość przechwyconej zmiennej musimy po "parameter list" dodać słowo kluczowe mutable. Ale wartość ta będzie zmieniona tylko w obrębie samej lambdy! Poniżej link, z dobrym wyjaśnieniem tego mechanizmu:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main()
    {
        vector<int> vec = {1, 2, 3, 4};
        int count = 1;
        auto change_second = [=](int v) mutable {
            if (count == 2)
                v = 222;
            count++;
            return v;
        };
    
        cout << "count berfore: " << count << endl;
        std::transform(begin(vec), end(vec), begin(vec), change_second);
        cout << "count after:   " << count << endl;
    
        cout << "New vector values: ";
        for(int& v : vec)
            cout << v << " ";
    
        return 0;
    }
    
    Wynik (jak się zaczyna zabawę z lambdami, trochę zaskakujący):
    count berfore: 1
    count after:   1
    New vector values: 1 222 3 4 
    
    Standard nie definiuje w jaki sposób funkcja lambda zostanie zaimplementowana. Ta sama lambda, w dwóch implementacjach może być dwoma zupełnie innymi typami. Do przechowywania można wykorzystać std::function, wskaźnik do funkcji lub wykorzystać detekcję tupu za pomocą auto. I właśnie korzystanie z auto jest zalecanym sposobem. std::function, może wołać lambdę, za pośrednictwem funkcji wirtualnych, co wpływa na szybkość działania programu (mechanizm type-erasure - nie weryfikowałem tego).

    To czego zabrakło w C++11, a zostało naprawione w C++17, czyli obsługa this.
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct MyClass {
        MyClass() : vec{0, 0, 0} {
        }
        void update() {
            auto fun = [&, this]() { this->vec[1] = 9; };
            fun();
        }
    
        vector<int> vec;
    };
    
    int main()
    {
        MyClass obj;
        obj.update();
    
        for (const auto& v : obj.vec)
            cout << v << " ";
    }
    
    Wynik:
    0 9 0
    
    Oczywiście sprawa się na tym nie kończy. Istnieją duża bardziej skomplikowane przypadki np. zwracanie lambdy modyfikująca pola obiektu z metody tego obiektu. Dobry opis na tym blogu [2].

    2 czerwca 2013

    Ubuntu 13.04 - powolna praca na VirtualBox-ie

    Nowy system, nowe problemy, tym razem z Unity, które od wersji 12.10 występuje jedynie w wersji 3D. Cały system zaraz po uruchomieniu wydaj się działać niezwykle wolno. Oznacza to tyle, że na VirtualBoz-ie potrzebne są dodatkowe zabiegi, aby dało się "płynnie" pracować. Poniżej link, który opisuje całą procedurę:

    http://askubuntu.com/questions/207813/why-does-an-ubuntu-12-10-guest-in-virtualbox-run-very-very-slowly

    1 czerwca 2013

    C++11 - konwersja z liczby na string i odwrotnie

    Nowy standard wnosi kilka nowych metod, umożliwiających konwertowanie string-u na liczbę i odwrotnie. W zależności od tego na jaki typ liczbowy trzeba dokonać konwersji, mamy do dyspozycji kilka metod: stoi() (string na unsigned int), stol() (na typ long), stoll(), stod() itd. Są to odpowiedniki metod std::ato* (np. std::atoi()), które przyjmowały jako argument wskaźnik do tablicy znaków.

    Inny rodzaj konwersji dostarcza std::to_string(), który zapisuje liczbę w postaci stringu (nie ma flag formatujących). Więcej informacji: http://en.cppreference.com/w/cpp/string/basic_string/to_string.

    Co ciekawe, do standardu C++ została dołożona z C także funkcja std::snprintf(), nie byłem świadomy, że jej jeszcze tam nie było. Więcej info: http://en.cppreference.com/w/cpp/io/c/fprintf.
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <cstdio>
    
    int main()
    {
        const int i = std::stoi("567");
        std::cout << "int: " << i << std::endl;
    
        const std::string s = std::to_string(783);
        std::cout << "string: " << s << std::endl;
    
        const double d = 9.8765E4;
        constexpr int size_tab = 100;
        char tab[size_tab];
        std::snprintf(tab, size_tab, "%e", d);
        const std::string stab(tab);
        std::cout << "double: " << stab << std::endl;
    
        std::stringstream strstream;
        strstream << "double: " << std::scientific << d << std::endl;
        std::cout << strstream.str();
    
        return 0;
    }
    
    Wynik.
    int: 567
    string: 783
    double: 9.876500e+04
    double: 9.876500e+04