4
\$\begingroup\$

This is a follow up of my original question in which I'd still like to have some answers, opinions etc. but after looking through some of the standard library's features I have come across std::bitset and was looking at its behavior.

I managed to write a simple class template to provide the behavior I was after. This also covers some of the questions and concerns I had previously asked. It helps to remove a lot of the type casting. I believe it helps to make it more generic and portable. It should be trivially copyable as long as std::bitset is in which I'm not 100% sure. It simplifies the code a great deal making it more readable and manageable.

Now for accessing individual bits within a Byte, Word, DWord or QWord through a direct member variable within a bitfield, the std::bitset allows you to do so by using the index operator which is fine and actually more convenient if you are trying to use it through an iterative loop. This also removed the need for the inner struct and having to access the value through multiple levels of indirection.

The only major difference here is the actual output. It shows the values in its pure binary representation which is okay. There are available functions to convert them to either an integer type or a string type.

Here is what I have now compared to my previous code:

-main.cpp-

#include <iostream>
#include "Register.h"

int main() {

    Register r1;
    std::cout << "Register<8>\n";
    for (i16 i = 0; i < 21; i++) {
        r1.register_ = i;
        std::cout << r1.register_ << "\n";
    }
    std::cout << '\n';

    // Note: my output shows: 0 1 1 0 0 1 0 0 
    // as I am running on an intel x86-64 bit Quad Core Extreme
    // this is expected since my machine is little endian.
    r1.register_ = 38;
    std::cout << "Bit Values\n";
    std::cout << r1.register_[0] << " " 
              << r1.register_[1] << " " 
              << r1.register_[2] << " " 
              << r1.register_[3] << " "
              << r1.register_[4] << " " 
              << r1.register_[5] << " " 
              << r1.register_[6] << " " 
              << r1.register_[7] << "\n\n";

    Register<16> r2;
    std::cout << "Register<16>\n";
    for (i16 i = 0; i < 21; i++) {
        r2.register_ = i;
        std::cout << r2.register_ << "\n";
    }
    std::cout << '\n';

    Register<32> r3;
    std::cout << "Register<32>\n";
    for (i32 i = 0; i < 21; i++) {
        r3.register_ = i;
        std::cout << r3.register_ << "\n";
    }
    std::cout << '\n';

    Register<64> r4;
    std::cout << "Register<64>\n";
    for (i64 i = 0; i < 21; i++) {
        r4.register_ = i;
        std::cout << r4.register_ << "\n";
    }
    std::cout << '\n';

    return EXIT_SUCCESS;
}

-Output-

Register<8>
00000000
00000001
00000010
00000011
00000100
00000101
00000110
00000111
00001000
00001001
00001010
00001011
00001100
00001101
00001110
00001111
00010000
00010001
00010010
00010011
00010100

Bit Values
0 1 1 0 0 1 0 0

Register<16>
0000000000000000
0000000000000001
0000000000000010
0000000000000011
0000000000000100
0000000000000101
0000000000000110
0000000000000111
0000000000001000
0000000000001001
0000000000001010
0000000000001011
0000000000001100
0000000000001101
0000000000001110
0000000000001111
0000000000010000
0000000000010001
0000000000010010
0000000000010011
0000000000010100

Register<32>
00000000000000000000000000000000
00000000000000000000000000000001
00000000000000000000000000000010
00000000000000000000000000000011
00000000000000000000000000000100
00000000000000000000000000000101
00000000000000000000000000000110
00000000000000000000000000000111
00000000000000000000000000001000
00000000000000000000000000001001
00000000000000000000000000001010
00000000000000000000000000001011
00000000000000000000000000001100
00000000000000000000000000001101
00000000000000000000000000001110
00000000000000000000000000001111
00000000000000000000000000010000
00000000000000000000000000010001
00000000000000000000000000010010
00000000000000000000000000010011
00000000000000000000000000010100

Register<64>
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000000011
0000000000000000000000000000000000000000000000000000000000000100
0000000000000000000000000000000000000000000000000000000000000101
0000000000000000000000000000000000000000000000000000000000000110
0000000000000000000000000000000000000000000000000000000000000111
0000000000000000000000000000000000000000000000000000000000001000
0000000000000000000000000000000000000000000000000000000000001001
0000000000000000000000000000000000000000000000000000000000001010
0000000000000000000000000000000000000000000000000000000000001011
0000000000000000000000000000000000000000000000000000000000001100
0000000000000000000000000000000000000000000000000000000000001101
0000000000000000000000000000000000000000000000000000000000001110
0000000000000000000000000000000000000000000000000000000000001111
0000000000000000000000000000000000000000000000000000000000010000
0000000000000000000000000000000000000000000000000000000000010001
0000000000000000000000000000000000000000000000000000000000010010
0000000000000000000000000000000000000000000000000000000000010011
0000000000000000000000000000000000000000000000000000000000010100

-Register.h-

#pragma once

#include <bitset>
#include <vector> // include for typedefs below.

typedef std::int8_t  i8;
typedef std::int16_t i16;
typedef std::int32_t i32;
typedef std::int64_t i64;    

template<std::uint64_t N = 8>
struct Register {
    std::bitset<8> register_;

    Register() {
        static_assert( 
            ((N % 8) == 0) &&
            (N >= 8) &&
            (N <= 64)
        );
    }
};

template<>
struct Register<16> {
    std::bitset<16> register_;
    Register() = default;
};

template<>
struct Register<32> {
    std::bitset<32> register_;
    Register() = default;
};

template<>
struct Register<64> {
    std::bitset<64> register_;
    Register() = default;
};

Let me know what you think of this new model compared to my original design and implementation...

\$\endgroup\$
  • \$\begingroup\$ Thank you for editing. I didn't get a chance to finish proof reading as I was limited on time and I didn't want to lose what I already had so I did quick post(draft). \$\endgroup\$ – Francis Cugler May 5 at 22:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.