On 11/29/2015 9:27 PM, MikeCopeland wrote:
> Is there a way to initialize a non-contiguous number of bits in a
> std::bitset (other than with a string of 0 or 1 bits with those desired
> bits as 1)? That is, I have a declration of:
> std::bitset<100> myBits;
> and I want to set the following bits:
> 7, 9, 43, 47, 51-59, 66, 67
> I can, of course, construct a string constant of these bits, but it's
> tedious to code and completely lacking in good documentation...
> Is there an easy way to do so in source code? TIA
The answers so far have just presented short, easy to grasp code.
But a challenge to simplify one little aspect of notation requires lots
more code, to hone that little aspect down to the very simplest! Like
my::Bits<100> const bits = { 7, 9, 43, 47, Range( 51, 59 ), 66, 67 };
In the following I have however refrained from adding the most obvious
things like standard typedefs for iterators, or a formally correct
operator++(int); I leave those details to the reader!
<code>
#include <bitset>
#include <functional> // std::equal_to, std::less
#include <initializer_list>
#include <iostream>
#include <stddef.h> // ptrdiff_t
#include <utility> // std::move
namespace my {
using std::bitset;
using std::equal_to;
using std::initializer_list;
using std::less;
using std::move;
using Size = ptrdiff_t;
template< class Type >
auto n_items( Type const& o ) -> Size { return o.size(); }
template< class Type >
auto stdcmp( Type&& a, Type&& b )
-> int
{
using Eq = equal_to<Type>;
using Lt = less<Type>;
return (Eq()( a, b )? 0 : Lt()( a, b )? -1 : +1);
}
template< class State >
class Forward_iterator
{
private:
State state_;
public:
friend
auto operator==( Forward_iterator const& a, Forward_iterator
const& b )
-> bool
{ return (compare( a.state_, b.state_ ) == 0); }
friend
auto operator!=( Forward_iterator const& a, Forward_iterator
const& b )
-> bool
{ return (compare( a.state_, b.state_ ) != 0); }
auto operator++()
-> Forward_iterator&
{ state_.advance(); return *this; }
void operator++( int )
{
//Forward_iterator result = *this;
state_.advance();
//return result;
}
auto operator*() const
-> decltype( state_.referent() )
{ return state_.referent(); }
Forward_iterator( State state ): state_( move( state ) ) {}
};
template< class Type = int >
class Int_range
{
private:
Type first_;
Type last_;
class Iterstate
{
friend class Int_range<Type>;
private:
Int_range const* p_range_;
Type current_;
Iterstate( Int_range const& range, Type const where )
: p_range_( &range ), current_( where )
{}
public:
friend
auto compare( Iterstate const& a, Iterstate const& b )
-> int
{
if( int const r = stdcmp( a.p_range_, b.p_range_ ) ) {
return r; };
return stdcmp( a.current_, b.current_ );
}
void advance() { ++current_; }
auto referent() const -> Type { return current_; }
};
public:
using Iterator = Forward_iterator<Iterstate>;
auto begin() const
-> Iterator
{ return Iterator( Iterstate( *this, first_ ) ); }
auto end() const
-> Iterator
{ return Iterator( Iterstate( *this, last_ + 1 ) ); }
Int_range( Type const value )
: first_( value ), last_( value )
{}
Int_range( Type const a, Type const b )
: first_( a ), last_( b )
{}
};
template< Size n >
class Bits
: public std::bitset< n >
{
public:
Bits( initializer_list<Int_range<>> const& one_bits )
{
for( Int_range<> const& r : one_bits )
{
for( int const i : r )
{
this->set( i );
}
}
}
};
} // namespace my
auto main() -> int
{
using Range = my::Int_range<>;
my::Bits<100> const bits = { 7, 9, 43, 47, Range( 51, 59 ), 66, 67 };
std::cout << "Bits ";
for ( int i = 0; i < n_items( bits ); i++)
{
if( bits.test(i) )
{
std::cout << i << ' ';
}
}
std::cout << "are set." << std::endl;
}
</code>
Cheers, & hth.,
- Alf