1

I have a class Bitset that stores a vector of chars, and I want to be able, whenever I use cout << char, to cast that char into a short int ONLY if it is part of that class.

Code:

template<long long X>
class Bitset
{
    public: std::vector<unsigned char> bit = std::vector<unsigned char> ((X+7)/8);

    public:
        /* constructors */

        friend std::ostream &operator<< (std::ostream &output, const char x);
};

std::ostream &operator<< (std::ostream &output, const char x)
{
    output<<(short)(x);
    return output;
}

The idea is that if I write:

Bitset a;
/* code */
cout << a.bit[x];
cout << 'a';

I want to cast a.bit[x] into a short, but not 'a' as well.

1
  • It's a bit unclear what you're asking. When you say "I want to be able, whenever I use cout<<char, to cast that char into a short int ONLY if it is part of that class", it sounds like what you're trying to achieve is completely unrelated to the Bitset class. Do you mean that you want cout << a.bit[x]; to always print a number instead of an ASCII character? This will need something other than char, but you could do it with a simple struct that wraps a char. You could also use std::byte to more clearly document that this is not a character
    – alter_igel
    Commented Jun 23, 2020 at 21:49

2 Answers 2

7

You can't overload operator<< for char to behave the way you want. It has no idea where the char comes from, so it can't behave differently based on the source.

To make this work the way you want, you will have to make Bitset implement its own operator[] that returns a proxy object, and then you can overload operator<< for that proxy, eg:

template<long long X>
class Bitset
{
private:
    std::vector<unsigned char> bits = std::vector<unsigned char> ((X+7)/8);

public:
    /* constructors */

    class BitProxy
    {
    private:
        unsigned char &bit;

    public:
        BitProxy(unsigned char &bit) : bit(bit) {}

        BitProxy& operator=(unsigned char x) { bit = x; return *this; }
        operator unsigned char() const { return bit; }
    };

    BitProxy operator[](size_t index) { return BitProxy(bits[index]); }

    friend std::ostream& operator<< (std::ostream &output, const BitProxy &x)
    {
        output << static_cast<short>(static_cast<unsigned char>(x));
        return output;
    }
};
Bitset a;
// populate a as needed...
cout << a[x];
cout << 'a';

Live Demo

0

I would adopt a very simple approach to this: just implement a function in your class with the following signature:

short GetElementAsShort (size_t index);

And then you can of course do:

Bitset <128> a;
std::cout << a.GetElementAsShort (42) << "\n";

I really don't see why anything more complicated as needed. It also makes it obvious what's going on when you read the code.

1
  • Well, yeah, that's an easy way of doing it, it's just that I'm setting challenges for myself for practice.
    – H-005
    Commented Jun 24, 2020 at 14:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.