byte vs char

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • diadomraz
    New Member
    • Nov 2008
    • 2

    #1

    byte vs char

    Hi,

    This is a question about declaring a signed 8bit numeric type in C++ that prints like a numeric variable and not like a char variable. I would like to declare a type with name 'byte' which represents 8bit numeric values. Of course C++ has char with the right size. So I tried
    ------
    typedef char byte;
    ------
    This is fine, until I tried
    ---------
    byte b = 1;
    cout << b;
    ---------
    This (as expected) does not output '1' (as I would like), but rather the char with ascii code 1. Since I would prefer my numeric types to print as their decimal value (like int, doulbe, etc.), I tried
    --------
    typedef char byte;
    std::ostream &operator<<(std ::ostream &os, const byte &b) {
    os << (int)b;
    return os;
    }
    -------
    Now
    --------
    char b=62;
    cout << b;
    -------
    prints '62' and not 'A'. It seems that typedef is simply aliasing and not actually creating a new type. My next attempt is to create a new type which just wraps char
    ---------
    class byte {
    char v;
    public:
    byte() : v() { }
    byte(const byte &w) : v(w.v) { }
    byte(const char &w) : v(w) { }

    byte &operator=(cons t byte &w) { v = w.v; return *this; }
    byte &operator=(cons t char &w) { v = w; return *this; }

    operator char() { return v; }

    friend std::ostream &operator<<(std ::ostream &, const byte &);
    friend std::istream &operator>>(std ::istream &, byte &);
    };

    std::ostream &operator<<(std ::ostream &os, const byte &b) {
    os << (int)b.v;
    return os;
    }
    ------------
    This works fine, except when compiling with g++ (GCC) 4.1.2 20071124 (Red Hat 4.1.2-42)
    ------
    byte b = 0;
    b++;
    -----
    produces:
    error: no 'operator++(int )' declared for postfix '++', trying prefix operator instead
    error: no match for 'operator++' in '++b'

    This is rather odd because
    ------
    byte b = 0;
    b = b + 1;
    -----
    compiles fine (the conversion to unsigned char is called as intended).

    So it seems like I have to declare ++, --, +=, .... At this point I gave up on this attempt because it seemed to me that the solution is already going out of hand for what I wanted originally.

    Is there an elegant solution to this?

    Thanks,
    Vladimir
  • JosAH
    Recognized Expert MVP
    • Mar 2007
    • 11453

    #2
    You're on the right track: indeed the old C typedef just creates a new name for
    an already existing type and the pre- or postfix ++ isn't mapped to a x+1 binary
    operator. If takes a bit of work to create an entirely new type that accepts the
    same operators as the built-in primitives.

    You can define the operators 'op' in terms of the 'op=' operators. The first one just
    calls the second one on a copy of the the left hand operand. So you have to
    create a copy constructor (which is trivial in your case).

    Compare your 'byte' class with Bjarne Stroustrup's 'complex' class; they're similar.

    kind regards,

    Jos

    Comment

    • Banfa
      Recognized Expert Expert
      • Feb 2006
      • 9067

      #3
      Depending on how often you output bytes using cout you may find it easier just to static_cast your byte type'd variables to int in your cout statements.

      This is one area where I have always felt that C++s attempt to guess how you want your variable output was rather less useful than C's basic insistence that you tell it how to do it.

      Also if you want byte as an unsigned 8 bit variable then you need to define it as
      typedef unsigned char byte

      because the signedness of char is platform dependent.

      Comment

      • diadomraz
        New Member
        • Nov 2008
        • 2

        #4
        Thanks, guys!

        I fiddled with this some more over the weekend and found out that the following code works for me. Thought I would post this in case somebody is fighting with the same...
        ---------------------
        template <class T>
        class byte_templ {
        T v;

        public:
        byte_templ<T>() : v() { }
        byte_templ<T>(c onst T &w) : v(w.v) { }
        byte_templ<T>(c onst byte_templ<T> &w) : v(w) { }

        byte_templ<T> &operator=(cons t byte_templ<T> &w) { v = w.v; return *this; }
        byte_templ<T> &operator=(cons t T &w) { v = w; return *this; }

        operator T() const { return v; }
        operator T &() { return v; }
        };

        std::ostream &operator<<(std ::ostream &os, const byte_templ<unsi gned char> &b) {
        os << (unsigned short)b;
        return os;
        }

        std::istream &operator>>(std ::istream &is, byte_templ<unsi gned char> &b) {
        unsigned short i;

        is >> i;
        b = (unsigned char)i;
        return is;
        }

        typedef byte_templ<unsi gned char> byte;
        ---------------------
        Now
        ---------------------
        cin >> b;
        b++;
        cout << b;
        ---------------------
        works as intended. Basically, I needed to add the cast to (unsigned char &), because 'b++' implicitly contains an assignment...

        Best, Vladimir

        Comment

        Working...