La solución es fácil:
#include <tuple>
using std::get;
using std::tuple;
using std::make_tuple;
#include <boost/dynamic_bitset.hpp>
using boost::dynamic_bitset;
template <typename Block, typename Allocator>
unsigned block_index(const boost::dynamic_bitset<Block, Allocator>& b, unsigned pos)
{ return pos/b.bits_per_block; }
namespace boost {
template <>
inline void
to_block_range(const dynamic_bitset<>& b, tuple<unsigned, unsigned, unsigned long&> param)
{
{
unsigned beg = get<0>(param);
unsigned len = get<1>(param);
unsigned block1 = block_index(b, beg);
unsigned block2 = block_index(b, beg + len -1);
unsigned bit_index = beg % b.bits_per_block;
unsigned long bitmask = (1 << len) - 1;
get<2>(param) = ((b.m_bits[block1] >> bit_index) |
(b.m_bits[block2] << (b.bits_per_block - bit_index) )) &
bitmask;
return;
}
}
}
unsigned long res;
to_block_range(bits, make_tuple(pos, len, std::ref(res)));
para llamar:
boost::dynamic_bitset<> bits;
unsigned long result;
to_block_range(bits, t_extract_range{begin_bit, length_bits, result});
no hay apoyo directo, nativo en dynamic_bitset
.
Para obtener una gama de bits, debe ingresar al dynamic_bitset
, obtener acceso al almacenamiento subyacente y extraer los bits usted mismo.
El código para hacer esto es trivial pero los datos (dynamic_bitset::m_bits
) están dentro de la parte privada de la clase. Hay tres formas de hackear el muro privado:
- Finja que el compilador no es conforme.
#define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
. Esto cambia private
a public
cambiando BOOST_DYNAMIC_BITSET_PRIVATE
.
- Hackear el encabezado
dynamic_bitset.hpp
para exponer m_bits
.
- La tercera solución es trabajar alrededor del código actual.
(1) y (2) son asaltos frágiles y frontales que serán una pesadilla de mantenimiento.
Afortunadamente para (3), hay funciones de plantilla que son friend
s de dynamic_bitset
. Podemos sustituir nuestra propia función para hacer nuestra propia extracción asumiendo (especializando) esta plantilla.
template <typename Block, typename Allocator, typename BlockOutputIterator>
inline void
to_block_range(const dynamic_bitset<Block, Allocator>& b,
BlockOutputIterator result)
{
std::copy(b.m_bits.begin(), b.m_bits.end(), result);
}
La plantilla copias función canónica del bitset toda a iterador BlockOutputIterator
que es no lo que queremos.
vamos a especializarse boost::to_block_range
utilizando un único tipo personalizado en lugar del BlockOutputIterator
que mantendrá la totalidad 3 i/o parámetros, a saber:
begin_bit
,
length_of_range
y
- destino.
Siempre que llame to_block_range
con el tipo requerido, se llamará a su propia función en lugar de la plantilla estándar, pero con pleno acceso a los componentes internos también. ¡Usted esencialmente ha subvertido el sistema de especificación de acceso de C++!
N.B.El código de ejemplo no verifica errores. Ningún intento para asegurarse de
- que el rango se ajusta a largo sin signo o
- que el rango no excede los límites de la bitset o
- que el bitset utiliza largos sin signo internamente.