Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9297823
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 18, 20262026-06-18T22:10:04+00:00 2026-06-18T22:10:04+00:00

I am attempting to implement a packed_bits class using variadic templates and std::bitset .

  • 0

I am attempting to implement a packed_bits class using variadic templates and std::bitset.

In particular, I am running into problems writing a get function which returns a reference to a subset of the member m_bits which contains all the packed bits. The function should be analogous to std::get for std::tuple.

It should act as an reference overlay so I can manipulate a subset of packed_bits.

For instance,

using my_bits = packed_bits<8,16,4>;
my_bits b;
std::bitset<  8 >& s0 = get<0>( b );
std::bitset< 16 >& s1 = get<1>( b );
std::bitset<  4 >& s2 = get<2>( b );

UPDATE

Below is the code that has been rewritten according to Yakk’s recommendations below. I am stuck at the point of his last paragraph: not sure how to glue together the individual references into one bitset-like reference. Thinking/working on that last part now.

UPDATE 2

Okay, my new approach is going to be to let bit_slice<> do the bulk of the work:

  • it is meant to be short-lived
  • it will publicly subclass std::bitset<length>, acting as a temporary buffer
  • on construction, it will copy from packed_bits<>& m_parent;
  • on destruction, it will write to m_parent
  • in addition to the reference via m_parent, it must also know offset, length
  • get<> will become a free-function which takes a packet_bits<> and returns a bit_slice<> by value instead of bitset<> by reference

There are various short-comings to this approach:

  • bit_slice<> has to be relatively short-lived to avoid aliasing issues, since we only update on construction and destruction
  • we must avoid multiple overlapping references while coding (whether threaded or not)
  • we will be prone to slicing if we attempt to hold a pointer to the base class when we have an instance of the child class

but I think this will be sufficient for my needs. I will post the finished code when it is complete.

UPDATE 3

After fighting with the compiler, I think I have a basic version working. Unfortunately, I could not get the free-floating ::get() to compile properly: BROKEN shows the spot. Otherwise, I think it’s working.

Many thanks to Yakk for his suggestions: the code below is about 90%+ based on his comments.

UPDATE 4

Free-floating ::get() fixed.

UPDATE 5

As suggested by Yakk, I have eliminated the copy. bit_slice<> will read on get_value() and write on set_value(). Probably 90%+ of my calls will be through these interfaces anyways, so no need to subclass/copy.

No more dirtiness.

CODE

#include <cassert>
#include <bitset>
#include <iostream>

// ----------------------------------------------------------------------------

template<unsigned... Args>
struct Add { enum { val = 0 }; };

template<unsigned I,unsigned... Args>
struct Add<I,Args...> { enum { val = I + Add<Args...>::val }; };

template<int IDX,unsigned... Args>
struct Offset { enum { val = 0 }; };

template<int IDX,unsigned I,unsigned... Args>
struct Offset<IDX,I,Args...> { 
    enum { 
        val = IDX>0 ? I + Offset<IDX-1,Args...>::val : Offset<IDX-1,Args...>::val 
    }; 
};

template<int IDX,unsigned... Args>
struct Length { enum { val = 0 }; };

template<int IDX,unsigned I,unsigned... Args>
struct Length<IDX,I,Args...> { 
    enum { 
        val = IDX==0 ? I : Length<IDX-1,Args...>::val 
    }; 
};

// ----------------------------------------------------------------------------

template<unsigned... N_Bits>
struct seq
{
    static const unsigned total_bits = Add<N_Bits...>::val;
    static const unsigned size       = sizeof...( N_Bits );

    template<int IDX>
    struct offset
    {
        enum { val = Offset<IDX,N_Bits...>::val };
    };

    template<int IDX>
    struct length
    {
        enum { val = Length<IDX,N_Bits...>::val };
    };
};

// ----------------------------------------------------------------------------

template<unsigned offset,unsigned length,typename PACKED_BITS>
struct bit_slice
{
    PACKED_BITS& m_parent;

    bit_slice( PACKED_BITS& t ) :
        m_parent( t )
    { 
    }

    ~bit_slice()
    {
    }

    bit_slice( bit_slice const& rhs ) :
        m_parent( rhs.m_parent )
    { }

    bit_slice& operator=( bit_slice const& rhs ) = delete;

    template<typename U_TYPE>
    void set_value( U_TYPE u )
    {
        for ( unsigned i=0; i<length; ++i )
        {
            m_parent[offset+i] = u&1;
            u >>= 1;
        }
    }

    template<typename U_TYPE>
    U_TYPE get_value() const
    {
        U_TYPE x = 0;
        for ( int i=length-1; i>=0; --i )
        {
            if ( m_parent[offset+i] )
                ++x;
            if ( i!=0 )
                x <<= 1;
        }
        return x;
    }
};

template<typename SEQ>
struct packed_bits :
    public std::bitset< SEQ::total_bits >
{  
    using bs_type   = std::bitset< SEQ::total_bits >;
    using reference = typename bs_type::reference;

    template<int IDX> using offset = typename SEQ::template offset<IDX>;
    template<int IDX> using length = typename SEQ::template length<IDX>;
    template<int IDX> using slice_type = 
        bit_slice<offset<IDX>::val,length<IDX>::val,packed_bits>;

    template<int IDX>
    slice_type<IDX> get()
    {
        return slice_type<IDX>( *this );
    }
};

template<int IDX,typename T>
typename T::template slice_type<IDX>
get( T& t )
{
    return t.get<IDX>();
};

// ----------------------------------------------------------------------------

int main( int argc, char* argv[] )
{
    using my_seq   = seq<8,16,4,8,4>;
    using my_bits  = packed_bits<my_seq>;
    using my_slice = bit_slice<8,16,my_bits>;
    using slice_1  = 
        bit_slice<my_bits::offset<1>::val,my_bits::length<1>::val,my_bits>;

    my_bits        b;
    my_slice       s(  b );
    slice_1        s1( b );

    assert( sizeof( b )==8 );
    assert( my_seq::total_bits==40 );
    assert( my_seq::size==5 );

    assert( my_seq::offset<0>::val==0  );
    assert( my_seq::offset<1>::val==8  );
    assert( my_seq::offset<2>::val==24 );
    assert( my_seq::offset<3>::val==28 );
    assert( my_seq::offset<4>::val==36 );

    assert( my_seq::length<0>::val==8  );
    assert( my_seq::length<1>::val==16 );
    assert( my_seq::length<2>::val==4  );
    assert( my_seq::length<3>::val==8  );
    assert( my_seq::length<4>::val==4  );

    {
        auto s2 = b.get<2>();
    }
    {
        auto s2 = ::get<2>( b );
        s2.set_value( 25 );  // 25==11001, but only 4 bits, so we take 1001 
        assert( s2.get_value<unsigned>()==9 );
    }

    return 0;
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-18T22:10:06+00:00Added an answer on June 18, 2026 at 10:10 pm

    I wouldn’t have get return a bitset, because each bitset needs to manage its own memory.

    Instead, I’d use a bitset internally to manage all of the bits, and create bitset::reference-like individual bit references, and bitset-like “slices”, which get can return.

    A bitslice would have a pointer back to the original packed_bits, and would know the offset where it starts, and how wide it is. It’s references to individual bits would be references from the original packed_bits, which are references from the internal bitset, possibly.

    Your Size is redundant — sizeof...(pack) tells you how many elements are in the pack.

    I’d pack up the sizes of the slices into a seqence so you can pass it around easier. Ie:

    template<unsigned... Vs>
    struct seq {};
    

    is a type from which you can extract an arbitrary length list of unsigned ints, yet can be passed as a single parameter to a template.

    As a first step, write bit_slice<offset, length>, which takes a std::bitset<size> and produces bitset::references to individual bits, where bit_slice<offset, length>[n] is the same as bitset[n+offset].

    Optionally, bit_slice could store offset as a run-time parameter (because offset as a compile-time parameter is just an optimization, and not that strong of one I suspect).

    Once you have bit_slice, working on the tuple syntax of packed_bits is feasible. get<n, offset=0>( packed_bits<a,b,c,...>& ) returns a bit_slice<x> determined by indexing the packed_bits sizes, with an offset determined by adding the first n-1 packed_bits sizes, which is then constructed from the internal bitset of the packed_bits.

    Make sense?

    Apparently not. Here is a quick bit_slice that represents some sub-range of bits within a std::bitset.

    #include <bitset>
    
    template<unsigned Width, unsigned Offset, std::size_t SrcBitWidth>
    struct bit_slice {
    private:
      std::bitset<SrcBitWidth>* bits;
    public:
      // cast to `bitset`:
      operator std::bitset<Width>() const {
        std::bitset<Width> retval;
        for(unsigned i = 0; i < Offset; ++i) {
          retval[i] = (*this)[i];
        }
        return retval;
      }
      typedef typename std::bitset<SrcBitWidth>::reference reference;
      reference operator[]( size_t pos ) {
        // TODO: check that pos < Width?
        return (*bits)[pos+Offset];
      }
      constexpr bool operator[]( size_t pos ) const {
        // TODO: check that pos < Width?
        return (*bits)[pos+Offset];
      }
      typedef bit_slice<Width, Offset, SrcBitWidth> self_type;
      // can be assigned to from any bit_slice with the same width:
      template<unsigned O_Offset, unsigned O_SrcBitWidth>
      self_type& operator=( bit_slice<Width, O_Offset, O_SrcBitWidth>&& o ) {
        for (unsigned i = 0; i < Width; ++i ) {
          (*this)[i] = o[i];
        }
        return *this;
      }
      // can be assigned from a `std::bitset<Width>` of the same size:
      self_type& operator=( std::bitset<Width> const& o ) {
        for (unsigned i = 0; i < Width; ++i ) {
          (*this)[i] = o[i];
        }
        return *this;
      }
      explicit bit_slice( std::bitset<SrcBitWidth>& src ):bits(&src) {}
      bit_slice( self_type const& ) = default;
      bit_slice( self_type&& ) = default;
      bit_slice( self_type&o ):bit_slice( const_cast<self_type const&>(o)) {}
      // I suspect, but am not certain, the the default move/copy ctor would do...
      // dtor not needed, as there is nothing to destroy
    
      // TODO: reimplement rest of std::bitset's interface that you care about
    };
    
    template<unsigned offset, unsigned width, std::size_t src_width>
    bit_slice< width, offset, src_width > make_slice( std::bitset<src_width>& src ) {
      return bit_slice< width, offset, src_width >(src);
    }
    
    #include <iostream>
    int main() {
      std::bitset<16> bits;
      bits[8] = true;
      auto slice = make_slice< 8, 8 >( bits );
      bool b0 = slice[0];
      bool b1 = slice[1];
      std::cout << b0 << b1 << "\n"; // should output 10
    }
    

    Another useful class would be a bit_slice with runtime offset-and-source size. This will be less efficient, but easier to program against.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In attempting to implement fileUpload using the streaming API I get an error described
Attempting to implement a poor man's test of whether a process is still running
I'm attempting to implement nested object forms for my site, using Ryan Daigle's blog
I'm attempting to implement a phpBB library into Kohana. I have created a vendor
I am attempting to implement a reverse proxy using the RequestInterceptor from WCF REST
I'm attempting to implement quicksort in-place, using boost's threading facility. Unfortunately I'm getting an
I'm attempting to implement a stack using a linked list. My stack constructor createStack()
I'm attempting to implement the IObservable interface in C# using Mono 2.10.6, and Monodevelop
I'm attempting to implement a PreInsertEvent listener using the latest version (which was at
Im attempting to implement an RSA encryption algorithm into my iOS app, but when

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.