C++Guns – RoboBlog blogging the bot

03.03.2017

C++ Guns - Fun with enable_if

Filed under: Allgemein — Tags: — Thomas @ 08:03

Schonmal std::enable_if benutzt? Ich nicht. Man kann damit Funktionen deaktivieren... Irgendwie... SFINAE... Gesundheit!
Die Beispiele dazu sind alles nur Kraut und Rüben. Vor lauter Template Scheiße sieht man den Kern der Aussage nicht.
Also, hier mein eigenen Testfall:


// Template Parameter N wird einfach an die Funktionen weitergegeben
template<int N>
class Testclass {
public:

    // Um enable_if und SFINAE zu nutzen, muss die Funktion ein Template sein.
    // Dummerweise muss der Template Parameter afaik auch in enable_if genutzt werden.
    template<int U=N>
    enable_if_t< U>=1 , int>
    eins() {
        return 1;
    }

    // Wo steckt der Rueckgabetyp? Im zweiten enable_if Template Paramter. Strange...
    template<int U=N>
    enable_if_t< U>=2 , int>
    zwei() {
        return 2;
    }

    // Dabei darauf achten, dass die beiden dreioverload() Funktionen auch unterschiedliche Template Typen
    // haben. Sonst ist, wie beim normalen function overload, kein ueberladen moeglich. Wo ist der Unterschied
    // in den Typen? N ist gleich. U ist gleich. int ist gleich. Nur der erste Parameter von enable_if evaluiert
    // einmal zu true und einmal zu false. Das sind zwei unterschiedliche Typen!
    template<int U=N>
    enable_if_t< U>=3 , int>
    dreioverload() {
        return 3;
    }

    template<int U=N>
    enable_if_t< !(U>=3) , int>
    dreioverload() {
        return -1;
    }
};

    cout << Testclass<1>().eins() << "\n";
    cout << Testclass<2>().eins() << "\n";
    cout << Testclass<2>().zwei() << "\n";
    cout << Testclass<2>().dreioverload() << "\n"; // Print -1

Mal abwarten ob so etwas im normalen Code sinnvoll einsetzbar ist.

01.03.2017

todo: owning and non owning

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

Jeder Funktionsparemter der (const)(Referenz)(Pointer) ist, ist non-owning

C++ Guns - Point3D ist KEINE Erweiterung von Point2D!

Filed under: Allgemein — Tags: — Thomas @ 15:03

Point3D ist KEINE Erweiterung von Point2D!
Sondern Point2D ist eine Reduzierung von Point3D. WTF? Ja ist so :P

Beweis:


struct Point2D {
    double x,y;
};

struct Point3D : public Point2D {
    double z;
};

static_assert(std::is_standard_layout<Point3D>::value);
main.cpp:14:1: error: static assertion failed
static_assert(std::is_standard_layout<Point3D>::value);

In der C++ Sprache ist alles, was berechnet werden kann, ausdrückbar. Wird dabei das Standard Layout nicht eingehalten, ist definitiv der falsche Weg eingeschlagen worden.

Der zweite Tipp ist, dass ohne Standardlayout die Typen auch nicht POD sind. Und man kann wohl getrost annehmen, wenn ein double POD ist. Dann muss auch ein Type mit 2 oder 3 double POD sein!

Lösung:
Point2D ist auch im Point3D enthalten. Es wird halt nicht x,y,z beachtet, sondern nur x,y.
Wenn PointND als Array implementiert wird, ist das nichts anderes als array_view (string_view).
Sprich, wird der Datensatz als Point3D gespeichert (owning), sind Point2D und Point1D non-owning.

Beispiel:


template<size_t N>
struct PointNDRef : public array_view<double, N>
{
    using array_view<double,N>::array_view;
};

template<size_t N>
struct PointND : public std::array<double,N>
{
    operator PointNDRef<2>() {
        return this->data();
    }

    operator PointNDRef<1>() {
        return this->data();
    }
};

static_assert(std::is_standard_layout<PointND>::value);

using Point3D = PointND<3>;
using Point2DRef = PointNDRef<2>;

void func(const Point2DRef p) {
    p[0];
    get<0>(p);
}

int main() {
    Point3D p;
    func(p);
    return 0;
}

Die Implementation von array_view kommt dann irgendwann die Wochen.

todo: dereference of a null pointer at compile time?

Filed under: Allgemein — Thomas @ 12:03
« Newer Posts

Powered by WordPress