C++Guns – RoboBlog blogging the bot

23.01.2018

C++ Guns - C++17 class template argument deduction user guide

Filed under: Allgemein — Tags: — Thomas @ 16:01

Es ist ja bekannt, dass der Compiler die Template Parameter von Funktionen selbst bestimmen kann.

template<typename T>
T func(T val) {
  return val;
}

auto i = func(1); // i int

Seit C++17 funktioniert das nun auch mit Klassen. Das Feature hierfür nennt sich __cpp_deduction_guides und wird seit GCC 7 unterstützt.
https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
Mehr noch, es können User Guides angegeben werden. Mit denen wird festgelegt, wie genau sich der Type der Klasse ableiten soll.
Hier ein einfaches Beispiel:

#include <type_traits>

#ifndef __cpp_deduction_guides
#error "need gcc 7"
#endif

template<class T>
struct A {
    using value_type = T;

    template<typename U, typename V>
    constexpr A(U, V) {
    }
};

// Das ist der  class template argument deduction user guide
// Der gemeinsame Type von U und V soll T von der Klasse A sein.
template<typename U, typename V>
A(U, V) -> A<std::common_type_t<U, V>>;


constexpr A x(1, 2.0);
// Der gemeinsame Type von int und double ist double
// Zur Compilezeit getestet!
static_assert(std::is_same_v<decltype(x)::value_type, double>);
// yeah

Sehr geiles feature.

19.01.2018

GIT specify private ssh key

Filed under: Allgemein — Tags: — Thomas @ 19:01

Das dumme an private keys ist, man kann sie nicht so einfach wie Passwörter überall mit hin nehmen. Schon garnicht zu anderen Rechner wo man selbst kein eigenen Useraccount hat. Und der vorhandene trusted user sein eigenen ssh key hat.
Bei ssh kann man leicht sein eigenes keyfile mit angeben. Bei GIT geht das auch, nur anders:

$ GIT_SSH_COMMAND='ssh -i key' git pull

Nur solle man tunlichts nicht vergessen sein keyfile wieder zu löschen. Sonst hat das ganze kein Sinn ;)

16.01.2018

C++ Guns: passing lambda to class - class template argument deduction

Filed under: Allgemein — Tags: — Thomas @ 12:01

auf http://en.cppreference.com/w/cpp/language/class_template_argument_deduction
gibts das halbe beispiel

// deduces Foo<T>, where T is the unique lambda type
 std::for_each(vi.begin(), vi.end(), Foo([&](int i) {...})); 

Ein compilierfähiges Beispiel wäre folgendes:

template<typename T>
struct Foo {
        Foo(T lambda) : lambda(lambda) {
        }


        void operator()(int y) {
                lambda(y);
        }

        T lambda;
};

int main() {
        std::vector<int> vi {1,2,3};
        std::for_each(vi.begin(), vi.end(), Foo( [&](int i) { std::cout << i << "\n";} ));
}

g++ --version
g++ (GCC) 7.1.0
g++ -std=c++17 lambdaFoo.cpp
$ ./a.out
1
2
3

Aber hat irgendjemand eine Idee, was man damit anfangen soll? Mir erschließt sich das gerade nicht.

11.01.2018

C++ Guns: C++ && Unicode

Filed under: Allgemein — Tags: — Thomas @ 09:01

Vorheriger Post Qt && Unicode

Heute möchste ich Unicode Zeichen mit C++ schreiben. Und zwar mit dem normalen 1 Byte std::string und std::ostream, also std::cout. Mit Qt war das einfach, wie im vorherigen Post zu lesen ist. Die Klasse QString nutz intern 2 Byte Zeichen und sonst kümmert sich Qt ja auch um alles.

Mit std C++ ist es eigentlich auch ganz einfach. Man darf sich nur nicht durch UTF8, UTF16, UTF32, Raw Strings, Kodierungen und Locale verwirren lassen.

Das Problem ist einfach gesagt, dass es viel mehr Zeichen auf der Welt gibt, als mit einem normalen, klassichen 1 Byte char dargestellt werden kann. Da passen nur 256 unterscheidliche Zeichen rein. Von denen werden für ASCII noch viel weniger benutzt. Um mehr Zeichen darzustellen, nutzt man einfach einen größeren Char Type. Da gibt es den wide char wchar_t, der aber nicht standardisiert ist und unter Windows und Linux wohl unterschiedlich viele Byte gelegt.

Die standardisierten Typen lauten char16_t und char32_t mit 2 und 4 Byte. Mit dem 4 Byte Char lassen sich ca. 2 bzw 4 Milliarden unterschiedliche Zeichen darstellen! Das sollte dann wohl reichen.
Leider bezahlt man dafür mit doppelten bzw. vierfachen Speicherplatzverbrauch, was für manche Anwendungen unmöglich ist. Noch dazu möchte man auch kompatibel zu anderen Code sein, der komplett auf std::string setzt. Und das ständige Unterscheiden zwischen std::string, std::wstring, std::u16string und std::u32string ist auch unmöglich.

Also hat man sich überlegt, ob nicht die gebräuchlichsten UTF-32 Zeichen als 1- oder 2 Byte gespeichert werden kann. So ist dann wohl UTF-16 und UTF-8 entstanden.
Konkret bedeutet dies, dass UTF-8 eine Kodierung mit variabler Breite ist. Häufig vorkommende Zeichen passen in 1 Byte, weniger oft verwendete Zeichen in 2 Byte und seltene Zeichen in 3 oder 4 Byte.

Damit ist, bist auf Umlaute, wieder alles gut. Umlaute müssen in UTF-8 als zwei 1 Byte Zeichen kodiert werden. Damit besteht der UTF-8 String u8"L\u00e4cheln!" zwar aus ach Unicode-Zeichen, aber da das zweite Zeichen ein kleines ä ist, welches in UTF-8 als zwei Bytes, nämlich 0xc3a4 kodiert ist, ist der komplette String 9 Zeichen lang!

Dies führt nun zu bestimmten Problemen, wenn Strings nach ihrer Länge ausgewertet werden. Oder wenn Zeichen in UTF-8 Strings gesucht werden. Aus diesem Grund benutzt Qt's QString Klasse wohl UTF-16.

Beispiele:

    std::string UTF8laecheln1 = "Lächeln!";
    std::string UTF8laecheln2 = u8"L\u00e4cheln!";
    std::cout << "locale    : " << UTF8laecheln1 << " size: " << UTF8laecheln1.size() << "\n";
    std::cout << "UTF-8     : " << UTF8laecheln2 << " size: " << UTF8laecheln2.size() << "\n";
    std::cout << u8"\u2581" << u8"\u2582" << u8"\u2583" << u8"\u2584" << u8"\u2585" << u8"\u2586" << u8"\u2587" << u8"\u2588";
locale    : Lächeln! size: 9
UTF-8     : Lächeln! size: 9
????????

Scheint als wäre mein Code Editor schon auf UTF8 eingestellt, der Browser wohl nicht. Die Konvertierung nach UTF-16 ist leider schon wieder so ein Brainfuck, dass ich obwohl mit Beispiel nicht geschafft habe.

Im Unicodeblock 00 findet ihr die Umlaute.
ä 00E4
Ä 00C4
ö 00F6
Ö 00D6
ü 00FC
Ü 00DC
Unicodeblock_Lateinisch-1, Ergänzung

02.01.2018

CAD/CAM heightmap Part 2

Filed under: Allgemein — Tags: — Thomas @ 14:01

dolphin

Dieses mal versuche ich eine rotierte Heightmap zu erzeugen. Dabei wird das Modell um die Y Achse rotiert und zwar um den Mittelpunkt von Modell.

    // origin y is z
    Point3D rotateAroundY(const double angle, const Point2D& origin) const {
        const auto c = std::cos(deg2rad(angle));
        const auto s = std::sin(deg2rad(angle));
        const auto xnew = c*(x()-origin.x()) - s*(z()-origin.y()) + origin.x();
        const auto znew = s*(x()-origin.x()) + c*(z()-origin.y()) + origin.y();
        return Point3D{xnew, y(), znew};

    }

Das Endergebnis sieht auf den ersten Blick etwas komisch aus, aber ich denke, es ist richtig. Einmal hat man die Ansicht von Unten. Dann seitlich und von Oben, mit der Rückenflosse.

heightmapRot

Powered by WordPress