dynamic_bitset:

* fixed form of some remaining copyright lines
    * using namespace detail::dynamic_bitset_impl for *all* implementation
      details (dynamic_bitset_*count*_impl removed) and consequently shortened
      some entity names
    * switched from enum to bools for "enum mode", to help several compilers
      which show problems with recognizing access_by_bytes and access_by_blocks
      as constant expressions
    * minor comment changes
    * implemented the do-the-right-thing dispatch for constructor from
      iterator-range, a la standard sequence containers (feature request #2172)
    * dropped now useless comparison with zero in reference constructor

NOTE:
    updated tests and documentation not committed yet; let's wait for the trunk
    results first


[SVN r48478]
This commit is contained in:
Gennaro Prota 2008-08-30 18:00:30 +00:00
parent d80a9dbdf8
commit d09c7d2180
2 changed files with 146 additions and 51 deletions

View File

@ -1,7 +1,7 @@
// --------------------------------------------------
// -----------------------------------------------------------
//
// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002.
// (C) Copyright Gennaro Prota 2003 - 2006.
// Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
// Copyright (c) 2003-2006, 2008 Gennaro Prota
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@ -9,14 +9,10 @@
//
// -----------------------------------------------------------
// See http://www.boost.org/libs/dynamic_bitset/ for documentation.
//
// $Revision$ $Date$ - $Name$
#ifndef BOOST_DETAIL_DYNAMIC_BITSET_HPP
#define BOOST_DETAIL_DYNAMIC_BITSET_HPP
#include <cstddef> // for std::size_t
#include <cstddef>
#include "boost/config.hpp"
#include "boost/detail/workaround.hpp"
@ -24,6 +20,7 @@
namespace boost {
namespace detail {
namespace dynamic_bitset_impl {
// Gives (read-)access to the object representation
// of an object of type T (3.9p4). CANNOT be used
@ -46,13 +43,29 @@ namespace boost {
// ------- count function implementation --------------
namespace dynamic_bitset_count_impl {
typedef unsigned char byte_type;
enum mode { access_by_bytes, access_by_blocks };
// This two entities
//
// enum mode { access_by_bytes, access_by_blocks };
// template <mode> struct mode_to_type {};
//
// were removed, since the regression logs (as of 24 Aug 2008) show
// that several compilers have troubles with recognizing
//
// const mode m = access_by_bytes
//
// as a constant expression
//
// *We'll use a bool, instead *.
//
template <bool value>
struct value_to_type
{
};
const bool access_by_bytes = true;
const bool access_by_blocks = false;
template <mode> struct mode_to_type {};
// the table: wrapped in a class template, so
// that it is only instantiated if/when needed
@ -87,7 +100,7 @@ namespace boost {
template <typename Iterator>
inline std::size_t do_count(Iterator first, std::size_t length,
int /*dummy param*/,
mode_to_type<access_by_bytes>* )
value_to_type<access_by_bytes>* )
{
std::size_t num = 0;
if (length)
@ -111,7 +124,7 @@ namespace boost {
//
template <typename Iterator, typename ValueType>
inline std::size_t do_count(Iterator first, std::size_t length, ValueType,
mode_to_type<access_by_blocks>*)
value_to_type<access_by_blocks>*)
{
std::size_t num = 0;
while (length){
@ -129,8 +142,6 @@ namespace boost {
return num;
}
} // dynamic_bitset_count_impl
// -------------------------------------------------------
@ -139,7 +150,7 @@ namespace boost {
//
// size_type(-1) / sizeof(T)
//
// from vector<>::max_size. This tries to get out more
// from vector<>::max_size. This tries to get more
// meaningful info.
//
template <typename T>
@ -158,16 +169,57 @@ namespace boost {
// for static_asserts
template <typename T>
struct dynamic_bitset_allowed_block_type {
struct allowed_block_type {
enum { value = T(-1) > 0 }; // ensure T has no sign
};
template <>
struct dynamic_bitset_allowed_block_type<bool> {
struct allowed_block_type<bool> {
enum { value = false };
};
template <typename T>
struct is_numeric {
enum { value = false };
};
# define BOOST_dynamic_bitset_is_numeric(x) \
template<> \
struct is_numeric<x> { \
enum { value = true }; \
} /**/
BOOST_dynamic_bitset_is_numeric(bool);
BOOST_dynamic_bitset_is_numeric(char);
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_dynamic_bitset_is_numeric(wchar_t);
#endif
BOOST_dynamic_bitset_is_numeric(signed char);
BOOST_dynamic_bitset_is_numeric(short int);
BOOST_dynamic_bitset_is_numeric(int);
BOOST_dynamic_bitset_is_numeric(long int);
BOOST_dynamic_bitset_is_numeric(unsigned char);
BOOST_dynamic_bitset_is_numeric(unsigned short);
BOOST_dynamic_bitset_is_numeric(unsigned int);
BOOST_dynamic_bitset_is_numeric(unsigned long);
#if defined(BOOST_HAS_LONG_LONG)
BOOST_dynamic_bitset_is_numeric(::boost::long_long_type);
BOOST_dynamic_bitset_is_numeric(::boost::ulong_long_type);
#endif
// intentionally omitted
//BOOST_dynamic_bitset_is_numeric(float);
//BOOST_dynamic_bitset_is_numeric(double);
//BOOST_dynamic_bitset_is_numeric(long double);
#undef BOOST_dynamic_bitset_is_numeric
} // dynamic_bitset_impl
} // namespace detail
} // namespace boost

View File

@ -58,7 +58,7 @@ class dynamic_bitset
// this class definition to avoid problems with VC++. Similarly,
// with the member functions of nested classes.
BOOST_STATIC_ASSERT(detail::dynamic_bitset_allowed_block_type<Block>::value);
BOOST_STATIC_ASSERT(detail::dynamic_bitset_impl::allowed_block_type<Block>::value);
public:
typedef Block block_type;
@ -82,7 +82,7 @@ public:
// the one and only non-copy ctor
reference(block_type & b, block_type pos)
:m_block(b), m_mask(block_type(1) << pos)
{ assert(pos >= 0 && pos < bits_per_block); }
{ assert( pos < bits_per_block); }
void operator&(); // left undefined
@ -166,10 +166,39 @@ public:
dynamic_bitset(BlockInputIterator first, BlockInputIterator last,
const Allocator& alloc = Allocator())
:m_bits(first, last, alloc),
m_num_bits(m_bits.size() * bits_per_block)
{}
:m_bits(alloc),
m_num_bits(0)
{
using boost::detail::dynamic_bitset_impl::value_to_type;
using boost::detail::dynamic_bitset_impl::is_numeric;
const value_to_type<
is_numeric<BlockInputIterator>::value> selector;
dispatch_init(first, last, selector);
}
template <typename T>
void dispatch_init(T num_bits, unsigned long value,
detail::dynamic_bitset_impl::value_to_type<true>)
{
init_from_unsigned_long(static_cast<size_type>(num_bits), value);
}
template <typename T>
void dispatch_init(T first, T last,
detail::dynamic_bitset_impl::value_to_type<false>)
{
init_from_block_range(first, last);
}
template <typename BlockIter>
void init_from_block_range(BlockIter first, BlockIter last)
{
assert(m_bits.size() == 0);
m_bits.insert(m_bits.end(), first, last);
m_num_bits = m_bits.size() * bits_per_block;
}
// copy constructor
dynamic_bitset(const dynamic_bitset& b);
@ -350,6 +379,39 @@ private:
}
void init_from_unsigned_long(size_type num_bits,
unsigned long value/*,
const Allocator& alloc*/)
{
assert(m_bits.size() == 0);
m_bits.resize(calc_num_blocks(num_bits));
m_num_bits = num_bits;
typedef unsigned long num_type;
typedef boost::detail::dynamic_bitset_impl
::shifter<num_type, bits_per_block, ulong_width> shifter;
//if (num_bits == 0)
// return;
// zero out all bits at pos >= num_bits, if any;
// note that: num_bits == 0 implies value == 0
if (num_bits < static_cast<size_type>(ulong_width)) {
const num_type mask = (num_type(1) << num_bits) - 1;
value &= mask;
}
typename buffer_type::iterator it = m_bits.begin();
for( ; value; shifter::left_shift(value), ++it) {
*it = static_cast<block_type>(value);
}
}
BOOST_DYNAMIC_BITSET_PRIVATE:
bool m_unchecked_test(size_type pos) const;
@ -539,28 +601,10 @@ dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>::
dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc)
: m_bits(calc_num_blocks(num_bits), Block(0), alloc),
m_num_bits(num_bits)
: m_bits(alloc),
m_num_bits(0)
{
typedef unsigned long num_type;
typedef boost::detail::shifter<num_type, bits_per_block, ulong_width> shifter;
//if (num_bits == 0)
// return;
// zero out all bits at pos >= num_bits, if any;
// note that: num_bits == 0 implies value == 0
if (num_bits < static_cast<size_type>(ulong_width)) {
const num_type mask = (num_type(1) << num_bits) - 1;
value &= mask;
}
typename buffer_type::iterator it = m_bits.begin();
for( ; value; shifter::left_shift(value), ++it) {
*it = static_cast<block_type>(value);
}
init_from_unsigned_long(num_bits, value);
}
// copy constructor
@ -957,18 +1001,17 @@ template <typename Block, typename Allocator>
typename dynamic_bitset<Block, Allocator>::size_type
dynamic_bitset<Block, Allocator>::count() const
{
using namespace detail::dynamic_bitset_count_impl;
using namespace detail::dynamic_bitset_impl;
const bool no_padding = bits_per_block == CHAR_BIT * sizeof(Block);
const bool enough_table_width = table_width >= CHAR_BIT;
const mode m = (no_padding && enough_table_width)
? access_by_bytes
: access_by_blocks;
typedef mode_to_type<m> m_type;
const bool mode = (no_padding && enough_table_width)
? access_by_bytes
: access_by_blocks;
return do_count(m_bits.begin(), num_blocks(), Block(0),
static_cast<m_type *>(0));
static_cast<value_to_type<mode> *>(0));
}