Javas byte in C++(11) - ein char-Wrapper



  • Hi!

    Ich war letztens sehr traurig 😞 , dass es in C++ nicht sowas schönes gibt wie byte (Java). Ich fand es also umso lustiger, mal was auszuprobieren und hab schließlich das hier herausbekommen:

    #include <iostream>
    
    template<typename a, typename b, bool AorB>
    struct base_byte_helper{};
    
    template<typename a, typename b>
    struct base_byte_helper<a, b, true>
    {
          typedef a type;
    };
    template<typename a, typename b>
    struct base_byte_helper<a, b, false>
    {
          typedef b type;
    };
    
    template<bool>
    class base_byte;
    
    template<bool si>
    std::istream& operator>>(std::istream& is, base_byte<si>& b);
    
    template<bool signed_>
    class base_byte
    {
    public:
    
          typedef typename base_byte_helper<int8_t, uint8_t, signed_>::type underlying_type;
    
          base_byte(underlying_type t) throw():
          value(t) {}
    
          base_byte() throw() {}
    
          operator underlying_type&() throw()
          {
                return value;
          }
          operator underlying_type() const throw()
          {
                return value;
          }
    
          friend std::istream& operator>><>(std::istream& is, base_byte& b);
    
    private:
    
           underlying_type value;
    };
    
    template<bool si>
    std::ostream& operator<<(std::ostream& os, base_byte<si> const& b)
    {
          return os << short(typename base_byte<si>::underlying_type(b));
    }
    
    template<bool si>
    std::istream& operator>>(std::istream& is, base_byte<si>& b)
    {
          return is >> reinterpret_cast<typename base_byte_helper<short&, unsigned short&, si>::type>(b.value);
    }
    
    typedef base_byte<true> byte;
    typedef base_byte<true> signed_byte;
    typedef base_byte<false> unsigned_byte;
    

    Hier meine Fragen:

    • Ist der Code vollständig standardkonform (bspw. der reinterpret_cast )?
      Von reinterprect_cast kenne ich Paragraph 5.2.10, Klausel 11 (N3337):

    An lvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to
    T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. That is, a reference
    cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with
    the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x)). The result refers to the same
    object as the source lvalue, but with a different type. The result is an lvalue for an lvalue reference type or
    an rvalue reference to function type and an xvalue for an rvalue reference to object type. No temporary is
    created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called.

    Also ist dieser Type pun legal?

    • Verhalten sich byte , signed_byte und unsigned_byte jetzt genau wie int8_t (char) / uint8_t (unsigned char) , abgesehen vom I/O?
    • Und natürlich, ob man das noch besser/kürzer machen kann.
    • Und noch eine nebenfrage, nähmlich ob es sowas wie base_byte_helper in den Type-Traits oder irgendwo schon gibt.

    MfG, Hacker



  • std::conditional



  • Kellerautomat schrieb:

    std::conditional

    Ich wusste, ich hab das gesehen. Danke schon mal für den Tipp 😃
    Das Problem ist halt, ich wollte den Code nicht nur für C++11 schreiben. Aber was solls...

    #include <iostream>
    
    template<bool>
    class base_byte;
    
    template<bool si>
    std::istream& operator>>(std::istream& is, base_byte<si>& b);
    
    template<bool signed_>
    class base_byte
    {
    public:
    
          typedef typename std::conditional<signed_, int8_t, uint8_t>::type underlying_type;
    
          base_byte(underlying_type t) noexcept:
          value(t) {}
    
          base_byte() noexcept {}
    
          operator underlying_type&() noexcept
          {
                return value;
          }
          operator underlying_type() const noexcept
          {
                return value;
          }
    
          friend std::istream& operator>><>(std::istream& is, base_byte& b);
    
    private:
    
           underlying_type value;
    };
    
    template<bool si>
    std::ostream& operator<<(std::ostream& os, base_byte<si> const& b)
    {
          return os << short(typename base_byte<si>::underlying_type(b));
    }
    
    template<bool si>
    std::istream& operator>>(std::istream& is, base_byte<si>& b)
    {
          return is >> reinterpret_cast<typename std::conditional<si, short&, unsigned short&>::type>(b.value);
    }
    
    typedef base_byte<true> byte;
    typedef base_byte<true> signed_byte;
    typedef base_byte<false> unsigned_byte;
    


  • Hacker schrieb:

    Ich war letztens sehr traurig 😞 , dass es in C++ nicht sowas schönes gibt wie byte (Java).

    Was ist an byte in Java so besonders?

    Dir gehts nur ums IO oder?



  • Shade Of Mine schrieb:

    Hacker schrieb:

    Ich war letztens sehr traurig 😞 , dass es in C++ nicht sowas schönes gibt wie byte (Java).

    Was ist an byte in Java so besonders?

    Dir gehts nur ums IO oder?

    Das sieht man doch. 🙄 😃



  • Ehrlich gesagt, ich sehe auch nicht welches Problem geloest werden soll.



  • Hat er doch gesagt:
    Problem: Er war traurig
    Lösung: Er hat was programmiert



  • Hacker schrieb:

    Das sieht man doch. 🙄 😃

    Ehrlich gesagt, nein.
    Man sieht dass du zuviel Zeit hast - aber nicht welches Problem hier gelöst werden soll.

    Du willst einfach immer nur einen cast beim output haben?

    Und dein input klappt natürlich nicht, weil short >1byte ist 😉



  • Wofür genau soll das gut sein? Wieso benutzt du nicht einfach signed bzw. unsigned char?



  • dot schrieb:

    Wofür genau soll das gut sein? Wieso benutzt du nicht einfach signed bzw. unsigned char?

    Das ist doch nicht der Punkt! Es war nur zum Spaß (weil ich nix zu tun hab), und ich wollte wissen ob das so geht und ob es richtig Programmiert wurde.

    Shade's Vorschlag war hilfreich. Der Input ist also nicht äquivalent, daran muss ich also noch pfeilen.

    Mit "Problem" hat das nix zu tun. Ich würde nie im Leben in einem richtigen Projekt sowas benötigen, geschweige benutzen.
    😃

    Verdammt nochmal, Leute, es sind Sommerferien und ich hab einfach nix zum Programmieren. Ich könnte locker 10 Stunden am Tag dafür nehmen. Aber ich weiß nicht wofür. ➡ 😞 ➡ 💡 ➡ ⚠



  • Man kann sich kaum mehr vorstellen, wie sich meine Generation vor 35 Jahren in den Sommerferien gelangweilt haben muss ...



  • Gibt es denn tatsächlich nichts, was dich interessiert, was du dir immer schonmal anschauen wolltest oder was du immer schonmal machen wolltest?



  • Ich könnte ein Praktikum in einer SE-Firma machen, das wär doch was. Kennt da jemand eine gute (Hamburg)?



  • Fällt dir ja früh' ein ...

    Ne, schreib' lieber weiterhin Code, den die Welt nicht braucht. 👍 🤡



  • Projektideen gibt es wie Sand am mehr. Z.b. billige Webkam kaufen und und auf das Aquarium richten. Bewegung der Fische verfolgen lassen. Alternativ auf die Strasse richten und Autos tracken. Idee stammt nicht von mir, das Thema kam hier im Forum mal auf.

    Alternativ Handgestenerkennenung, oder erstmal bis zum Punkt: Livestream einlesen, Hand und Fingerkuppen extrahieren, etc. ....



  • Ich finde auch, dass nicht deutlich rauskommt (abgesehen vom Spaßfaktor), warum du das gemacht hast.

    Hacker schrieb:

    Ist der Code vollständig standardkonform (bspw. der reinterpret_cast)?

    Sieht auf den ersten Blick falsch aus. Der interessante Teil ist doch:

    signed char some_byte;
    some_inputstream >> reinterpret_cast<short&>(some_byte);
    

    bzw

    unsigned char some_byte;
    some_inputstream >> reinterpret_cast<unsigned short&>(some_byte);
    

    Erklär mal, wie kommst du drauf, dass das okay wäre. Du versaust dir hier ja den automatischen Speicher, da sizeof(char) typischerweise kleiner als sizeof(short) ist.

    Ich denke, du wolltest eher so etwas schreiben:

    int value;
    some_inputstream >> value;
    if (value<SCHAR_MIN || value>SCHAR_MAX) {
      Überlauf irgendwie abfangen/signalisieren
      da die Zuweisung im else-Teil sonst UB hervorrufen würde
    } else {
      signed char some_byte = value;
      ...
    }
    


  • Es geht ihm darum dass beim "Rausschiften" eines char/signed char/unsigned char mit Wert 50 nicht 50 am Schirm steht sondern irgend ein blöder Buchstabe.

    Ich finde das übrigens auch immer wieder sehr bekloppt, vor allem weil es auch signed char und unsigned char betrifft.
    Fragt man sich wozu es char dann überhaupt als 3. Typen gibt.



  • Das einfachste dürfte wohl sein, die Operatoren selbst für signed char und unsigned char zu überladen. Ich glaube, die sind laut Standard nicht definiert.



  • Kellerautomat schrieb:

    Das einfachste dürfte wohl sein, die Operatoren selbst für signed char und unsigned char zu überladen. Ich glaube, die sind laut Standard nicht definiert.

    Leider doch. 27.6.1.2.3§10, 27.6.2.5.4 (C++98)



  • Hacker schrieb:

    Verdammt nochmal, Leute, es sind Sommerferien und ich hab einfach nix zum Programmieren. Ich könnte locker 10 Stunden am Tag dafür nehmen. Aber ich weiß nicht wofür. ➡ 😞 ➡ 💡 ➡ ⚠

    renn 200km


Anmelden zum Antworten