diff --git a/doc/integer_mask.html b/doc/integer_mask.html
index 5bc7301..6dba489 100644
--- a/doc/integer_mask.html
+++ b/doc/integer_mask.html
@@ -8,7 +8,11 @@
Integer Bit Mask Templates
-The class templates in <boost/integer/integer_mask.hpp> provide bit masks for a certain bit position or a contiguous-bit pack of a certain size. The types of the masking constants come from the integer type selection templates header.
+The class templates in <boost/integer/integer_mask.hpp>
+provide bit masks for a certain bit position or a contiguous-bit pack of a
+certain size. The types of the masking constants come from the integer type selection templates header.
@@ -17,6 +21,7 @@ align="middle" width="277" height="86">Integer Bit Mask Templates
Synopsis
Single Bit-Mask Class Template
Group Bit-Mask Class Template
+ MPL-Compatible Variants
Example
Demonstration Program
Rationale
@@ -26,39 +31,68 @@ align="middle" width="277" height="86">Integer Bit Mask Templates
-#include <cstddef> // for std::size_t
+#include <boost/integer_fwd.hpp> // forwarding header
+#include <boost/integer.hpp> // for boost::int_fast_t
+#include <cstddef> // for std::size_t
namespace boost
{
-template < std::size_t Bit >
-struct high_bit_mask_t
+// MPL-compatible
+template < int Offset >
+struct integer_hi_mask
{
- typedef implementation_supplied least;
- typedef implementation_supplied fast;
+ static bool const is_specialized = implementation_supplied;
+ static int const bit_offset = Offset;
- static const least high_bit = implementation_defined;
- static const fast high_bit_fast = implementation_defined;
+ typedef implementation_supplied type;
+ typedef implementation_supplied value_type;
+ static value_type const value = implementation_supplied;
+ // There are other (optional) operations....
+};
+
+template < int Length >
+struct integer_lo_mask
+{
+ static bool const is_specialized = implementation_supplied;
+ static int const bit_count = Length;
+
+ typedef implementation_supplied type;
+ typedef implementation_supplied value_type;
+ static value_type const value = implementation_supplied;
+ // There are other (optional) operations....
+};
+
+// single
+template < std::size_t Bit >
+class high_bit_mask_t
+{
+public:
+ typedef typename integer_hi_mask<Bit>::value_type least;
+ typedef int_fast_t<least>::fast fast;
+
+ static const least high_bit = integer_hi_mask<Bit>::value;
+ static const fast high_bit_fast = high_bit;
static const std::size_t bit_position = Bit;
};
+// group
template < std::size_t Bits >
-struct low_bits_mask_t
+class low_bits_mask_t
{
- typedef implementation_supplied least;
- typedef implementation_supplied fast;
+public:
+ typedef typename integer_lo_mask<Bits>::value_type least;
+ typedef int_fast_t<least>::fast fast;
- static const least sig_bits = implementation_defined;
- static const fast sig_bits_fast = implementation_defined;
+ static const least sig_bits = integer_lo_mask<Bits>::value;
+ static const fast sig_bits_fast = sig_bits;
static const std::size_t bit_count = Bits;
};
-// Specializations for low_bits_mask_t exist for certain bit counts.
-
} // namespace boost
@@ -149,16 +183,149 @@ describes the members of an instantiation of
-Implementation Note
-When Bits
is the exact size of a built-in unsigned type,
-the implementation has to change to prevent undefined behavior.
-Therefore, there are specializations of low_bits_mask_t
at
-those bit counts.
+
+
+The single and group bit-mask class templates have several drawbacks:
+
+
+ - You must know the valid bit-lengths in advance.
+ - Using an inappropriate parameter value results in a compiler
+ diagnostic.
+ - The type names used are inconsistent with other transformations in
+ Boost, like in MPL.
+ - The above two facts make use of the regular bit-mask class templates
+ incompatible with template meta-programming techniques.
+
+
+The integer_hi_mask
and integer_lo_mask
class
+templates provide MPL-compatible alternatives. These alternatives have the
+form:
+
+
+template< int Size >
+struct name
+{
+ static bool const is_specialized = implementation_supplied;
+ static int const switch_id = Size;
+
+ typedef implementation_supplied type;
+ typedef implementation_supplied value_type;
+ static value_type const value = implementation_supplied;
+ // with other operations...
+};
+
+
+Only some of the members are always present. The presence of other members
+and operations is flagged by the (always-present) is_specialized
.
+
+
+ Permanent Members of the MPL-Compatible Masking Class Template
+ Types
+
+ Class Template Member |
+ Meaning |
+
+
+ is_specialized |
+ Flag indicating when a particular template class instantiation is a
+ valid meta-function (true ) or not (false ). |
+
+
+ switch_id (Actual name is template-specific.) |
+ The value of the main control parameter, accessible even if the
+ template class instantiation is aliased. |
+
+
+
+The optional members are based from inheriting from a MPL-style Integral
+Constant type, but only if is_specialized
is true
.
+
+
+ Optional Members of the MPL-Compatible Masking Types
+
+ Class Template Member |
+ Meaning |
+
+
+ value |
+ The actual bit mask. |
+
+
+ value_type |
+ The type of the bit mask value. |
+
+
+ type |
+ The Integral Constant implementation type, which should be
+ boost::mpl::
+ integral_c< value_type, value
+ > . |
+
+
+
+The Integral Constant prototype also adds the following operations:
+
+
+ Optional Operations of the MPL-Compatible Masking Types
+
+ Operation (with n as a masking type) |
+ Meaning |
+
+
+ boost::mpl::next< n >::type |
+ boost::mpl::next< n::type >::type , i.e.
+ boost::mpl::integral_c< n::value_type, n::value + 1
+ > . |
+
+
+ boost::mpl::prior< n >::type |
+ boost::mpl::prior< n::type >::type , i.e.
+ boost::mpl::integral_c< n::value_type, n::value - 1
+ > . |
+
+
+ n::value_type const c = n(); |
+ c is set to n::value . |
+
+
+
+The specifics for each masking class template are:
+
+
+ Criteria for the MPL-Compatible Masking Types
+ (Everything besides the parameter ID is in name-space
+ boost
except where indicated.)
+
+ Class Template |
+ Parameter Member ID |
+ Classic Equivalent |
+ Value Type |
+ Value |
+ Valid Range |
+
+
+ integer_hi_mask |
+ bit_offset |
+ high_bit_mask_t |
+ sized_integral < bit_offset + 1, unsigned > |
+ 2bit_offset |
+ 0 <= bit_offset < std::numeric_limits< uintmax_t >::digits |
+
+
+ integer_lo_mask |
+ bit_count |
+ low_bits_mask_t |
+ sized_integral < bit_count, unsigned > |
+ 2bit_offset - 1 |
+ 0 <= bit_count <= std::numeric_limits< uintmax_t >::digits |
+
+
-#include <boost/integer/integer_mask.hpp>
+#include <boost/integer/integer_mask.hpp>
//...
@@ -200,7 +367,7 @@ href="http://www.boost.org/people/daryle_walker.html">Daryle Walker.
-Revised September 23, 2001
+Revised July 29, 2008
© Copyright Daryle Walker 2001. Use, modification, and distribution are
subject to the Boost Software License, Version 1.0. (See accompanying file // self include
-#include // for BOOST_STATIC_CONSTANT
-#include // for boost::uint_t
+#include // for BOOST_STATIC_CONSTANT
+#include // for boost::uintmax_t
+#include // for boost::sized_integral
+#include // for std::numeric_limits
+#include // for boost::mpl::and_
+#include // for boost::mpl::bitor_, shift_left
+#include // for boost::mpl::true_
+#include // for boost::mpl::greater_equal, etc.
+#include // for boost::mpl::empty_base
+#include // for boost::mpl::if_
+#include // for boost::mpl::int_
+#include // for boost::integral_c
+#include // for boost::mpl::next, prior
+#include // for boost::enable_if
-#include // for BOOST_HAS_XINT, etc.
-
-#include // for UCHAR_MAX, etc.
#include // for std::size_t
-#include // for std::numeric_limits
-
namespace boost
{
+namespace detail
+{
+
+// Helper templates --------------------------------------------------------//
+
+template < int Bits >
+struct hi_integer_mask_builder1
+{
+ typedef boost::mpl::int_ bit_count_type;
+
+ typedef typename boost::mpl::next::type
+ mask_length_type;
+ typedef boost::sized_integral
+ mask_type;
+
+ typedef boost::mpl::integral_c one_type;
+ typedef boost::mpl::shift_left result_type;
+};
+
+template < int Bits >
+struct hi_integer_mask_builder2
+{
+ typedef boost::mpl::int_ bit_count_type;
+
+ typedef boost::mpl::greater_equal< bit_count_type, boost::mpl::int_<0> >
+ lo_bound_type;
+ typedef boost::mpl::less< bit_count_type,
+ boost::mpl::int_::digits> >
+ hi_bound_type;
+ typedef boost::mpl::and_ count_valid_type;
+};
+
+template < int Bits, class Enable = void >
+struct hi_integer_mask_builder3
+{
+ BOOST_STATIC_CONSTANT( bool, is_specialized = false );
+};
+
+template < int Bits >
+struct hi_integer_mask_builder3< Bits, typename boost::enable_if::count_valid_type>::type >
+ : hi_integer_mask_builder1::result_type
+{
+ BOOST_STATIC_CONSTANT( bool, is_specialized = true );
+};
+
+template < int Bits >
+struct lo_integer_mask_builder1
+{
+ typedef boost::mpl::int_ bit_count_type;
+
+ typedef typename boost::mpl::prior::type
+ shift_length_type;
+ typedef boost::sized_integral
+ mask_type;
+
+ typedef boost::mpl::integral_c one_type;
+ typedef boost::mpl::shift_left
+ high_bit_type;
+ typedef typename boost::mpl::prior::type low_bits_type;
+ typedef boost::mpl::bitor_ result_type;
+};
+
+template < >
+struct lo_integer_mask_builder1< 0 >
+{
+ // Let's not deal with negative interim values....
+ typedef boost::mpl::integral_c result_type;
+};
+
+template < int Bits >
+struct lo_integer_mask_builder2
+{
+ typedef boost::mpl::int_ bit_count_type;
+
+ typedef boost::mpl::greater_equal< bit_count_type, boost::mpl::int_<0> >
+ lo_bound_type;
+ typedef boost::mpl::less_equal< bit_count_type,
+ boost::mpl::int_::digits> >
+ hi_bound_type;
+ typedef boost::mpl::and_ count_valid_type;
+};
+
+template < >
+struct lo_integer_mask_builder2< 0 >
+{
+ typedef boost::mpl::true_ count_valid_type;
+};
+
+template < int Bits, class Enable = void >
+struct lo_integer_mask_builder3
+{
+ BOOST_STATIC_CONSTANT( bool, is_specialized = false );
+ // No MPL Integral Constant to inherit from
+};
+
+template < int Bits >
+struct lo_integer_mask_builder3< Bits, typename enable_if::count_valid_type>::type >
+ : lo_integer_mask_builder1::result_type
+{
+ BOOST_STATIC_CONSTANT( bool, is_specialized = true );
+};
+
+} // namespace detail
+
+
+// MPL-compatible integer mask class templates -----------------------------//
+
+// Displaced single-bit mask, 1 << Offset, 0 <= Offset < BitLengthOf(uintmax_t)
+template < int Offset >
+struct integer_hi_mask
+ : detail::hi_integer_mask_builder3
+{
+ BOOST_STATIC_CONSTANT( int, bit_offset = Offset );
+};
+
+// Lowest bit-group mask, 2**Length - 1, 0 <= Length <= BitLengthOf(uintmax_t)
+template < int Length >
+struct integer_lo_mask
+ : detail::lo_integer_mask_builder3
+{
+ BOOST_STATIC_CONSTANT( int, bit_count = Length );
+};
// Specified single-bit mask class declaration -----------------------------//
// (Lowest bit starts counting at 0.)
template < std::size_t Bit >
-struct high_bit_mask_t
+class high_bit_mask_t
{
- typedef typename uint_t<(Bit + 1)>::least least;
- typedef typename uint_t<(Bit + 1)>::fast fast;
+ typedef integer_hi_mask impl_type;
- BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << Bit) );
- BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << Bit) );
+public:
+ typedef typename impl_type::value_type least;
+ typedef typename int_fast_t::fast fast;
- BOOST_STATIC_CONSTANT( std::size_t, bit_position = Bit );
+ BOOST_STATIC_CONSTANT( least, high_bit = impl_type::value );
+ BOOST_STATIC_CONSTANT( fast, high_bit_fast = impl_type::value );
+
+ BOOST_STATIC_CONSTANT( std::size_t, bit_position = impl_type::bit_offset );
}; // boost::high_bit_mask_t
// Specified bit-block mask class declaration ------------------------------//
// Makes masks for the lowest N bits
-// (Specializations are needed when N fills up a type.)
template < std::size_t Bits >
-struct low_bits_mask_t
+class low_bits_mask_t
{
- typedef typename uint_t::least least;
- typedef typename uint_t::fast fast;
+ typedef integer_lo_mask impl_type;
- BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) );
- BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) );
+public:
+ typedef typename impl_type::value_type least;
+ typedef typename int_fast_t::fast fast;
- BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits );
+ BOOST_STATIC_CONSTANT( least, sig_bits = impl_type::value );
+ BOOST_STATIC_CONSTANT( fast, sig_bits_fast = impl_type::value );
+
+ BOOST_STATIC_CONSTANT( std::size_t, bit_count = impl_type::bit_count );
}; // boost::low_bits_mask_t
-#define BOOST_LOW_BITS_MASK_SPECIALIZE( Type ) \
- template < > struct low_bits_mask_t< std::numeric_limits::digits > { \
- typedef std::numeric_limits limits_type; \
- typedef uint_t::least least; \
- typedef uint_t::fast fast; \
- BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); \
- BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); \
- BOOST_STATIC_CONSTANT( std::size_t, bit_count = limits_type::digits ); \
- }
-
-BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned char );
-
-#if USHRT_MAX > UCHAR_MAX
-BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned short );
-#endif
-
-#if UINT_MAX > USHRT_MAX
-BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned int );
-#endif
-
-#if ULONG_MAX > UINT_MAX
-BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned long );
-#endif
-
-#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX)
-BOOST_LOW_BITS_MASK_SPECIALIZE( ::boost::detail::uxint_t );
-#endif
-
-#undef BOOST_LOW_BITS_MASK_SPECIALIZE
-
-
} // namespace boost
diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp
index e15385a..3ece2e3 100644
--- a/include/boost/integer_fwd.hpp
+++ b/include/boost/integer_fwd.hpp
@@ -9,12 +9,10 @@
#ifndef BOOST_INTEGER_FWD_HPP
#define BOOST_INTEGER_FWD_HPP
-#include // for UCHAR_MAX, etc.
#include // for std::size_t
-#include // for BOOST_NO_INTRINSIC_WCHAR_T
+#include // for BOOST_NO_INTRINSIC_WCHAR_T, etc.
#include // for boost::uintmax_t, intmax_t
-#include // for std::numeric_limits
#include // for BOOST_HAS_XINT, etc.
@@ -131,35 +129,17 @@ template< uintmax_t Value >
// From -----------------------------------//
+template < int Offset >
+ struct integer_hi_mask;
+
+template < int Length >
+ struct integer_lo_mask;
+
template < std::size_t Bit >
- struct high_bit_mask_t;
+ class high_bit_mask_t;
template < std::size_t Bits >
- struct low_bits_mask_t;
-
-template < >
- struct low_bits_mask_t< ::std::numeric_limits::digits >;
-
-#if USHRT_MAX > UCHAR_MAX
-template < >
- struct low_bits_mask_t< ::std::numeric_limits::digits >;
-#endif
-
-#if UINT_MAX > USHRT_MAX
-template < >
- struct low_bits_mask_t< ::std::numeric_limits::digits >;
-#endif
-
-#if ULONG_MAX > UINT_MAX
-template < >
- struct low_bits_mask_t< ::std::numeric_limits::digits >;
-#endif
-
-#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX)
-template < >
- struct low_bits_mask_t< ::std::numeric_limits< ::boost::detail::uxint_t
- >::digits >;
-#endif
+ class low_bits_mask_t;
// From ------------------------------------//
diff --git a/test/integer_mask_test.cpp b/test/integer_mask_test.cpp
index 99a22b0..65b6fc2 100644
--- a/test/integer_mask_test.cpp
+++ b/test/integer_mask_test.cpp
@@ -8,6 +8,8 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
+// 29 Jul 2008 Added MPL-compatible variants of the integer-mask templates.
+// (Daryle Walker)
// 27 Jul 2008 Changed tests to use the unit-test system; added
// extended-integer support. (Daryle Walker)
// 23 Sep 2001 Initial version (Daryle Walker)
@@ -18,24 +20,72 @@
#include // for boost::uintmax_t
#include // for boost::high_bit_mask_t, etc.
#include // for std::numeric_limits
-#include // for BOOST_MPL_ASSERT_RELATION
+#include // for BOOST_MPL_ASSERT_RELATION,etc.
+#include // for boost::mpl::bool_
+#include // for boost::mpl::bitor_, shift_left
+#include // for boost::mpl::equal_to
+#include // for boost::mpl::int_
+#include // for boost::mpl::integral_c
+#include // for boost::mpl::prior
#include // for boost::mpl::range_c
#include // for std::size_t
+#include // for std::hex
+#include // for std::cout
+#include // for std::endl
+
+
+// Control if events will be printed conventionally, or just logged.
+#ifndef CONTROL_SHOW_TYPES
+#define CONTROL_SHOW_TYPES 0
+#endif
+
+// Logging
+#if CONTROL_SHOW_TYPES
+#define PRIVATE_SHOW_MESSAGE( m ) std::cout << m << std::endl
+#else
+#define PRIVATE_SHOW_MESSAGE( m ) BOOST_TEST_MESSAGE( m )
+#endif
// Custom types/templates, helper functions, and objects
namespace
{
-// A big one
-boost::uintmax_t const one = 1u;
-
// List the ranges of template parameters tests (ranges are half-open)
int const max_offset = std::numeric_limits::digits;
-typedef boost::mpl::range_c high_bit_offsets;
-typedef boost::mpl::range_c low_bit_lengths;
+typedef boost::mpl::range_c high_bit_offsets;
+typedef boost::mpl::range_c low_bit_lengths;
+typedef boost::mpl::range_c special_low_bit_lengths;
+
+// List a range with out-of-service values
+typedef boost::mpl::range_c wild_bit_lengths;
+
+// Use SFINAE to check if a particular parameter is supported
+template < typename ValueT, template class Tmpl, ValueT Value >
+bool
+print_out_template( Tmpl const &, ValueT setting, char const
+ *template_name, typename Tmpl::type *unused = 0 )
+{
+ // Too bad the type-id expression couldn't use the compact form "*unused",
+ // but type-ids of dereferenced null pointers throw by order of C++ 2003,
+ // sect. 5.2.8, para. 2 (although the result is not conceptually needed).
+ PRIVATE_SHOW_MESSAGE( "There is an " << template_name << "<" << setting <<
+ "> specialization with type '" << typeid(typename
+ Tmpl::value_type).name() << "' and value '" << std::hex <<
+ Tmpl::value << "'." );
+ return true;
+}
+
+template < typename ValueT, typename T >
+bool
+print_out_template( T const &, ValueT setting, char const *template_name )
+{
+ PRIVATE_SHOW_MESSAGE( "There is no " << template_name << "<" << setting <<
+ "> specialization." );
+ return false;
+}
} // unnamed namespace
@@ -46,14 +96,18 @@ BOOST_AUTO_TEST_SUITE( integer_mask_tests )
// Check the bit-masks of one offset bit
BOOST_AUTO_TEST_CASE_TEMPLATE( high_bit_mask_test, T, high_bit_offsets )
{
+ typedef boost::mpl::integral_c::least, 1u> one_type;
+ typedef boost::mpl::shift_left result_type;
+
BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit, ==,
- (one << T::value) );
+ result_type::value );
BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit_fast,
- ==, (one << T::value) );
+ ==, result_type::value );
}
-// Check the bit-masks of a block of low-valued bits
-BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths )
+// Check the bit-masks of a block of low-valued bits, non-zero block-lengths
+BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, special_low_bit_lengths )
{
// One can express (2^x - 1) in two ways
// 1. (1 << x) - 1
@@ -62,10 +116,51 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths )
// when x is the number of bits in the register. However, that last case
// gives warnings about the sole bit flowing past the register. Applying
// distributive property backwards gives [2], which works without overflow.
+ typedef typename boost::mpl::prior::type shift_type;
+ typedef boost::mpl::integral_c::least, 1u> one_type;
+ typedef boost::mpl::shift_left high_bit_type;
+ typedef typename boost::mpl::prior::type low_bits_type;
+ typedef boost::mpl::bitor_ result_type;
+
BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits, ==,
- (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) );
+ result_type::value );
BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits_fast,
- ==, (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) );
+ ==, result_type::value );
+}
+
+// Check the bit-masks of a block of low-valued bits, zero block-length
+BOOST_AUTO_TEST_CASE( special_low_bits_mask_test )
+{
+ // Just like "low_bits_mask_test" above, except that the shifts are negative
+ // when the bit-count is zero. That causes a lot of warnings and errors, so
+ // special-case that bit-count.
+ BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t<0u>::sig_bits, ==, 0 );
+ BOOST_MPL_ASSERT_RELATION(boost::low_bits_mask_t<0u>::sig_bits_fast, ==, 0);
+}
+
+// Check the specialization type status of given bit-offsets/lengths
+BOOST_AUTO_TEST_CASE_TEMPLATE( confirm_bounds_test, T, wild_bit_lengths )
+{
+ typedef boost::integer_hi_mask hi_type;
+ typedef boost::mpl::int_ hi_offset_type;
+ typedef boost::mpl::bool_ special_hi_type;
+
+ BOOST_MPL_ASSERT( (boost::mpl::equal_to< hi_offset_type, T >) );
+ BOOST_MPL_ASSERT( (boost::mpl::equal_to< special_hi_type,
+ boost::mpl::bool_<(T::value >= 0) && (T::value < max_offset)> >) );
+ BOOST_CHECK_EQUAL( print_out_template(hi_type(), hi_offset_type::value,
+ "integer_hi_mask"), special_hi_type::value );
+
+ typedef boost::integer_lo_mask lo_type;
+ typedef boost::mpl::int_ lo_length_type;
+ typedef boost::mpl::bool_ special_lo_type;
+
+ BOOST_MPL_ASSERT( (boost::mpl::equal_to< lo_length_type, T >) );
+ BOOST_MPL_ASSERT( (boost::mpl::equal_to< special_lo_type,
+ boost::mpl::bool_<(T::value >= 0) && (T::value <= max_offset)> >) );
+ BOOST_CHECK_EQUAL( print_out_template(lo_type(), lo_length_type::value,
+ "integer_lo_mask"), special_lo_type::value );
}
BOOST_AUTO_TEST_SUITE_END()