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")