Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r48695 - trunk/libs/dynamic_bitset
From: gennaro.prota_at_[hidden]
Date: 2008-09-10 06:07:47


Author: gennaro_prota
Date: 2008-09-10 06:07:46 EDT (Wed, 10 Sep 2008)
New Revision: 48695
URL: http://svn.boost.org/trac/boost/changeset/48695

Log:
added specific tests for constructor dispatch and clarified the corresponding comments a bit; minor formatting consistency fixes; updated documentation and added license reference text to it
Text files modified:
   trunk/libs/dynamic_bitset/bitset_test.hpp | 45 ++++++++++------
   trunk/libs/dynamic_bitset/dyn_bitset_unit_tests1.cpp | 99 +++++++++++++++++++++++++++++++------
   trunk/libs/dynamic_bitset/dynamic_bitset.html | 103 +++++++++++++++++++++++++++++++--------
   3 files changed, 190 insertions(+), 57 deletions(-)

Modified: trunk/libs/dynamic_bitset/bitset_test.hpp
==============================================================================
--- trunk/libs/dynamic_bitset/bitset_test.hpp (original)
+++ trunk/libs/dynamic_bitset/bitset_test.hpp 2008-09-10 06:07:46 EDT (Wed, 10 Sep 2008)
@@ -1,6 +1,6 @@
 // -----------------------------------------------------------
 // Copyright (c) 2001 Jeremy Siek
-// Copyright (c) 2003-2006 Gennaro Prota
+// 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
@@ -108,32 +108,43 @@
 // constructors
 // default (can't do this generically)
 
-// from unsigned long
-
 template <typename Bitset>
 struct bitset_test {
 
   typedef typename Bitset::block_type Block;
   BOOST_STATIC_CONSTANT(int, bits_per_block = Bitset::bits_per_block);
 
-
- static void from_unsigned_long(std::size_t sz, unsigned long num)
+ // from unsigned long
+ //
+ // Note: this is templatized so that we check that the do-the-right-thing
+ // constructor dispatch is working correctly.
+ //
+ template <typename NumBits, typename Value>
+ static void from_unsigned_long(NumBits num_bits, Value num)
   {
- // An object of size N = sz is constructed:
- // - the first M bit positions are initialized to the corresponding bit
- // values in num (M being the smaller of N and the width of unsigned
- // long)
+ // An object of size sz = num_bits is constructed:
+ // - the first m bit positions are initialized to the corresponding
+ // bit values in num (m being the smaller of sz and ulong_width)
+ //
+ // - any remaining bit positions are initialized to zero
     //
- // - if M < N remaining bit positions are initialized to zero
 
- Bitset b(sz, num);
+ Bitset b(num_bits, num);
+
+ // OK, we can now cast to size_type
+ typedef typename Bitset::size_type size_type;
+ const size_type sz = static_cast<size_type>(num_bits);
+
     BOOST_CHECK(b.size() == sz);
 
     const std::size_t ulong_width = std::numeric_limits<unsigned long>::digits;
- std::size_t m = (std::min)(sz, ulong_width);
- std::size_t i;
- for (i = 0; i < m; ++i)
- BOOST_CHECK(b.test(i) == nth_bit(num, i));
+ size_type m = sz;
+ if (ulong_width < sz)
+ m = ulong_width;
+
+ size_type i = 0;
+ for ( ; i < m; ++i)
+ BOOST_CHECK(b.test(i) == nth_bit(static_cast<unsigned long>(num), i));
     for ( ; i < sz; ++i)
       BOOST_CHECK(b.test(i) == 0);
   }
@@ -978,7 +989,7 @@
   //-------------------------------------------------------------------------
 
   // operator<<( [basic_]ostream,
- template<typename Stream>
+ template <typename Stream>
   static void stream_inserter(const Bitset & b,
                               Stream & s,
                               const char * file_name
@@ -1058,7 +1069,7 @@
   }
 
   // operator>>( [basic_]istream
- template<typename Stream, typename String>
+ template <typename Stream, typename String>
   static void stream_extractor(Bitset& b,
                                Stream& is,
                                String& str

Modified: trunk/libs/dynamic_bitset/dyn_bitset_unit_tests1.cpp
==============================================================================
--- trunk/libs/dynamic_bitset/dyn_bitset_unit_tests1.cpp (original)
+++ trunk/libs/dynamic_bitset/dyn_bitset_unit_tests1.cpp 2008-09-10 06:07:46 EDT (Wed, 10 Sep 2008)
@@ -15,7 +15,7 @@
 
 #include "boost/detail/workaround.hpp"
 
-#define BOOST_BITSET_TEST_COUNT_OF(x) (sizeof(x)/sizeof(x[0]))
+#define BOOST_BITSET_TEST_COUNT(x) (sizeof(x)/sizeof(x[0]))
 
 
 // Codewarrior 8.3 for Win fails without this.
@@ -54,6 +54,43 @@
 
 }
 
+// tests the do-the-right-thing constructor dispatch
+template <typename Tests, typename T>
+void run_numeric_ctor_tests( BOOST_EXPLICIT_TEMPLATE_TYPE(Tests)
+ BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T) )
+{
+
+ const int bits_per_block = Tests::bits_per_block;
+ const int width = std::numeric_limits<T>::digits;
+ const T ma = (std::numeric_limits<T>::max)();
+ const T mi = (std::numeric_limits<T>::min)();
+
+ int sizes[] = {
+ 0, 7*width/10, width, 13*width/10, 3*width,
+ 7*bits_per_block/10, bits_per_block, 13*bits_per_block/10, 3*bits_per_block
+ };
+
+ const T numbers[] = {
+ T(-1), T(-3), T(-8), T(-15), mi/2, mi,
+ 0, 1, 3, 8, 15, ma/2, ma
+ };
+
+ for (std::size_t s = 0; s < BOOST_BITSET_TEST_COUNT(sizes); ++s) {
+ for (std::size_t n = 0; n < BOOST_BITSET_TEST_COUNT(numbers); ++n ) {
+
+ // can match ctor from ulong or templated one
+ Tests::from_unsigned_long(sizes[s], numbers[n]);
+
+ // can match templated ctor only (so we test dispatching)
+ assert( sizes[s] < (std::numeric_limits<char>::max)() );
+ Tests::from_unsigned_long(static_cast<T>(sizes[s]), numbers[n]);
+
+ }
+ }
+
+}
+
+
 template <typename Block>
 void run_test_cases( BOOST_EXPLICIT_TEMPLATE_TYPE(Block) )
 {
@@ -67,24 +104,52 @@
   //=====================================================================
   // Test construction from unsigned long
   {
- typedef unsigned long source_type;
- const std::size_t source_width = std::numeric_limits<source_type>::digits;
- const source_type source_max =(std::numeric_limits<source_type>::max)();
-
- source_type numbers[] = { 0, 1, 40247, source_max >> 1, source_max };
- std::size_t sizes[] =
- { 0, 7 * source_width / 10, source_width, 13 * source_width / 10,
- 7 * bits_per_block / 10, bits_per_block, 13 * bits_per_block / 10,
- 3 * bits_per_block };
-
- const std::size_t value_count = BOOST_BITSET_TEST_COUNT_OF(numbers);
- const std::size_t size_count = BOOST_BITSET_TEST_COUNT_OF(sizes);
-
- for (std::size_t v = 0; v < value_count; ++v) {
- for (std::size_t s = 0; s < size_count; ++s) {
- Tests::from_unsigned_long(sizes[s], numbers[v]);
+ typedef typename bitset_type::size_type size_type;
+
+
+ // NOTE:
+ //
+ // 1. keep this in sync with the numeric types supported
+ // for constructor dispatch (of course)
+ // 2. bool is tested separately; ugly and inelegant, but
+ // we don't have much time to think of a better solution
+ // which is likely to work on broken compilers
+ //
+ const int sizes[] = {
+ 0, 1, 3,
+ 7*bits_per_block/10, bits_per_block, 13*bits_per_block/10, 3*bits_per_block
+ };
+
+ const bool values[] = { false, true };
+
+ for (std::size_t s = 0; s < BOOST_BITSET_TEST_COUNT(sizes); ++s) {
+ for (std::size_t v = 0; v < BOOST_BITSET_TEST_COUNT(values); ++v) {
+ Tests::from_unsigned_long(sizes[s], values[v]);
+ Tests::from_unsigned_long(sizes[s] != 0, values[v]);
       }
     }
+
+ run_numeric_ctor_tests<Tests, char>();
+
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+ run_numeric_ctor_tests<Tests, wchar_t>();
+#endif
+
+ run_numeric_ctor_tests<Tests, signed char>();
+ run_numeric_ctor_tests<Tests, short int>();
+ run_numeric_ctor_tests<Tests, int>();
+ run_numeric_ctor_tests<Tests, long int>();
+
+ run_numeric_ctor_tests<Tests, unsigned char>();
+ run_numeric_ctor_tests<Tests, unsigned short>();
+ run_numeric_ctor_tests<Tests, unsigned int>();
+ run_numeric_ctor_tests<Tests, unsigned long>();
+
+#if defined(BOOST_HAS_LONG_LONG)
+ run_numeric_ctor_tests<Tests, ::boost::long_long_type>();
+ run_numeric_ctor_tests<Tests, ::boost::ulong_long_type>();
+#endif
+
   }
   //=====================================================================
   // Test construction from a string

Modified: trunk/libs/dynamic_bitset/dynamic_bitset.html
==============================================================================
--- trunk/libs/dynamic_bitset/dynamic_bitset.html (original)
+++ trunk/libs/dynamic_bitset/dynamic_bitset.html 2008-09-10 06:07:46 EDT (Wed, 10 Sep 2008)
@@ -574,11 +574,20 @@
 
 <b>Effects:</b> Constructs a bitset from an integer. The first
 <tt>M</tt> bits are initialized to the corresponding bits in
-<tt>val</tt> and all other bits, if any, to zero (where <tt>M =
+<tt>value</tt> and all other bits, if any, to zero (where <tt>M =
 min(num_bits, std::numeric_limits&lt;unsigned long&gt;::digits)</tt>). A copy of
 the <tt>alloc</tt> object will be used in subsequent bitset
-operations such as <tt>resize</tt> to allocate memory.<br />
- <b>Postconditions:</b>
+operations such as <tt>resize</tt> to allocate memory. Note that, e.g., the
+following
+<br /><br />
+<tt>
+dynamic_bitset b<>( 16, 7 );
+</tt><br /><br />
+will match the constructor from an iterator range (not this
+one), but the underlying implementation will still "do the right thing" and
+construct a bitset of 16 bits, from the value 7.
+<br />
+<b>Postconditions:</b>
 
 <ul>
 <li><tt>this-&gt;size() == num_bits</tt></li>
@@ -620,24 +629,56 @@
                const Allocator&amp; alloc = Allocator());
 </pre>
 
-<b>Effects:</b> Constructs a bitset based on a range of blocks.
-Let <tt>*first</tt> be block number 0, <tt>*++first</tt> block
-number 1, etc. Block number <tt>b</tt> is used to initialize the
-bits of the dynamic_bitset in the position range
-<tt>[b*bits_per_block, (b+1)*bits_per_block)</tt>. For each block
-number <tt>b</tt> with value <tt>bval</tt>, the bit <tt>(bval
-&gt;&gt; i) &amp; 1</tt> corresponds to the bit at position
-<tt>(b * bits_per_block + i)</tt> in the bitset (where <tt>i</tt>
-goes through the range <tt>[0, bits_per_block)</tt>).<br />
- <b>Requires:</b> The type <tt>BlockInputIterator</tt> must be a
-model of <a href=
-"http://www.sgi.com/tech/stl/InputIterator.html">Input
-Iterator</a> and its <tt>value_type</tt> must be the same type as
-<tt>Block</tt>.<br />
- <b>Throws:</b> An allocation error if memory is exhausted
-(<tt>std::bad_alloc</tt> if
-<tt>Allocator=std::allocator</tt>).<br />
-
+<b>Effects:</b>
+<ul>
+<li>
+If this constructor is called with a type <tt>BlockInputIterator</tt> which
+<i>is actually an integral type</i>, the library behaves as if the constructor
+from <tt>unsigned long</tt> had been called, with arguments
+<tt>static_cast&lt;size_type&gt;(first), last and alloc</tt>, in that order.
+
+Example:
+<pre>
+// b is constructed as if by calling the constructor
+//
+// dynamic_bitset(size_type num_bits,
+// unsigned long value = 0,
+// const Allocator&amp; alloc = Allocator())
+//
+// with arguments
+//
+// static_cast&lt;dynamic_bitset&lt;unsigned short&gt;::size_type&gt;(8),
+// 7,
+// Allocator()
+//
+dynamic_bitset&lt;unsigned short&gt; b(8, 7);
+</pre><br />
+<i>Note:</i><br/>
+This is analogous to what the standard mandates for sequence containers (namely,
+that if the type on which the template constructor is intantiated "does not
+qualify as an input iterator" then the other constructor is called; "the extent
+to which an implementation determines that a type cannot be an input iterator is
+unspecified, except that as a minimum integral types shall not qualify as input
+iterators").<br /><br />
+</li>
+<li>
+<i>Otherwise</i> (<i>i.e.</i> if the template argument is not an integral
+type), constructs&mdash;under the condition in the <tt>requires</tt>
+clause&mdash;a bitset based on a range of blocks. Let <tt>*first</tt> be block
+number 0, <tt>*++first</tt> block number 1, etc. Block number <tt>b</tt> is used
+to initialize the bits of the dynamic_bitset in the position range
+<tt>[b*bits_per_block, (b+1)*bits_per_block)</tt>. For each block number
+<tt>b</tt> with value <tt>bval</tt>, the bit <tt>(bval &gt;&gt; i) &amp; 1</tt>
+corresponds to the bit at position <tt>(b * bits_per_block + i)</tt> in the
+bitset (where <tt>i</tt> goes through the range <tt>[0, bits_per_block)</tt>).
+</li>
+</ul>
+<br />
+<b>Requires:</b> <tt>BlockInputIterator</tt> must be either an integral type or
+a model of <a href= "http://www.sgi.com/tech/stl/InputIterator.html">Input
+ Iterator</a> whose <tt>value_type</tt> is the same type as
+<tt>Block</tt>.<br /> <b>Throws:</b> An allocation error if memory is exhausted
+(<tt>std::bad_alloc</tt> if <tt>Allocator=std::allocator</tt>).<br />
 
 <hr />
 <pre>
@@ -1436,11 +1477,17 @@
 <h3><a id="exception-guarantees">Exception guarantees</a></h3>
 
 All of <tt>dynamic_bitset</tt> functions offer at least the basic
-exception guarantee.
+exception guarantee.
 
 <hr />
 <h3><a id="changes-from-previous-ver">Changes from previous version(s)</a></h3>
 
+<h4><i>Changes in Boost 1.37.0</i></h4>
+<ul>
+<li>The constructor from a block-range implements a <i>do-the-right-thing</i>
+behavior, a la standard sequences.</li>
+</ul>
+
 <!-- Changes from Boost 1.31.0 -->
 <h4><i>Changes from Boost 1.31.0</i></h4>
 <ul>
@@ -1514,9 +1561,19 @@
 C/C++ Users Journal (<a
 href="mailto:cda_at_[hidden]">cda_at_[hidden]</a>)<br
 /></td> </tr> <tr>
-<td>Copyright &copy; 2003-2004, 2008</td> <td>Gennaro Prota</td>
+<td>Copyright &copy; 2003-2004, 2008</td> <td><a
+ href="http://gennaro-prota.50webs.com/">Gennaro Prota</a>
+ (name.surname yahoo.com)</td>
 </tr>
 </table>
+<br />
+<div class="legalnotice">
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt
+ or copy at <a class="ulink" href="http://www.boost.org/LICENSE_1_0.txt">
+http://www.boost.org/LICENSE_1_0.txt>)
+</div>
+
 
 </div>
 </div>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk