Home > Software engineering >  How can I extend or change the behaviour of c standard library objects
How can I extend or change the behaviour of c standard library objects

Time:07-27

Let's say I want to change the default way the std::bitset prints out its bit. The normal way is:

#include <iostream>
#include <bitset>

int main() {

    std::cout << "size of int is: " << (sizeof (int)) << std::endl;

    std::bitset<32> bits = 0xFFFF0000;
    std::cout << "Original\n" << bits << std::endl;
    
    return 0;
}

Which rightfully outputs (assuming 32 bit processor):

size of int is: 4
Original
11111111111111110000000000000000

Now I want it to print the bits with a space between each byte: e.g.

11111111 11111111 00000000 00000000

or a hypen between each byte:

11111111-11111111-00000000-00000000

I know that a solution is to I make my own function to print bits. But I want to know how can I extend or add more functionality and options to a standard library object.

CodePudding user response:

I want to know how can I extend or add more functionality and options to a standard library object.

Don't. At least not directly. In general you better do not overload operators for types you do not own. In this case there is already an std::ostreams << operator. Rather write your own custom type that manages how to print a std::bitset.

#include <iostream>
#include <bitset>

template<size_t N>
struct pretty_print_bitset {
    pretty_print_bitset(std::bitset<N>& ref,char sep) : ref(ref),sep(sep) {} // constructor for CTAD
    std::bitset<N>& ref;
    char sep;
};

template <size_t N>
std::ostream& operator<<(std::ostream& out,const pretty_print_bitset<N>& ppb){
    for (int i=0;i<N;  i){
        out << ppb.ref[i];
        if ((i 1)%8 ==0 && i !=N-1) out << ppb.sep;
    }        
    return out;
}

int main() {
    std::bitset<32> b;
    std::cout << pretty_print_bitset{b,'-'};
}

Output:

00000000-00000000-00000000-00000000

CodePudding user response:

In your case, you simply want to change the representation of the bitset when passing to an ostream. I.e you do not need to change any internal behavior of the bitset, nor access any internal data by other means than using the public API.

In this case you can simply overload the stream insertion operator:

#include <iostream>
#include <bitset>

template < std::size_t T >
std::ostream& operator << (std::ostream& os, const std::bitset<T>& v) 
{
    for(int i=T-1; i>=0; --i) {
        os << v[i];
        if(i%8 == 0) {
            os << " ";
        }
    }
    return os;
}

int main() {

    std::cout << "size of int is: " << (sizeof (int)) << std::endl;

    std::bitset<32> bits = 0xFFFF0000;
    std::cout << "Original\n" << bits << std::endl;
    
    return 0;
}
  • Related