Squashed 'third_party/boostorg/utility/' content from commit ebe4429

Change-Id: I8e6ee78273db31df18f99d29034f855ccc064551
git-subtree-dir: third_party/boostorg/utility
git-subtree-split: ebe44296ca698e333a09e8268ea8ccedb3886c4d
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
new file mode 100644
index 0000000..7fd5b2f
--- /dev/null
+++ b/test/Jamfile.v2
@@ -0,0 +1,43 @@
+# Copyright David Abrahams 2003.
+
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+# For more information, see http://www.boost.org/
+
+# bring in rules for testing
+import testing ;
+
+run base_from_member_test.cpp ;
+run base_from_member_ref_test.cpp ;
+
+run binary_test.cpp ;
+
+run call_traits_test.cpp : -u ;
+
+run compressed_pair_test.cpp ;
+
+run iterators_test.cpp ;
+
+run operators_test.cpp ;
+
+compile result_of_test.cpp ;
+
+# compile-fail string_ref_from_rvalue.cpp ;
+run string_ref_test1.cpp ;
+run string_ref_test2.cpp ;
+run string_ref_test_io.cpp ;
+# compile-fail string_view_from_rvalue.cpp ;
+compile string_view_constexpr_test1.cpp ;
+run string_view_test1.cpp ;
+run string_view_test2.cpp ;
+run string_view_test_io.cpp ;
+
+run value_init_test.cpp ;
+run value_init_workaround_test.cpp ;
+run initialized_test.cpp ;
+compile-fail value_init_test_fail1.cpp ;
+compile-fail value_init_test_fail2.cpp ;
+compile-fail value_init_test_fail3.cpp ;
+compile-fail initialized_test_fail1.cpp ;
+compile-fail initialized_test_fail2.cpp ;
diff --git a/test/base_from_member_ref_test.cpp b/test/base_from_member_ref_test.cpp
new file mode 100644
index 0000000..52f9b87
--- /dev/null
+++ b/test/base_from_member_ref_test.cpp
@@ -0,0 +1,29 @@
+//
+// Test that a base_from_member<T&> can be properly constructed
+//
+// Copyright 2014 Agustin Berge
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <boost/utility/base_from_member.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+struct foo : boost::base_from_member<int&>
+{
+    explicit foo(int& ref) : boost::base_from_member<int&>(ref)
+    {
+        BOOST_TEST(&member == &ref);
+    }
+};
+
+int main()
+{
+    int i = 0;
+    foo f(i);
+
+    return boost::report_errors();
+}
diff --git a/test/base_from_member_test.cpp b/test/base_from_member_test.cpp
new file mode 100644
index 0000000..685c638
--- /dev/null
+++ b/test/base_from_member_test.cpp
@@ -0,0 +1,593 @@
+//  Boost test program for base-from-member class templates  -----------------//
+
+//  Copyright 2001, 2003 Daryle Walker.  Use, modification, and distribution are
+//  subject to the Boost Software License, Version 1.0.  (See accompanying file
+//  LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+//  See <http://www.boost.org/libs/utility/> for the library's home page.
+
+//  Revision History
+//  14 Jun 2003  Adjusted code for Boost.Test changes (Daryle Walker)
+//  29 Aug 2001  Initial Version (Daryle Walker)
+
+#include <boost/core/lightweight_test.hpp>
+
+#include <boost/config.hpp>       // for BOOST_NO_MEMBER_TEMPLATES
+#include <boost/noncopyable.hpp>  // for boost::noncopyable
+
+#include <boost/utility/base_from_member.hpp>  // for boost::base_from_member
+
+#include <functional>  // for std::less
+#include <iostream>    // for std::cout (std::ostream, std::endl indirectly)
+#include <set>         // for std::set
+#include <typeinfo>    // for std::type_info
+#include <utility>     // for std::pair, std::make_pair
+#include <vector>      // for std::vector
+
+
+// Control if extra information is printed
+#ifndef CONTROL_EXTRA_PRINTING
+#define CONTROL_EXTRA_PRINTING  1
+#endif
+
+
+// A (sub)object can be identified by its memory location and its type.
+// Both are needed since an object can start at the same place as its
+// first base class subobject and/or contained subobject.
+typedef std::pair< void *, std::type_info const * >  object_id;
+
+// Object IDs need to be printed
+std::ostream &  operator <<( std::ostream &os, object_id const &oi );
+
+// A way to generate an object ID
+template < typename T >
+  object_id  identify( T &obj );
+
+// A custom comparison type is needed
+struct object_id_compare
+{
+    bool  operator ()( object_id const &a, object_id const &b ) const;
+
+};  // object_id_compare
+
+// A singleton of this type coordinates the acknowledgements
+// of objects being created and used.
+class object_registrar
+    : private boost::noncopyable
+{
+public:
+
+    #ifndef BOOST_NO_MEMBER_TEMPLATES
+    template < typename T >
+        void  register_object( T &obj )
+            { this->register_object_imp( identify(obj) ); }
+    template < typename T, typename U >
+        void  register_use( T &owner, U &owned )
+            { this->register_use_imp( identify(owner), identify(owned) ); }
+    template < typename T, typename U >
+        void  unregister_use( T &owner, U &owned )
+            { this->unregister_use_imp( identify(owner), identify(owned) ); }
+    template < typename T >
+        void  unregister_object( T &obj )
+            { this->unregister_object_imp( identify(obj) ); }
+    #endif
+
+    void  register_object_imp( object_id obj );
+    void  register_use_imp( object_id owner, object_id owned );
+    void  unregister_use_imp( object_id owner, object_id owned );
+    void  unregister_object_imp( object_id obj );
+
+    typedef std::set<object_id, object_id_compare>  set_type;
+
+    typedef std::vector<object_id>  error_record_type;
+    typedef std::vector< std::pair<object_id, object_id> >  error_pair_type;
+
+    set_type  db_;
+
+    error_pair_type    defrauders_in_, defrauders_out_;
+    error_record_type  overeager_, overkilled_;
+
+};  // object_registrar
+
+// A sample type to be used by containing types
+class base_or_member
+{
+public:
+    explicit  base_or_member( int x = 1, double y = -0.25 );
+             ~base_or_member();
+
+};  // base_or_member
+
+// A sample type that uses base_or_member, used
+// as a base for the main demonstration classes
+class base_class
+{
+public:
+    explicit  base_class( base_or_member &x, base_or_member *y = 0,
+     base_or_member *z = 0 );
+
+    ~base_class();
+
+private:
+    base_or_member  *x_, *y_, *z_;
+
+};  // base_class
+
+// This bad class demonstrates the direct method of a base class needing
+// to be initialized by a member.  This is improper since the member
+// isn't initialized until after the base class.
+class bad_class
+    : public base_class
+{
+public:
+     bad_class();
+    ~bad_class();
+
+private:
+    base_or_member  x_;
+
+};  // bad_class
+
+// The first good class demonstrates the correct way to initialize a
+// base class with a member.  The member is changed to another base
+// class, one that is initialized before the base that needs it.
+class good_class_1
+    : private boost::base_from_member<base_or_member>
+    , public base_class
+{
+    typedef boost::base_from_member<base_or_member>  pbase_type;
+    typedef base_class                                base_type;
+
+public:
+     good_class_1();
+    ~good_class_1();
+
+};  // good_class_1
+
+// The second good class also demonstrates the correct way to initialize
+// base classes with other subobjects.  This class uses the other helpers
+// in the library, and shows the technique of using two base subobjects
+// of the "same" type.
+class good_class_2
+    : private boost::base_from_member<base_or_member, 0>
+    , private boost::base_from_member<base_or_member, 1>
+    , private boost::base_from_member<base_or_member, 2>
+    , public base_class
+{
+    typedef boost::base_from_member<base_or_member, 0>  pbase_type0;
+    typedef boost::base_from_member<base_or_member, 1>  pbase_type1;
+    typedef boost::base_from_member<base_or_member, 2>  pbase_type2;
+    typedef base_class                                   base_type;
+
+public:
+     good_class_2();
+    ~good_class_2();
+
+};  // good_class_2
+
+// Declare/define the single object registrar
+object_registrar  obj_reg;
+
+
+// Main functionality
+int
+main()
+{
+    BOOST_TEST( obj_reg.db_.empty() );
+    BOOST_TEST( obj_reg.defrauders_in_.empty() );
+    BOOST_TEST( obj_reg.defrauders_out_.empty() );
+    BOOST_TEST( obj_reg.overeager_.empty() );
+    BOOST_TEST( obj_reg.overkilled_.empty() );
+
+    // Make a separate block to examine pre- and post-effects
+    {
+        using std::cout;
+        using std::endl;
+
+        bad_class  bc;
+        BOOST_TEST( obj_reg.db_.size() == 3 );
+        BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
+
+        good_class_1  gc1;
+        BOOST_TEST( obj_reg.db_.size() == 6 );
+        BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
+
+        good_class_2  gc2;
+        BOOST_TEST( obj_reg.db_.size() == 11 );
+        BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
+
+        BOOST_TEST( obj_reg.defrauders_out_.empty() );
+        BOOST_TEST( obj_reg.overeager_.empty() );
+        BOOST_TEST( obj_reg.overkilled_.empty() );
+
+        // Getting the addresses of the objects ensure
+        // that they're used, and not optimized away.
+        cout << "Object 'bc' is at " << &bc << '.' << endl;
+        cout << "Object 'gc1' is at " << &gc1 << '.' << endl;
+        cout << "Object 'gc2' is at " << &gc2 << '.' << endl;
+    }
+
+    BOOST_TEST( obj_reg.db_.empty() );
+    BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
+    BOOST_TEST( obj_reg.defrauders_out_.size() == 1 );
+    BOOST_TEST( obj_reg.overeager_.empty() );
+    BOOST_TEST( obj_reg.overkilled_.empty() );
+
+    return boost::report_errors();
+}
+
+
+// Print an object's ID
+std::ostream &
+operator <<
+(
+    std::ostream &     os,
+    object_id const &  oi
+)
+{
+    // I had an std::ostringstream to help, but I did not need it since
+    // the program never screws around with formatting.  Worse, using
+    // std::ostringstream is an issue with some compilers.
+
+    return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" )
+     << " at " << oi.first << ']';
+}
+
+// Get an object ID given an object
+template < typename T >
+inline
+object_id
+identify
+(
+    T &  obj
+)
+{
+    return std::make_pair( static_cast<void *>(&obj), &(typeid( obj )) );
+}
+
+// Compare two object IDs
+bool
+object_id_compare::operator ()
+(
+    object_id const &  a,
+    object_id const &  b
+) const
+{
+    std::less<void *>  vp_cmp;
+    if ( vp_cmp(a.first, b.first) )
+    {
+        return true;
+    }
+    else if ( vp_cmp(b.first, a.first) )
+    {
+        return false;
+    }
+    else
+    {
+        // object pointers are equal, compare the types
+        if ( a.second == b.second )
+        {
+            return false;
+        }
+        else if ( !a.second )
+        {
+            return true;   // NULL preceeds anything else
+        }
+        else if ( !b.second )
+        {
+            return false;  // NULL preceeds anything else
+        }
+        else
+        {
+            return a.second->before( *b.second ) != 0;
+        }
+    }
+}
+
+// Let an object register its existence
+void
+object_registrar::register_object_imp
+(
+    object_id  obj
+)
+{
+    if ( db_.count(obj) <= 0 )
+    {
+        db_.insert( obj );
+
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << "Registered " << obj << '.' << std::endl;
+        #endif
+    }
+    else
+    {
+        overeager_.push_back( obj );
+
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << "Attempted to register a non-existant " << obj
+         << '.' << std::endl;
+        #endif
+    }
+}
+
+// Let an object register its use of another object
+void
+object_registrar::register_use_imp
+(
+    object_id  owner,
+    object_id  owned
+)
+{
+    if ( db_.count(owned) > 0 )
+    {
+        // We don't care to record usage registrations
+    }
+    else
+    {
+        defrauders_in_.push_back( std::make_pair(owner, owned) );
+
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << "Attempted to own a non-existant " << owned
+         << " by " << owner << '.' << std::endl;
+        #endif
+    }
+}
+
+// Let an object un-register its use of another object
+void
+object_registrar::unregister_use_imp
+(
+    object_id  owner,
+    object_id  owned
+)
+{
+    if ( db_.count(owned) > 0 )
+    {
+        // We don't care to record usage un-registrations
+    }
+    else
+    {
+        defrauders_out_.push_back( std::make_pair(owner, owned) );
+
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << "Attempted to disown a non-existant " << owned
+         << " by " << owner << '.' << std::endl;
+        #endif
+    }
+}
+
+// Let an object un-register its existence
+void
+object_registrar::unregister_object_imp
+(
+    object_id  obj
+)
+{
+    set_type::iterator const  i = db_.find( obj );
+
+    if ( i != db_.end() )
+    {
+        db_.erase( i );
+
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << "Unregistered " << obj << '.' << std::endl;
+        #endif
+    }
+    else
+    {
+        overkilled_.push_back( obj );
+
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << "Attempted to unregister a non-existant " << obj
+         << '.' << std::endl;
+        #endif
+    }
+}
+
+// Macros to abstract the registration of objects
+#ifndef BOOST_NO_MEMBER_TEMPLATES
+#define PRIVATE_REGISTER_BIRTH(o)     obj_reg.register_object( (o) )
+#define PRIVATE_REGISTER_DEATH(o)     obj_reg.unregister_object( (o) )
+#define PRIVATE_REGISTER_USE(o, w)    obj_reg.register_use( (o), (w) )
+#define PRIVATE_UNREGISTER_USE(o, w)  obj_reg.unregister_use( (o), (w) )
+#else
+#define PRIVATE_REGISTER_BIRTH(o)     obj_reg.register_object_imp( \
+ identify((o)) )
+#define PRIVATE_REGISTER_DEATH(o)     obj_reg.unregister_object_imp( \
+ identify((o)) )
+#define PRIVATE_REGISTER_USE(o, w)    obj_reg.register_use_imp( identify((o)), \
+ identify((w)) )
+#define PRIVATE_UNREGISTER_USE(o, w)  obj_reg.unregister_use_imp( \
+ identify((o)), identify((w)) )
+#endif
+
+// Create a base_or_member, with arguments to simulate member initializations
+base_or_member::base_or_member
+(
+    int     x,  // = 1
+    double  y   // = -0.25
+)
+{
+    PRIVATE_REGISTER_BIRTH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy x-factor is " << x << " and my y-factor is " << y
+     << '.' << std::endl;
+    #endif
+}
+
+// Destroy a base_or_member
+inline
+base_or_member::~base_or_member
+(
+)
+{
+    PRIVATE_REGISTER_DEATH( *this );
+}
+
+// Create a base_class, registering any objects used
+base_class::base_class
+(
+    base_or_member &  x,
+    base_or_member *  y,  // = 0
+    base_or_member *  z   // = 0
+)
+    : x_( &x ), y_( y ), z_( z )
+{
+    PRIVATE_REGISTER_BIRTH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy x-factor is " << x_;
+    #endif
+
+    PRIVATE_REGISTER_USE( *this, *x_ );
+
+    if ( y_ )
+    {
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << ", my y-factor is " << y_;
+        #endif
+
+        PRIVATE_REGISTER_USE( *this, *y_ );
+    }
+
+    if ( z_ )
+    {
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << ", my z-factor is " << z_;
+        #endif
+
+        PRIVATE_REGISTER_USE( *this, *z_ );
+    }
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << '.' << std::endl;
+    #endif
+}
+
+// Destroy a base_class, unregistering the objects it uses
+base_class::~base_class
+(
+)
+{
+    PRIVATE_REGISTER_DEATH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy x-factor was " << x_;
+    #endif
+
+    PRIVATE_UNREGISTER_USE( *this, *x_ );
+
+    if ( y_ )
+    {
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << ", my y-factor was " << y_;
+        #endif
+
+        PRIVATE_UNREGISTER_USE( *this, *y_ );
+    }
+
+    if ( z_ )
+    {
+        #if CONTROL_EXTRA_PRINTING
+        std::cout << ", my z-factor was " << z_;
+        #endif
+
+        PRIVATE_UNREGISTER_USE( *this, *z_ );
+    }
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << '.' << std::endl;
+    #endif
+}
+
+// Create a bad_class, noting the improper construction order
+bad_class::bad_class
+(
+)
+    : x_( -7, 16.75 ), base_class( x_ )  // this order doesn't matter
+{
+    PRIVATE_REGISTER_BIRTH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy factor is at " << &x_
+     << " and my base is at " << static_cast<base_class *>(this) << '.'
+     << std::endl;
+    #endif
+}
+
+// Destroy a bad_class, noting the improper destruction order
+bad_class::~bad_class
+(
+)
+{
+    PRIVATE_REGISTER_DEATH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy factor was at " << &x_
+     << " and my base was at " << static_cast<base_class *>(this)
+     << '.' << std::endl;
+    #endif
+}
+
+// Create a good_class_1, noting the proper construction order
+good_class_1::good_class_1
+(
+)
+    : pbase_type( 8 ), base_type( member )
+{
+    PRIVATE_REGISTER_BIRTH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy factor is at " << &member
+     << " and my base is at " << static_cast<base_class *>(this) << '.'
+     << std::endl;
+    #endif
+}
+
+// Destroy a good_class_1, noting the proper destruction order
+good_class_1::~good_class_1
+(
+)
+{
+    PRIVATE_REGISTER_DEATH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy factor was at " << &member
+     << " and my base was at " << static_cast<base_class *>(this)
+     << '.' << std::endl;
+    #endif
+}
+
+// Create a good_class_2, noting the proper construction order
+good_class_2::good_class_2
+(
+)
+    : pbase_type0(), pbase_type1(-16, 0.125), pbase_type2(2, -3)
+    , base_type( pbase_type1::member, &this->pbase_type0::member,
+       &this->pbase_type2::member )
+{
+    PRIVATE_REGISTER_BIRTH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy factors are at " << &this->pbase_type0::member
+     << ", " << &this->pbase_type1::member << ", "
+     << &this->pbase_type2::member << ", and my base is at "
+     << static_cast<base_class *>(this) << '.' << std::endl;
+    #endif
+}
+
+// Destroy a good_class_2, noting the proper destruction order
+good_class_2::~good_class_2
+(
+)
+{
+    PRIVATE_REGISTER_DEATH( *this );
+
+    #if CONTROL_EXTRA_PRINTING
+    std::cout << "\tMy factors were at " << &this->pbase_type0::member
+     << ", " << &this->pbase_type1::member << ", "
+     << &this->pbase_type2::member << ", and my base was at "
+     << static_cast<base_class *>(this) << '.' << std::endl;
+    #endif
+}
diff --git a/test/binary_test.cpp b/test/binary_test.cpp
new file mode 100644
index 0000000..f39dc08
--- /dev/null
+++ b/test/binary_test.cpp
@@ -0,0 +1,647 @@
+/*=============================================================================
+    Copyright (c) 2006, 2007 Matthew Calabrese
+
+    Use, modification and distribution is subject to the Boost Software
+    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+    http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/utility/binary.hpp>
+#include <algorithm>
+#include <cstddef>
+
+#ifdef BOOST_MSVC
+#pragma warning(disable:4996) // warning C4996: 'std::equal': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
+#endif
+
+/*
+Note: This file tests every single valid bit-grouping on its own, and some
+      random combinations of bit-groupings.
+*/
+
+std::size_t const num_random_test_values = 32;
+
+// Note: These hex values should all correspond with the binary array below
+unsigned int const random_unsigned_ints_hex[num_random_test_values]
+  = { 0x0103u, 0x77ebu, 0x5f36u, 0x1f18u, 0xc530u, 0xa73au, 0xd6f8u, 0x0919u
+    , 0xfbb0u, 0x3e7cu, 0xd0e9u, 0x22c8u, 0x724eu, 0x14fau, 0xd98eu, 0x40b5
+    , 0xeba0u, 0xfe50u, 0x688au, 0x1b05u, 0x5f9cu, 0xe4fcu, 0xa7b8u, 0xd3acu
+    , 0x1dddu, 0xbf04u, 0x8352u, 0xe89cu, 0x7506u, 0xe767u, 0xf489u, 0xe167
+    };
+
+unsigned int const random_unsigned_ints_binary[num_random_test_values]
+  = { BOOST_BINARY( 0 00010000 0011 ), BOOST_BINARY( 0 11101 1111  101011 )
+    , BOOST_BINARY( 010111 1100110 1 1 0 ), BOOST_BINARY( 000 1 11110 00 11000 )
+    , BOOST_BINARY( 110 001010 0110 000 ), BOOST_BINARY( 1010 01110011 1010 )
+    , BOOST_BINARY( 11 010 1 101111 1000 ), BOOST_BINARY( 0000 100100 0110 01 )
+    , BOOST_BINARY( 1111 101110 11 0000 ), BOOST_BINARY( 00111110 01111100 )
+    , BOOST_BINARY( 11  010 000111 01001 ), BOOST_BINARY( 00100 010110   01000 )
+    , BOOST_BINARY( 01 11001001 001110 ), BOOST_BINARY( 0010 1001111 1010 )
+    , BOOST_BINARY( 1101 1 00110 0 01110 ), BOOST_BINARY( 100 000 01011010 1 )
+    , BOOST_BINARY( 11 1010 1110 1000 00 ), BOOST_BINARY( 11111 110010 10000 )
+    , BOOST_BINARY( 01101 00010 001010 ), BOOST_BINARY( 000 11011 000001 01 )
+    , BOOST_BINARY( 01 01111 1100111 00 ), BOOST_BINARY( 1 110010 0111111 00 )
+    , BOOST_BINARY( 101 0011 11 01110 00 ), BOOST_BINARY( 110100 1 110101 100 )
+    , BOOST_BINARY( 00 1110111 011 101 ), BOOST_BINARY( 1011 1111 00000 100 )
+    , BOOST_BINARY( 1000 00110 101 0010 ), BOOST_BINARY( 1110  10001 001110 0 )
+    , BOOST_BINARY( 011 1010100 000 110 ), BOOST_BINARY( 1110 0111 01100 111 )
+    , BOOST_BINARY( 11110 10010 001001 ), BOOST_BINARY( 11 1000010 1100 111 )
+    };
+
+unsigned int const unsigned_ints_1_bit[2] =
+{ BOOST_BINARY( 0 )
+, BOOST_BINARY( 1 )
+};
+
+unsigned int const unsigned_ints_2_bits[4] =
+{ BOOST_BINARY( 00 )
+, BOOST_BINARY( 01 )
+, BOOST_BINARY( 10 )
+, BOOST_BINARY( 11 )
+};
+
+unsigned int const unsigned_ints_3_bits[8] =
+{ BOOST_BINARY( 000 )
+, BOOST_BINARY( 001 )
+, BOOST_BINARY( 010 )
+, BOOST_BINARY( 011 )
+, BOOST_BINARY( 100 )
+, BOOST_BINARY( 101 )
+, BOOST_BINARY( 110 )
+, BOOST_BINARY( 111 )
+};
+
+unsigned int const unsigned_ints_4_bits[16] =
+{ BOOST_BINARY( 0000 )
+, BOOST_BINARY( 0001 )
+, BOOST_BINARY( 0010 )
+, BOOST_BINARY( 0011 )
+, BOOST_BINARY( 0100 )
+, BOOST_BINARY( 0101 )
+, BOOST_BINARY( 0110 )
+, BOOST_BINARY( 0111 )
+, BOOST_BINARY( 1000 )
+, BOOST_BINARY( 1001 )
+, BOOST_BINARY( 1010 )
+, BOOST_BINARY( 1011 )
+, BOOST_BINARY( 1100 )
+, BOOST_BINARY( 1101 )
+, BOOST_BINARY( 1110 )
+, BOOST_BINARY( 1111 )
+};
+
+unsigned int const unsigned_ints_5_bits[32] =
+{ BOOST_BINARY( 00000 )
+, BOOST_BINARY( 00001 )
+, BOOST_BINARY( 00010 )
+, BOOST_BINARY( 00011 )
+, BOOST_BINARY( 00100 )
+, BOOST_BINARY( 00101 )
+, BOOST_BINARY( 00110 )
+, BOOST_BINARY( 00111 )
+, BOOST_BINARY( 01000 )
+, BOOST_BINARY( 01001 )
+, BOOST_BINARY( 01010 )
+, BOOST_BINARY( 01011 )
+, BOOST_BINARY( 01100 )
+, BOOST_BINARY( 01101 )
+, BOOST_BINARY( 01110 )
+, BOOST_BINARY( 01111 )
+, BOOST_BINARY( 10000 )
+, BOOST_BINARY( 10001 )
+, BOOST_BINARY( 10010 )
+, BOOST_BINARY( 10011 )
+, BOOST_BINARY( 10100 )
+, BOOST_BINARY( 10101 )
+, BOOST_BINARY( 10110 )
+, BOOST_BINARY( 10111 )
+, BOOST_BINARY( 11000 )
+, BOOST_BINARY( 11001 )
+, BOOST_BINARY( 11010 )
+, BOOST_BINARY( 11011 )
+, BOOST_BINARY( 11100 )
+, BOOST_BINARY( 11101 )
+, BOOST_BINARY( 11110 )
+, BOOST_BINARY( 11111 )
+};
+
+unsigned int const unsigned_ints_6_bits[64] =
+{ BOOST_BINARY( 000000 )
+, BOOST_BINARY( 000001 )
+, BOOST_BINARY( 000010 )
+, BOOST_BINARY( 000011 )
+, BOOST_BINARY( 000100 )
+, BOOST_BINARY( 000101 )
+, BOOST_BINARY( 000110 )
+, BOOST_BINARY( 000111 )
+, BOOST_BINARY( 001000 )
+, BOOST_BINARY( 001001 )
+, BOOST_BINARY( 001010 )
+, BOOST_BINARY( 001011 )
+, BOOST_BINARY( 001100 )
+, BOOST_BINARY( 001101 )
+, BOOST_BINARY( 001110 )
+, BOOST_BINARY( 001111 )
+, BOOST_BINARY( 010000 )
+, BOOST_BINARY( 010001 )
+, BOOST_BINARY( 010010 )
+, BOOST_BINARY( 010011 )
+, BOOST_BINARY( 010100 )
+, BOOST_BINARY( 010101 )
+, BOOST_BINARY( 010110 )
+, BOOST_BINARY( 010111 )
+, BOOST_BINARY( 011000 )
+, BOOST_BINARY( 011001 )
+, BOOST_BINARY( 011010 )
+, BOOST_BINARY( 011011 )
+, BOOST_BINARY( 011100 )
+, BOOST_BINARY( 011101 )
+, BOOST_BINARY( 011110 )
+, BOOST_BINARY( 011111 )
+, BOOST_BINARY( 100000 )
+, BOOST_BINARY( 100001 )
+, BOOST_BINARY( 100010 )
+, BOOST_BINARY( 100011 )
+, BOOST_BINARY( 100100 )
+, BOOST_BINARY( 100101 )
+, BOOST_BINARY( 100110 )
+, BOOST_BINARY( 100111 )
+, BOOST_BINARY( 101000 )
+, BOOST_BINARY( 101001 )
+, BOOST_BINARY( 101010 )
+, BOOST_BINARY( 101011 )
+, BOOST_BINARY( 101100 )
+, BOOST_BINARY( 101101 )
+, BOOST_BINARY( 101110 )
+, BOOST_BINARY( 101111 )
+, BOOST_BINARY( 110000 )
+, BOOST_BINARY( 110001 )
+, BOOST_BINARY( 110010 )
+, BOOST_BINARY( 110011 )
+, BOOST_BINARY( 110100 )
+, BOOST_BINARY( 110101 )
+, BOOST_BINARY( 110110 )
+, BOOST_BINARY( 110111 )
+, BOOST_BINARY( 111000 )
+, BOOST_BINARY( 111001 )
+, BOOST_BINARY( 111010 )
+, BOOST_BINARY( 111011 )
+, BOOST_BINARY( 111100 )
+, BOOST_BINARY( 111101 )
+, BOOST_BINARY( 111110 )
+, BOOST_BINARY( 111111 )
+};
+
+unsigned int const unsigned_ints_7_bits[128] =
+{ BOOST_BINARY( 0000000 )
+, BOOST_BINARY( 0000001 )
+, BOOST_BINARY( 0000010 )
+, BOOST_BINARY( 0000011 )
+, BOOST_BINARY( 0000100 )
+, BOOST_BINARY( 0000101 )
+, BOOST_BINARY( 0000110 )
+, BOOST_BINARY( 0000111 )
+, BOOST_BINARY( 0001000 )
+, BOOST_BINARY( 0001001 )
+, BOOST_BINARY( 0001010 )
+, BOOST_BINARY( 0001011 )
+, BOOST_BINARY( 0001100 )
+, BOOST_BINARY( 0001101 )
+, BOOST_BINARY( 0001110 )
+, BOOST_BINARY( 0001111 )
+, BOOST_BINARY( 0010000 )
+, BOOST_BINARY( 0010001 )
+, BOOST_BINARY( 0010010 )
+, BOOST_BINARY( 0010011 )
+, BOOST_BINARY( 0010100 )
+, BOOST_BINARY( 0010101 )
+, BOOST_BINARY( 0010110 )
+, BOOST_BINARY( 0010111 )
+, BOOST_BINARY( 0011000 )
+, BOOST_BINARY( 0011001 )
+, BOOST_BINARY( 0011010 )
+, BOOST_BINARY( 0011011 )
+, BOOST_BINARY( 0011100 )
+, BOOST_BINARY( 0011101 )
+, BOOST_BINARY( 0011110 )
+, BOOST_BINARY( 0011111 )
+, BOOST_BINARY( 0100000 )
+, BOOST_BINARY( 0100001 )
+, BOOST_BINARY( 0100010 )
+, BOOST_BINARY( 0100011 )
+, BOOST_BINARY( 0100100 )
+, BOOST_BINARY( 0100101 )
+, BOOST_BINARY( 0100110 )
+, BOOST_BINARY( 0100111 )
+, BOOST_BINARY( 0101000 )
+, BOOST_BINARY( 0101001 )
+, BOOST_BINARY( 0101010 )
+, BOOST_BINARY( 0101011 )
+, BOOST_BINARY( 0101100 )
+, BOOST_BINARY( 0101101 )
+, BOOST_BINARY( 0101110 )
+, BOOST_BINARY( 0101111 )
+, BOOST_BINARY( 0110000 )
+, BOOST_BINARY( 0110001 )
+, BOOST_BINARY( 0110010 )
+, BOOST_BINARY( 0110011 )
+, BOOST_BINARY( 0110100 )
+, BOOST_BINARY( 0110101 )
+, BOOST_BINARY( 0110110 )
+, BOOST_BINARY( 0110111 )
+, BOOST_BINARY( 0111000 )
+, BOOST_BINARY( 0111001 )
+, BOOST_BINARY( 0111010 )
+, BOOST_BINARY( 0111011 )
+, BOOST_BINARY( 0111100 )
+, BOOST_BINARY( 0111101 )
+, BOOST_BINARY( 0111110 )
+, BOOST_BINARY( 0111111 )
+, BOOST_BINARY( 1000000 )
+, BOOST_BINARY( 1000001 )
+, BOOST_BINARY( 1000010 )
+, BOOST_BINARY( 1000011 )
+, BOOST_BINARY( 1000100 )
+, BOOST_BINARY( 1000101 )
+, BOOST_BINARY( 1000110 )
+, BOOST_BINARY( 1000111 )
+, BOOST_BINARY( 1001000 )
+, BOOST_BINARY( 1001001 )
+, BOOST_BINARY( 1001010 )
+, BOOST_BINARY( 1001011 )
+, BOOST_BINARY( 1001100 )
+, BOOST_BINARY( 1001101 )
+, BOOST_BINARY( 1001110 )
+, BOOST_BINARY( 1001111 )
+, BOOST_BINARY( 1010000 )
+, BOOST_BINARY( 1010001 )
+, BOOST_BINARY( 1010010 )
+, BOOST_BINARY( 1010011 )
+, BOOST_BINARY( 1010100 )
+, BOOST_BINARY( 1010101 )
+, BOOST_BINARY( 1010110 )
+, BOOST_BINARY( 1010111 )
+, BOOST_BINARY( 1011000 )
+, BOOST_BINARY( 1011001 )
+, BOOST_BINARY( 1011010 )
+, BOOST_BINARY( 1011011 )
+, BOOST_BINARY( 1011100 )
+, BOOST_BINARY( 1011101 )
+, BOOST_BINARY( 1011110 )
+, BOOST_BINARY( 1011111 )
+, BOOST_BINARY( 1100000 )
+, BOOST_BINARY( 1100001 )
+, BOOST_BINARY( 1100010 )
+, BOOST_BINARY( 1100011 )
+, BOOST_BINARY( 1100100 )
+, BOOST_BINARY( 1100101 )
+, BOOST_BINARY( 1100110 )
+, BOOST_BINARY( 1100111 )
+, BOOST_BINARY( 1101000 )
+, BOOST_BINARY( 1101001 )
+, BOOST_BINARY( 1101010 )
+, BOOST_BINARY( 1101011 )
+, BOOST_BINARY( 1101100 )
+, BOOST_BINARY( 1101101 )
+, BOOST_BINARY( 1101110 )
+, BOOST_BINARY( 1101111 )
+, BOOST_BINARY( 1110000 )
+, BOOST_BINARY( 1110001 )
+, BOOST_BINARY( 1110010 )
+, BOOST_BINARY( 1110011 )
+, BOOST_BINARY( 1110100 )
+, BOOST_BINARY( 1110101 )
+, BOOST_BINARY( 1110110 )
+, BOOST_BINARY( 1110111 )
+, BOOST_BINARY( 1111000 )
+, BOOST_BINARY( 1111001 )
+, BOOST_BINARY( 1111010 )
+, BOOST_BINARY( 1111011 )
+, BOOST_BINARY( 1111100 )
+, BOOST_BINARY( 1111101 )
+, BOOST_BINARY( 1111110 )
+, BOOST_BINARY( 1111111 )
+};
+unsigned int const unsigned_ints_8_bits[256] =
+{ BOOST_BINARY( 00000000 )
+, BOOST_BINARY( 00000001 )
+, BOOST_BINARY( 00000010 )
+, BOOST_BINARY( 00000011 )
+, BOOST_BINARY( 00000100 )
+, BOOST_BINARY( 00000101 )
+, BOOST_BINARY( 00000110 )
+, BOOST_BINARY( 00000111 )
+, BOOST_BINARY( 00001000 )
+, BOOST_BINARY( 00001001 )
+, BOOST_BINARY( 00001010 )
+, BOOST_BINARY( 00001011 )
+, BOOST_BINARY( 00001100 )
+, BOOST_BINARY( 00001101 )
+, BOOST_BINARY( 00001110 )
+, BOOST_BINARY( 00001111 )
+, BOOST_BINARY( 00010000 )
+, BOOST_BINARY( 00010001 )
+, BOOST_BINARY( 00010010 )
+, BOOST_BINARY( 00010011 )
+, BOOST_BINARY( 00010100 )
+, BOOST_BINARY( 00010101 )
+, BOOST_BINARY( 00010110 )
+, BOOST_BINARY( 00010111 )
+, BOOST_BINARY( 00011000 )
+, BOOST_BINARY( 00011001 )
+, BOOST_BINARY( 00011010 )
+, BOOST_BINARY( 00011011 )
+, BOOST_BINARY( 00011100 )
+, BOOST_BINARY( 00011101 )
+, BOOST_BINARY( 00011110 )
+, BOOST_BINARY( 00011111 )
+, BOOST_BINARY( 00100000 )
+, BOOST_BINARY( 00100001 )
+, BOOST_BINARY( 00100010 )
+, BOOST_BINARY( 00100011 )
+, BOOST_BINARY( 00100100 )
+, BOOST_BINARY( 00100101 )
+, BOOST_BINARY( 00100110 )
+, BOOST_BINARY( 00100111 )
+, BOOST_BINARY( 00101000 )
+, BOOST_BINARY( 00101001 )
+, BOOST_BINARY( 00101010 )
+, BOOST_BINARY( 00101011 )
+, BOOST_BINARY( 00101100 )
+, BOOST_BINARY( 00101101 )
+, BOOST_BINARY( 00101110 )
+, BOOST_BINARY( 00101111 )
+, BOOST_BINARY( 00110000 )
+, BOOST_BINARY( 00110001 )
+, BOOST_BINARY( 00110010 )
+, BOOST_BINARY( 00110011 )
+, BOOST_BINARY( 00110100 )
+, BOOST_BINARY( 00110101 )
+, BOOST_BINARY( 00110110 )
+, BOOST_BINARY( 00110111 )
+, BOOST_BINARY( 00111000 )
+, BOOST_BINARY( 00111001 )
+, BOOST_BINARY( 00111010 )
+, BOOST_BINARY( 00111011 )
+, BOOST_BINARY( 00111100 )
+, BOOST_BINARY( 00111101 )
+, BOOST_BINARY( 00111110 )
+, BOOST_BINARY( 00111111 )
+, BOOST_BINARY( 01000000 )
+, BOOST_BINARY( 01000001 )
+, BOOST_BINARY( 01000010 )
+, BOOST_BINARY( 01000011 )
+, BOOST_BINARY( 01000100 )
+, BOOST_BINARY( 01000101 )
+, BOOST_BINARY( 01000110 )
+, BOOST_BINARY( 01000111 )
+, BOOST_BINARY( 01001000 )
+, BOOST_BINARY( 01001001 )
+, BOOST_BINARY( 01001010 )
+, BOOST_BINARY( 01001011 )
+, BOOST_BINARY( 01001100 )
+, BOOST_BINARY( 01001101 )
+, BOOST_BINARY( 01001110 )
+, BOOST_BINARY( 01001111 )
+, BOOST_BINARY( 01010000 )
+, BOOST_BINARY( 01010001 )
+, BOOST_BINARY( 01010010 )
+, BOOST_BINARY( 01010011 )
+, BOOST_BINARY( 01010100 )
+, BOOST_BINARY( 01010101 )
+, BOOST_BINARY( 01010110 )
+, BOOST_BINARY( 01010111 )
+, BOOST_BINARY( 01011000 )
+, BOOST_BINARY( 01011001 )
+, BOOST_BINARY( 01011010 )
+, BOOST_BINARY( 01011011 )
+, BOOST_BINARY( 01011100 )
+, BOOST_BINARY( 01011101 )
+, BOOST_BINARY( 01011110 )
+, BOOST_BINARY( 01011111 )
+, BOOST_BINARY( 01100000 )
+, BOOST_BINARY( 01100001 )
+, BOOST_BINARY( 01100010 )
+, BOOST_BINARY( 01100011 )
+, BOOST_BINARY( 01100100 )
+, BOOST_BINARY( 01100101 )
+, BOOST_BINARY( 01100110 )
+, BOOST_BINARY( 01100111 )
+, BOOST_BINARY( 01101000 )
+, BOOST_BINARY( 01101001 )
+, BOOST_BINARY( 01101010 )
+, BOOST_BINARY( 01101011 )
+, BOOST_BINARY( 01101100 )
+, BOOST_BINARY( 01101101 )
+, BOOST_BINARY( 01101110 )
+, BOOST_BINARY( 01101111 )
+, BOOST_BINARY( 01110000 )
+, BOOST_BINARY( 01110001 )
+, BOOST_BINARY( 01110010 )
+, BOOST_BINARY( 01110011 )
+, BOOST_BINARY( 01110100 )
+, BOOST_BINARY( 01110101 )
+, BOOST_BINARY( 01110110 )
+, BOOST_BINARY( 01110111 )
+, BOOST_BINARY( 01111000 )
+, BOOST_BINARY( 01111001 )
+, BOOST_BINARY( 01111010 )
+, BOOST_BINARY( 01111011 )
+, BOOST_BINARY( 01111100 )
+, BOOST_BINARY( 01111101 )
+, BOOST_BINARY( 01111110 )
+, BOOST_BINARY( 01111111 )
+, BOOST_BINARY( 10000000 )
+, BOOST_BINARY( 10000001 )
+, BOOST_BINARY( 10000010 )
+, BOOST_BINARY( 10000011 )
+, BOOST_BINARY( 10000100 )
+, BOOST_BINARY( 10000101 )
+, BOOST_BINARY( 10000110 )
+, BOOST_BINARY( 10000111 )
+, BOOST_BINARY( 10001000 )
+, BOOST_BINARY( 10001001 )
+, BOOST_BINARY( 10001010 )
+, BOOST_BINARY( 10001011 )
+, BOOST_BINARY( 10001100 )
+, BOOST_BINARY( 10001101 )
+, BOOST_BINARY( 10001110 )
+, BOOST_BINARY( 10001111 )
+, BOOST_BINARY( 10010000 )
+, BOOST_BINARY( 10010001 )
+, BOOST_BINARY( 10010010 )
+, BOOST_BINARY( 10010011 )
+, BOOST_BINARY( 10010100 )
+, BOOST_BINARY( 10010101 )
+, BOOST_BINARY( 10010110 )
+, BOOST_BINARY( 10010111 )
+, BOOST_BINARY( 10011000 )
+, BOOST_BINARY( 10011001 )
+, BOOST_BINARY( 10011010 )
+, BOOST_BINARY( 10011011 )
+, BOOST_BINARY( 10011100 )
+, BOOST_BINARY( 10011101 )
+, BOOST_BINARY( 10011110 )
+, BOOST_BINARY( 10011111 )
+, BOOST_BINARY( 10100000 )
+, BOOST_BINARY( 10100001 )
+, BOOST_BINARY( 10100010 )
+, BOOST_BINARY( 10100011 )
+, BOOST_BINARY( 10100100 )
+, BOOST_BINARY( 10100101 )
+, BOOST_BINARY( 10100110 )
+, BOOST_BINARY( 10100111 )
+, BOOST_BINARY( 10101000 )
+, BOOST_BINARY( 10101001 )
+, BOOST_BINARY( 10101010 )
+, BOOST_BINARY( 10101011 )
+, BOOST_BINARY( 10101100 )
+, BOOST_BINARY( 10101101 )
+, BOOST_BINARY( 10101110 )
+, BOOST_BINARY( 10101111 )
+, BOOST_BINARY( 10110000 )
+, BOOST_BINARY( 10110001 )
+, BOOST_BINARY( 10110010 )
+, BOOST_BINARY( 10110011 )
+, BOOST_BINARY( 10110100 )
+, BOOST_BINARY( 10110101 )
+, BOOST_BINARY( 10110110 )
+, BOOST_BINARY( 10110111 )
+, BOOST_BINARY( 10111000 )
+, BOOST_BINARY( 10111001 )
+, BOOST_BINARY( 10111010 )
+, BOOST_BINARY( 10111011 )
+, BOOST_BINARY( 10111100 )
+, BOOST_BINARY( 10111101 )
+, BOOST_BINARY( 10111110 )
+, BOOST_BINARY( 10111111 )
+, BOOST_BINARY( 11000000 )
+, BOOST_BINARY( 11000001 )
+, BOOST_BINARY( 11000010 )
+, BOOST_BINARY( 11000011 )
+, BOOST_BINARY( 11000100 )
+, BOOST_BINARY( 11000101 )
+, BOOST_BINARY( 11000110 )
+, BOOST_BINARY( 11000111 )
+, BOOST_BINARY( 11001000 )
+, BOOST_BINARY( 11001001 )
+, BOOST_BINARY( 11001010 )
+, BOOST_BINARY( 11001011 )
+, BOOST_BINARY( 11001100 )
+, BOOST_BINARY( 11001101 )
+, BOOST_BINARY( 11001110 )
+, BOOST_BINARY( 11001111 )
+, BOOST_BINARY( 11010000 )
+, BOOST_BINARY( 11010001 )
+, BOOST_BINARY( 11010010 )
+, BOOST_BINARY( 11010011 )
+, BOOST_BINARY( 11010100 )
+, BOOST_BINARY( 11010101 )
+, BOOST_BINARY( 11010110 )
+, BOOST_BINARY( 11010111 )
+, BOOST_BINARY( 11011000 )
+, BOOST_BINARY( 11011001 )
+, BOOST_BINARY( 11011010 )
+, BOOST_BINARY( 11011011 )
+, BOOST_BINARY( 11011100 )
+, BOOST_BINARY( 11011101 )
+, BOOST_BINARY( 11011110 )
+, BOOST_BINARY( 11011111 )
+, BOOST_BINARY( 11100000 )
+, BOOST_BINARY( 11100001 )
+, BOOST_BINARY( 11100010 )
+, BOOST_BINARY( 11100011 )
+, BOOST_BINARY( 11100100 )
+, BOOST_BINARY( 11100101 )
+, BOOST_BINARY( 11100110 )
+, BOOST_BINARY( 11100111 )
+, BOOST_BINARY( 11101000 )
+, BOOST_BINARY( 11101001 )
+, BOOST_BINARY( 11101010 )
+, BOOST_BINARY( 11101011 )
+, BOOST_BINARY( 11101100 )
+, BOOST_BINARY( 11101101 )
+, BOOST_BINARY( 11101110 )
+, BOOST_BINARY( 11101111 )
+, BOOST_BINARY( 11110000 )
+, BOOST_BINARY( 11110001 )
+, BOOST_BINARY( 11110010 )
+, BOOST_BINARY( 11110011 )
+, BOOST_BINARY( 11110100 )
+, BOOST_BINARY( 11110101 )
+, BOOST_BINARY( 11110110 )
+, BOOST_BINARY( 11110111 )
+, BOOST_BINARY( 11111000 )
+, BOOST_BINARY( 11111001 )
+, BOOST_BINARY( 11111010 )
+, BOOST_BINARY( 11111011 )
+, BOOST_BINARY( 11111100 )
+, BOOST_BINARY( 11111101 )
+, BOOST_BINARY( 11111110 )
+, BOOST_BINARY( 11111111 )
+};
+
+struct left_is_not_one_less_than_right
+{
+  bool operator ()( unsigned int left, unsigned int right ) const
+  {
+    return right != left + 1;
+  }
+};
+
+template< std::size_t Size >
+bool is_ascending_from_0_array( unsigned int const (&array)[Size] )
+{
+  unsigned int const* const curr = array,
+                    * const end  = array + Size;
+
+  return    ( *curr == 0 )
+         && (    std::adjacent_find( curr, end
+                                   , left_is_not_one_less_than_right()
+                                   )
+              == end
+            );
+}
+
+std::size_t const unsigned_int_id = 1,
+                  unsigned_long_int_id = 2;
+
+typedef char (&unsigned_int_id_type)[unsigned_int_id];
+typedef char (&unsigned_long_int_id_type)[unsigned_long_int_id];
+
+// Note: Functions only used for type checking
+unsigned_int_id_type      binary_type_checker( unsigned int );
+unsigned_long_int_id_type binary_type_checker( unsigned long int );
+
+int main()
+{
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_1_bit ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_2_bits ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_3_bits ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_4_bits ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_5_bits ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_6_bits ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_7_bits ) );
+  BOOST_TEST( is_ascending_from_0_array( unsigned_ints_8_bits ) );
+
+  BOOST_TEST( std::equal( &random_unsigned_ints_hex[0]
+                         , random_unsigned_ints_hex + num_random_test_values
+                         , &random_unsigned_ints_binary[0]
+                         )
+             );
+
+  BOOST_TEST(    sizeof( binary_type_checker( BOOST_BINARY_U( 110100 1010 ) ) )
+               == unsigned_int_id
+             );
+
+  BOOST_TEST(    sizeof( binary_type_checker( BOOST_BINARY_UL( 11110 ) ) )
+               == unsigned_long_int_id
+             );
+
+  BOOST_TEST(    sizeof( binary_type_checker( BOOST_BINARY_LU( 10 0001 ) ) )
+               == unsigned_long_int_id
+             );
+
+  return boost::report_errors();
+}
diff --git a/test/call_traits_test.cpp b/test/call_traits_test.cpp
new file mode 100644
index 0000000..9e49b68
--- /dev/null
+++ b/test/call_traits_test.cpp
@@ -0,0 +1,418 @@
+//  boost::compressed_pair test program   
+    
+//  (C) Copyright John Maddock 2000. 
+//  Use, modification and distribution are subject to the Boost Software License,
+//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt).
+
+
+// standalone test program for <boost/call_traits.hpp>
+// 18 Mar 2002:
+//    Changed some names to prevent conflicts with some new type_traits additions.
+// 03 Oct 2000:
+//    Enabled extra tests for VC6.
+
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+#include <typeinfo>
+#include <boost/call_traits.hpp>
+
+#include <libs/type_traits/test/test.hpp>
+#include <libs/type_traits/test/check_type.hpp>
+
+#ifdef BOOST_MSVC
+#pragma warning(disable:4181) // : warning C4181: qualifier applied to reference type; ignored
+#endif
+
+// a way prevent warnings for unused variables
+template<class T> inline void unused_variable(const T&) {}
+
+//
+// struct contained models a type that contains a type (for example std::pair)
+// arrays are contained by value, and have to be treated as a special case:
+//
+template <class T>
+struct contained
+{
+   // define our typedefs first, arrays are stored by value
+   // so value_type is not the same as result_type:
+   typedef typename boost::call_traits<T>::param_type       param_type;
+   typedef typename boost::call_traits<T>::reference        reference;
+   typedef typename boost::call_traits<T>::const_reference  const_reference;
+   typedef T                                                value_type;
+   typedef typename boost::call_traits<T>::value_type       result_type;
+
+   // stored value:
+   value_type v_;
+   
+   // constructors:
+   contained() {}
+   contained(param_type p) : v_(p){}
+   // return byval:
+   result_type value()const { return v_; }
+   // return by_ref:
+   reference get() { return v_; }
+   const_reference const_get()const { return v_; }
+   // pass value:
+   void call(param_type){}
+private:
+   contained& operator=(const contained&);
+};
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+template <class T, std::size_t N>
+struct contained<T[N]>
+{
+   typedef typename boost::call_traits<T[N]>::param_type       param_type;
+   typedef typename boost::call_traits<T[N]>::reference        reference;
+   typedef typename boost::call_traits<T[N]>::const_reference  const_reference;
+   typedef T                                                   value_type[N];
+   typedef typename boost::call_traits<T[N]>::value_type       result_type;
+
+   value_type v_;
+
+   contained(param_type p)
+   {
+      std::copy(p, p+N, v_);
+   }
+   // return byval:
+   result_type value()const { return v_; }
+   // return by_ref:
+   reference get() { return v_; }
+   const_reference const_get()const { return v_; }
+   void call(param_type){}
+private:
+   contained& operator=(const contained&);
+};
+#endif
+
+template <class T>
+contained<typename boost::call_traits<T>::value_type> test_wrap_type(const T& t)
+{
+   typedef typename boost::call_traits<T>::value_type ct;
+   return contained<ct>(t);
+}
+
+namespace test{
+
+template <class T1, class T2>
+std::pair<
+   typename boost::call_traits<T1>::value_type,
+   typename boost::call_traits<T2>::value_type>
+      make_pair(const T1& t1, const T2& t2)
+{
+   return std::pair<
+      typename boost::call_traits<T1>::value_type,
+      typename boost::call_traits<T2>::value_type>(t1, t2);
+}
+
+} // namespace test
+
+using namespace std;
+
+//
+// struct call_traits_checker:
+// verifies behaviour of contained example:
+//
+template <class T>
+struct call_traits_checker
+{
+   typedef typename boost::call_traits<T>::param_type param_type;
+   void operator()(param_type);
+};
+
+template <class T>
+void call_traits_checker<T>::operator()(param_type p)
+{
+   T t(p);
+   contained<T> c(t);
+   cout << "checking contained<" << typeid(T).name() << ">..." << endl;
+   BOOST_CHECK(t == c.value());
+   BOOST_CHECK(t == c.get());
+   BOOST_CHECK(t == c.const_get());
+#ifndef __ICL
+   //cout << "typeof contained<" << typeid(T).name() << ">::v_ is:           " << typeid(&contained<T>::v_).name() << endl;
+   cout << "typeof contained<" << typeid(T).name() << ">::value() is:      " << typeid(&contained<T>::value).name() << endl;
+   cout << "typeof contained<" << typeid(T).name() << ">::get() is:        " << typeid(&contained<T>::get).name() << endl;
+   cout << "typeof contained<" << typeid(T).name() << ">::const_get() is:  " << typeid(&contained<T>::const_get).name() << endl;
+   cout << "typeof contained<" << typeid(T).name() << ">::call() is:       " << typeid(&contained<T>::call).name() << endl;
+   cout << endl;
+#endif
+}
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+template <class T, std::size_t N>
+struct call_traits_checker<T[N]>
+{
+   typedef typename boost::call_traits<T[N]>::param_type param_type;
+   void operator()(param_type t)
+   {
+      contained<T[N]> c(t);
+      cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl;
+      unsigned int i = 0;
+      for(i = 0; i < N; ++i)
+         BOOST_CHECK(t[i] == c.value()[i]);
+      for(i = 0; i < N; ++i)
+         BOOST_CHECK(t[i] == c.get()[i]);
+      for(i = 0; i < N; ++i)
+         BOOST_CHECK(t[i] == c.const_get()[i]);
+
+      cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is:         " << typeid(&contained<T[N]>::v_).name() << endl;
+      cout << "typeof contained<" << typeid(T[N]).name() << ">::value is:      " << typeid(&contained<T[N]>::value).name() << endl;
+      cout << "typeof contained<" << typeid(T[N]).name() << ">::get is:        " << typeid(&contained<T[N]>::get).name() << endl;
+      cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is:  " << typeid(&contained<T[N]>::const_get).name() << endl;
+      cout << "typeof contained<" << typeid(T[N]).name() << ">::call is:       " << typeid(&contained<T[N]>::call).name() << endl;
+      cout << endl;
+   }
+};
+#endif
+
+//
+// check_wrap:
+template <class W, class U>
+void check_wrap(const W& w, const U& u)
+{
+   cout << "checking " << typeid(W).name() << "..." << endl;
+   BOOST_CHECK(w.value() == u);
+}
+
+//
+// check_make_pair:
+// verifies behaviour of "make_pair":
+//
+template <class T, class U, class V>
+void check_make_pair(T c, U u, V v)
+{
+   cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl;
+   BOOST_CHECK(c.first == u);
+   BOOST_CHECK(c.second == v);
+   cout << endl;
+}
+
+
+struct comparible_UDT
+{
+   int i_;
+   comparible_UDT() : i_(2){}
+   comparible_UDT(const comparible_UDT& other) : i_(other.i_){}
+   comparible_UDT& operator=(const comparible_UDT& other)
+   { 
+      i_ = other.i_;
+      return *this;
+   }
+   bool operator == (const comparible_UDT& v){ return v.i_ == i_; }
+};
+
+int main()
+{
+   call_traits_checker<comparible_UDT> c1;
+   comparible_UDT u;
+   c1(u);
+   call_traits_checker<int> c2;
+   call_traits_checker<enum_UDT> c2b;
+   int i = 2;
+   c2(i);
+   c2b(one);
+   int* pi = &i;
+   int a[2] = {1,2};
+#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL)
+   call_traits_checker<int*> c3;
+   c3(pi);
+   call_traits_checker<int&> c4;
+   c4(i);
+   call_traits_checker<const int&> c5;
+   c5(i);
+#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC)
+   call_traits_checker<int[2]> c6;
+   c6(a);
+#endif
+#endif
+
+   check_wrap(test_wrap_type(2), 2);
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
+   check_wrap(test_wrap_type(a), a);
+   check_make_pair(test::make_pair(a, a), a, a);
+#endif
+
+   // cv-qualifiers applied to reference types should have no effect
+   // declare these here for later use with is_reference and remove_reference:
+   typedef int& r_type;
+   typedef const r_type cr_type;
+
+   BOOST_CHECK_TYPE(comparible_UDT, boost::call_traits<comparible_UDT>::value_type);
+   BOOST_CHECK_TYPE(comparible_UDT&, boost::call_traits<comparible_UDT>::reference);
+   BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference);
+   BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type);
+   BOOST_CHECK_TYPE(int, boost::call_traits<int>::value_type);
+   BOOST_CHECK_TYPE(int&, boost::call_traits<int>::reference);
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<int>::const_reference);
+   BOOST_CHECK_TYPE(const int, boost::call_traits<int>::param_type);
+   BOOST_CHECK_TYPE(int*, boost::call_traits<int*>::value_type);
+   BOOST_CHECK_TYPE(int*&, boost::call_traits<int*>::reference);
+   BOOST_CHECK_TYPE(int*const&, boost::call_traits<int*>::const_reference);
+   BOOST_CHECK_TYPE(int*const, boost::call_traits<int*>::param_type);
+#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+   BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::value_type);
+   BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::reference);
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<int&>::const_reference);
+   BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::param_type);
+#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
+   BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::value_type);
+   BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::reference);
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<cr_type>::const_reference);
+   BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::param_type);
+#else
+   std::cout << "Your compiler cannot instantiate call_traits<int&const>, skipping four tests (4 errors)" << std::endl;
+#endif
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::value_type);
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::reference);
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::const_reference);
+   BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::param_type);
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+   BOOST_CHECK_TYPE(const int*, boost::call_traits<int[3]>::value_type);
+   BOOST_CHECK_TYPE(int(&)[3], boost::call_traits<int[3]>::reference);
+   BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<int[3]>::const_reference);
+   BOOST_CHECK_TYPE(const int*const, boost::call_traits<int[3]>::param_type);
+   BOOST_CHECK_TYPE(const int*, boost::call_traits<const int[3]>::value_type);
+   BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::reference);
+   BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::const_reference);
+   BOOST_CHECK_TYPE(const int*const, boost::call_traits<const int[3]>::param_type);
+   // test with abstract base class:
+   BOOST_CHECK_TYPE(test_abc1, boost::call_traits<test_abc1>::value_type);
+   BOOST_CHECK_TYPE(test_abc1&, boost::call_traits<test_abc1>::reference);
+   BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::const_reference);
+   BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::param_type);
+#else
+   std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl;
+#endif
+#else
+   std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl;
+#endif
+   // test with an incomplete type:
+   BOOST_CHECK_TYPE(incomplete_type, boost::call_traits<incomplete_type>::value_type);
+   BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits<incomplete_type>::reference);
+   BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference);
+   BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::param_type);
+   // test enum:
+   BOOST_CHECK_TYPE(enum_UDT, boost::call_traits<enum_UDT>::value_type);
+   BOOST_CHECK_TYPE(enum_UDT&, boost::call_traits<enum_UDT>::reference);
+   BOOST_CHECK_TYPE(const enum_UDT&, boost::call_traits<enum_UDT>::const_reference);
+   BOOST_CHECK_TYPE(const enum_UDT, boost::call_traits<enum_UDT>::param_type);
+   return 0;
+}
+
+//
+// define call_traits tests to check that the assertions in the docs do actually work
+// this is an compile-time only set of tests:
+//
+template <typename T, bool isarray = false>
+struct call_traits_test
+{
+   typedef ::boost::call_traits<T> ct;
+   typedef typename ct::param_type param_type;
+   typedef typename ct::reference reference;
+   typedef typename ct::const_reference const_reference;
+   typedef typename ct::value_type value_type;
+   static void assert_construct(param_type val);
+};
+
+template <typename T, bool isarray>
+void call_traits_test<T, isarray>::assert_construct(typename call_traits_test<T, isarray>::param_type val)
+{
+   //
+   // this is to check that the call_traits assertions are valid:
+   T t(val);
+   value_type v(t);
+   reference r(t);
+   const_reference cr(t);
+   param_type p(t);
+   value_type v2(v);
+   value_type v3(r);
+   value_type v4(p);
+   reference r2(v);
+   reference r3(r);
+   const_reference cr2(v);
+   const_reference cr3(r);
+   const_reference cr4(cr);
+   const_reference cr5(p);
+   param_type p2(v);
+   param_type p3(r);
+   param_type p4(p);
+   
+   unused_variable(v2);
+   unused_variable(v3);
+   unused_variable(v4);
+   unused_variable(r2);
+   unused_variable(r3);
+   unused_variable(cr2);
+   unused_variable(cr3);
+   unused_variable(cr4);
+   unused_variable(cr5);
+   unused_variable(p2);
+   unused_variable(p3);
+   unused_variable(p4);
+}
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+template <typename T>
+struct call_traits_test<T, true>
+{
+   typedef ::boost::call_traits<T> ct;
+   typedef typename ct::param_type param_type;
+   typedef typename ct::reference reference;
+   typedef typename ct::const_reference const_reference;
+   typedef typename ct::value_type value_type;
+   static void assert_construct(param_type val);
+};
+
+template <typename T>
+void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>::param_type val)
+{
+   //
+   // this is to check that the call_traits assertions are valid:
+   T t;
+   value_type v(t);
+   value_type v5(val);
+   reference r = t;
+   const_reference cr = t;
+   reference r2 = r;
+   #ifndef __BORLANDC__
+   // C++ Builder buglet:
+   const_reference cr2 = r;
+   #endif
+   param_type p(t);
+   value_type v2(v);
+   const_reference cr3 = cr;
+   value_type v3(r);
+   value_type v4(p);
+   param_type p2(v);
+   param_type p3(r);
+   param_type p4(p);
+   
+   unused_variable(v2);
+   unused_variable(v3);
+   unused_variable(v4);
+   unused_variable(v5);
+#ifndef __BORLANDC__
+   unused_variable(r2);
+   unused_variable(cr2);
+#endif
+   unused_variable(cr3);
+   unused_variable(p2);
+   unused_variable(p3);
+   unused_variable(p4);
+}
+#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+//
+// now check call_traits assertions by instantiating call_traits_test:
+template struct call_traits_test<int>;
+template struct call_traits_test<const int>;
+template struct call_traits_test<int*>;
+#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+template struct call_traits_test<int&>;
+template struct call_traits_test<const int&>;
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
+template struct call_traits_test<int[2], true>;
+#endif
+#endif
+
diff --git a/test/compressed_pair_test.cpp b/test/compressed_pair_test.cpp
new file mode 100644
index 0000000..ea10b2c
--- /dev/null
+++ b/test/compressed_pair_test.cpp
@@ -0,0 +1,387 @@
+//  boost::compressed_pair test program   
+    
+//  (C) Copyright John Maddock 2000. 
+//  Use, modification and distribution are subject to the Boost Software License,
+//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt).
+
+// standalone test program for <boost/compressed_pair.hpp>
+// Revised 03 Oct 2000: 
+//    Enabled tests for VC6.
+
+#include <iostream>
+#include <typeinfo>
+#include <cassert>
+
+#include <boost/compressed_pair.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost;
+
+struct empty_UDT
+{
+   ~empty_UDT(){};
+   empty_UDT& operator=(const empty_UDT&){ return *this; }
+   bool operator==(const empty_UDT&)const
+   { return true; }
+};
+struct empty_POD_UDT
+{
+   empty_POD_UDT& operator=(const empty_POD_UDT&){ return *this; }
+   bool operator==(const empty_POD_UDT&)const
+   { return true; }
+};
+
+struct non_empty1
+{ 
+   int i;
+   non_empty1() : i(1){}
+   non_empty1(int v) : i(v){}
+   friend bool operator==(const non_empty1& a, const non_empty1& b)
+   { return a.i == b.i; }
+};
+
+struct non_empty2
+{ 
+   int i;
+   non_empty2() : i(3){}
+   non_empty2(int v) : i(v){}
+   friend bool operator==(const non_empty2& a, const non_empty2& b)
+   { return a.i == b.i; }
+};
+
+#ifdef __GNUC__
+using std::swap;
+#endif
+
+template <class T1, class T2>
+struct compressed_pair_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
+{
+#ifndef __GNUC__
+   // gcc 2.90 can't cope with function scope using
+   // declarations, and generates an internal compiler error...
+   using std::swap;
+#endif
+   // default construct:
+   boost::compressed_pair<T1,T2> cp1;
+   // first param construct:
+   boost::compressed_pair<T1,T2> cp2(p1);
+   cp2.second() = p2;
+   BOOST_TEST(cp2.first() == p1);
+   BOOST_TEST(cp2.second() == p2);
+   // second param construct:
+   boost::compressed_pair<T1,T2> cp3(p2);
+   cp3.first() = p1;
+   BOOST_TEST(cp3.second() == p2);
+   BOOST_TEST(cp3.first() == p1);
+   // both param construct:
+   boost::compressed_pair<T1,T2> cp4(p1, p2);
+   BOOST_TEST(cp4.first() == p1);
+   BOOST_TEST(cp4.second() == p2);
+   boost::compressed_pair<T1,T2> cp5(p3, p4);
+   BOOST_TEST(cp5.first() == p3);
+   BOOST_TEST(cp5.second() == p4);
+   // check const members:
+   const boost::compressed_pair<T1,T2>& cpr1 = cp4;
+   BOOST_TEST(cpr1.first() == p1);
+   BOOST_TEST(cpr1.second() == p2);
+
+   // copy construct:
+   boost::compressed_pair<T1,T2> cp6(cp4);
+   BOOST_TEST(cp6.first() == p1);
+   BOOST_TEST(cp6.second() == p2);
+   // assignment:
+   cp1 = cp4;
+   BOOST_TEST(cp1.first() == p1);
+   BOOST_TEST(cp1.second() == p2);
+   cp1 = cp5;
+   BOOST_TEST(cp1.first() == p3);
+   BOOST_TEST(cp1.second() == p4);
+   // swap:
+   cp4.swap(cp5);
+   BOOST_TEST(cp4.first() == p3);
+   BOOST_TEST(cp4.second() == p4);
+   BOOST_TEST(cp5.first() == p1);
+   BOOST_TEST(cp5.second() == p2);
+   swap(cp4,cp5);
+   BOOST_TEST(cp4.first() == p1);
+   BOOST_TEST(cp4.second() == p2);
+   BOOST_TEST(cp5.first() == p3);
+   BOOST_TEST(cp5.second() == p4);
+}
+
+//
+// tests for case where one or both 
+// parameters are reference types:
+//
+template <class T1, class T2>
+struct compressed_pair_reference_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
+{
+#ifndef __GNUC__
+   // gcc 2.90 can't cope with function scope using
+   // declarations, and generates an internal compiler error...
+   using std::swap;
+#endif
+   // both param construct:
+   boost::compressed_pair<T1,T2> cp4(p1, p2);
+   BOOST_TEST(cp4.first() == p1);
+   BOOST_TEST(cp4.second() == p2);
+   boost::compressed_pair<T1,T2> cp5(p3, p4);
+   BOOST_TEST(cp5.first() == p3);
+   BOOST_TEST(cp5.second() == p4);
+   // check const members:
+   const boost::compressed_pair<T1,T2>& cpr1 = cp4;
+   BOOST_TEST(cpr1.first() == p1);
+   BOOST_TEST(cpr1.second() == p2);
+
+   // copy construct:
+   boost::compressed_pair<T1,T2> cp6(cp4);
+   BOOST_TEST(cp6.first() == p1);
+   BOOST_TEST(cp6.second() == p2);
+   // assignment:
+   // VC6 bug:
+   // When second() is an empty class, VC6 performs the
+   // assignment by doing a memcpy - even though the empty
+   // class is really a zero sized base class, the result
+   // is that the memory of first() gets trampled over.
+   // Similar arguments apply to the case that first() is 
+   // an empty base class.
+   // Strangely the problem is dependent upon the compiler
+   // settings - some generate the problem others do not.
+   cp4.first() = p3;
+   cp4.second() = p4;
+   BOOST_TEST(cp4.first() == p3);
+   BOOST_TEST(cp4.second() == p4);
+}
+//
+// supplimentary tests for case where first arg only is a reference type:
+//
+template <class T1, class T2>
+struct compressed_pair_reference1_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
+{
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+   // first param construct:
+   boost::compressed_pair<T1,T2> cp2(p1);
+   cp2.second() = p2;
+   BOOST_TEST(cp2.first() == p1);
+   BOOST_TEST(cp2.second() == p2);
+#endif
+}
+//
+// supplimentary tests for case where second arg only is a reference type:
+//
+template <class T1, class T2>
+struct compressed_pair_reference2_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
+{
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+   // second param construct:
+   boost::compressed_pair<T1,T2> cp3(p2);
+   cp3.first() = p1;
+   BOOST_TEST(cp3.second() == p2);
+   BOOST_TEST(cp3.first() == p1);
+#endif
+}
+
+//
+// tests for where one or the other parameter is an array:
+//
+template <class T1, class T2>
+struct compressed_pair_array1_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
+{
+  // default construct:
+   boost::compressed_pair<T1,T2> cp1;
+   // second param construct:
+   boost::compressed_pair<T1,T2> cp3(p2);
+   cp3.first()[0] = p1[0];
+   BOOST_TEST(cp3.second() == p2);
+   BOOST_TEST(cp3.first()[0] == p1[0]);
+   // check const members:
+   const boost::compressed_pair<T1,T2>& cpr1 = cp3;
+   BOOST_TEST(cpr1.first()[0] == p1[0]);
+   BOOST_TEST(cpr1.second() == p2);
+
+   BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
+}
+
+template <class T1, class T2>
+struct compressed_pair_array2_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
+{
+   // default construct:
+   boost::compressed_pair<T1,T2> cp1;
+   // first param construct:
+   boost::compressed_pair<T1,T2> cp2(p1);
+   cp2.second()[0] = p2[0];
+   BOOST_TEST(cp2.first() == p1);
+   BOOST_TEST(cp2.second()[0] == p2[0]);
+   // check const members:
+   const boost::compressed_pair<T1,T2>& cpr1 = cp2;
+   BOOST_TEST(cpr1.first() == p1);
+   BOOST_TEST(cpr1.second()[0] == p2[0]);
+
+   BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
+}
+
+template <class T1, class T2>
+struct compressed_pair_array_tester
+{
+   // define the types we need:
+   typedef T1                                                 first_type;
+   typedef T2                                                 second_type;
+   typedef typename call_traits<first_type>::param_type       first_param_type;
+   typedef typename call_traits<second_type>::param_type      second_param_type;
+   // define our test proc:
+   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
+};
+
+template <class T1, class T2>
+void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
+{
+   // default construct:
+   boost::compressed_pair<T1,T2> cp1;
+   cp1.first()[0] = p1[0];
+   cp1.second()[0] = p2[0];
+   BOOST_TEST(cp1.first()[0] == p1[0]);
+   BOOST_TEST(cp1.second()[0] == p2[0]);
+   // check const members:
+   const boost::compressed_pair<T1,T2>& cpr1 = cp1;
+   BOOST_TEST(cpr1.first()[0] == p1[0]);
+   BOOST_TEST(cpr1.second()[0] == p2[0]);
+
+   BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
+   BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
+}
+
+int main()
+{
+   // declare some variables to pass to the tester:
+   non_empty1 ne1(2);
+   non_empty1 ne2(3);
+   non_empty2 ne3(4);
+   non_empty2 ne4(5);
+   empty_POD_UDT  e1;
+   empty_UDT      e2;
+
+   // T1 != T2, both non-empty
+   compressed_pair_tester<non_empty1,non_empty2>::test(ne1, ne3, ne2, ne4);
+   // T1 != T2, T2 empty
+   compressed_pair_tester<non_empty1,empty_POD_UDT>::test(ne1, e1, ne2, e1);
+   // T1 != T2, T1 empty
+   compressed_pair_tester<empty_POD_UDT,non_empty2>::test(e1, ne3, e1, ne4);
+   // T1 != T2, both empty
+   compressed_pair_tester<empty_POD_UDT,empty_UDT>::test(e1, e2, e1, e2);
+   // T1 == T2, both non-empty
+   compressed_pair_tester<non_empty1,non_empty1>::test(ne1, ne1, ne2, ne2);
+   // T1 == T2, both empty
+   compressed_pair_tester<empty_UDT,empty_UDT>::test(e2, e2, e2, e2);
+
+
+   // test references:
+
+   // T1 != T2, both non-empty
+   compressed_pair_reference_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4);
+   compressed_pair_reference_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4);
+   compressed_pair_reference1_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4);
+   compressed_pair_reference2_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4);
+   // T1 != T2, T2 empty
+   compressed_pair_reference_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1);
+   compressed_pair_reference1_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1);
+   // T1 != T2, T1 empty
+   compressed_pair_reference_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4);
+   compressed_pair_reference2_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4);
+   // T1 == T2, both non-empty
+   compressed_pair_reference_tester<non_empty1&,non_empty1&>::test(ne1, ne1, ne2, ne2);
+
+   // tests arrays:
+   non_empty1 nea1[2];
+   non_empty1 nea2[2];
+   non_empty2 nea3[2];
+   non_empty2 nea4[2];
+   nea1[0] = non_empty1(5);
+   nea2[0] = non_empty1(6);
+   nea3[0] = non_empty2(7);
+   nea4[0] = non_empty2(8);
+   
+   // T1 != T2, both non-empty
+   compressed_pair_array1_tester<non_empty1[2],non_empty2>::test(nea1, ne3, nea2, ne4);
+   compressed_pair_array2_tester<non_empty1,non_empty2[2]>::test(ne1, nea3, ne2, nea4);
+   compressed_pair_array_tester<non_empty1[2],non_empty2[2]>::test(nea1, nea3, nea2, nea4);
+   // T1 != T2, T2 empty
+   compressed_pair_array1_tester<non_empty1[2],empty_POD_UDT>::test(nea1, e1, nea2, e1);
+   // T1 != T2, T1 empty
+   compressed_pair_array2_tester<empty_POD_UDT,non_empty2[2]>::test(e1, nea3, e1, nea4);
+   // T1 == T2, both non-empty
+   compressed_pair_array_tester<non_empty1[2],non_empty1[2]>::test(nea1, nea1, nea2, nea2);
+   return boost::report_errors();
+}
diff --git a/test/initialized_test.cpp b/test/initialized_test.cpp
new file mode 100644
index 0000000..0b8852f
--- /dev/null
+++ b/test/initialized_test.cpp
@@ -0,0 +1,116 @@
+// Copyright 2010, Niels Dekker.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for boost::initialized<T>.
+//
+// 2 May 2010 (Created) Niels Dekker
+
+#include <boost/utility/value_init.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include <string>
+
+namespace
+{
+  // Typical use case for boost::initialized<T>: A generic class that 
+  // holds a value of type T, which must be initialized by either 
+  // value-initialization or direct-initialization.
+  template <class T> class key_value_pair
+  {
+    std::string m_key;
+    boost::initialized<T> m_value;
+  public:
+ 
+    // Value-initializes the object held by m_value.
+    key_value_pair() { }
+
+    // Value-initializes the object held by m_value.
+    explicit key_value_pair(const std::string& key)
+    :
+    m_key(key)
+    {
+    }
+
+    // Direct-initializes the object held by m_value.
+    key_value_pair(const std::string& key, const T& value)
+    :
+    m_key(key), m_value(value)
+    {
+    }
+
+    const T& get_value() const
+    {
+      return m_value;
+    }
+  };
+
+
+  // Tells whether the argument is value-initialized.
+  bool is_value_initialized(const int& arg)
+  {
+    return arg == 0;
+  }
+
+
+  // Tells whether the argument is value-initialized.
+  bool is_value_initialized(const std::string& arg)
+  {
+    return arg.empty();
+  }
+
+  struct foo
+  {
+    int data;
+  };
+
+  bool operator==(const foo& lhs, const foo& rhs)
+  {
+    return lhs.data == rhs.data;
+  }
+
+
+  // Tells whether the argument is value-initialized.
+  bool is_value_initialized(const foo& arg)
+  {
+    return arg.data == 0;
+  }
+
+
+  template <class T>
+  void test_key_value_pair(const T& magic_value)
+  {
+    // The value component of a default key_value_pair must be value-initialized.
+    key_value_pair<T> default_key_value_pair;
+    BOOST_TEST( is_value_initialized(default_key_value_pair.get_value() ) );
+
+    // The value component of a key_value_pair that only has its key explicitly specified
+    // must also be value-initialized.
+    BOOST_TEST( is_value_initialized(key_value_pair<T>("key").get_value()) );
+
+    // However, the value component of the following key_value_pair must be 
+    // "magic_value", as it must be direct-initialized.
+    BOOST_TEST( key_value_pair<T>("key", magic_value).get_value() == magic_value );
+  }
+}
+
+
+// Tests boost::initialize for a fundamental type, a type with a
+// user-defined constructor, and a user-defined type without 
+// a user-defined constructor.
+int main()
+{
+
+  const int magic_number = 42;
+  test_key_value_pair(magic_number);
+
+  const std::string magic_string = "magic value";
+  test_key_value_pair(magic_string);
+
+  const foo magic_foo = { 42 };
+  test_key_value_pair(magic_foo);
+
+  return boost::report_errors();
+}
diff --git a/test/initialized_test_fail1.cpp b/test/initialized_test_fail1.cpp
new file mode 100644
index 0000000..ffeecab
--- /dev/null
+++ b/test/initialized_test_fail1.cpp
@@ -0,0 +1,33 @@
+// Copyright 2010, Niels Dekker.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for boost::initialized<T>. Must fail to compile.
+//
+// Initial: 2 May 2010
+
+#include <boost/utility/value_init.hpp>
+
+namespace
+{
+  void direct_initialize_from_int()
+  {
+    // Okay: initialized<T> supports direct-initialization from T.
+    boost::initialized<int> direct_initialized_int(1);
+  }
+
+  void copy_initialize_from_int()
+  {
+    // The following line should not compile, because initialized<T> 
+    // was not intended to supports copy-initialization from T.
+    boost::initialized<int> copy_initialized_int = 1;
+  }
+}
+
+int main()
+{
+  // This should fail to compile, so there is no need to call any function.
+  return 0;
+}
diff --git a/test/initialized_test_fail2.cpp b/test/initialized_test_fail2.cpp
new file mode 100644
index 0000000..f3fbf39
--- /dev/null
+++ b/test/initialized_test_fail2.cpp
@@ -0,0 +1,37 @@
+// Copyright 2010, Niels Dekker.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for boost::initialized<T>. Must fail to compile.
+//
+// Initial: 2 May 2010
+
+#include <boost/utility/value_init.hpp>
+
+namespace
+{
+  void from_value_initialized_to_initialized()
+  {
+    boost::value_initialized<int> value_initialized_int;
+
+    // Okay: initialized<T> can be initialized by value_initialized<T>.
+    boost::initialized<int> initialized_int(value_initialized_int);
+  }
+
+  void from_initialized_to_value_initialized()
+  {
+    boost::initialized<int> initialized_int(13);
+
+    // The following line should not compile, because initialized<T>
+    // should not be convertible to value_initialized<T>.
+    boost::value_initialized<int> value_initialized_int(initialized_int);
+  }
+}
+
+int main()
+{
+  // This should fail to compile, so there is no need to call any function.
+  return 0;
+}
diff --git a/test/iterators_test.cpp b/test/iterators_test.cpp
new file mode 100644
index 0000000..8f2d04d
--- /dev/null
+++ b/test/iterators_test.cpp
@@ -0,0 +1,322 @@
+//  Demonstrate and test boost/operators.hpp on std::iterators  --------------//
+
+//  (C) Copyright Jeremy Siek 1999.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for most recent version including documentation.
+
+//  Revision History
+//  29 May 01 Factored implementation, added comparison tests, use Test Tools
+//            library (Daryle Walker)
+//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
+
+#include <boost/core/lightweight_test.hpp>
+
+#include <boost/config.hpp>     // for BOOST_STATIC_CONSTANT
+#include <boost/operators.hpp>  // for boost::random_access_iterator_helper
+
+#include <cstddef>    // for std::ptrdiff_t, std::size_t
+#include <cstring>    // for std::strcmp
+#include <iostream>   // for std::cout (std::endl, ends, and flush indirectly)
+#include <string>     // for std::string
+#include <sstream>    // for std::stringstream
+
+# ifdef BOOST_NO_STDC_NAMESPACE
+    namespace std { using ::strcmp; }
+# endif
+
+
+// Iterator test class
+template <class T, class R, class P>
+struct test_iter
+  : public boost::random_access_iterator_helper<
+     test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
+{
+  typedef test_iter self;
+  typedef R Reference;
+  typedef std::ptrdiff_t Distance;
+
+public:
+  explicit test_iter(T* i =0) : _i(i) { }
+  test_iter(const self& x) : _i(x._i) { }
+  self& operator=(const self& x) { _i = x._i; return *this; }
+  Reference operator*() const { return *_i; }
+  self& operator++() { ++_i; return *this; }
+  self& operator--() { --_i; return *this; }
+  self& operator+=(Distance n) { _i += n; return *this; }
+  self& operator-=(Distance n) { _i -= n; return *this; }
+  bool operator==(const self& x) const { return _i == x._i; }
+  bool operator<(const self& x) const { return _i < x._i; }
+  friend Distance operator-(const self& x, const self& y) {
+    return x._i - y._i; 
+  }
+protected:
+  P _i;
+};
+
+// Iterator operator testing classes
+class test_opr_base
+{
+protected:
+    // Test data and types
+    BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
+
+    typedef std::string  fruit_array_type[ fruit_length ];
+
+    static  fruit_array_type    fruit;
+
+};  // test_opr_base
+
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+//  A definition is required even for integral static constants
+const std::size_t test_opr_base::fruit_length;
+#endif
+
+template <typename T, typename R = T&, typename P = T*>
+class test_opr
+    : public test_opr_base
+{
+    typedef test_opr<T, R, P>  self_type;
+
+public:
+    // Types
+    typedef T  value_type;
+    typedef R  reference;
+    typedef P  pointer;
+
+    typedef test_iter<T, R, P>  iter_type;
+
+    // Test controller
+    static  void  master_test( char const name[] );
+
+private:
+    // Test data
+    static iter_type const  fruit_begin;
+    static iter_type const  fruit_end;
+
+    // Test parts
+    static  void  post_increment_test();
+    static  void  post_decrement_test();
+    static  void  indirect_referral_test();
+    static  void  offset_addition_test();
+    static  void  reverse_offset_addition_test();
+    static  void  offset_subtraction_test();
+    static  void  comparison_test();
+    static  void  indexing_test();
+
+};  // test_opr
+
+
+// Class-static data definitions
+test_opr_base::fruit_array_type
+ test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
+
+template <typename T, typename R, typename P>
+  typename test_opr<T, R, P>::iter_type const
+ test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
+
+template <typename T, typename R, typename P>
+typename test_opr<T, R, P>::iter_type const
+ test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
+
+
+// Main testing function
+int
+main()
+{
+    using std::string;
+
+    typedef test_opr<string, string &, string *>              test1_type;
+    typedef test_opr<string, string const &, string const *>  test2_type;
+
+    test1_type::master_test( "non-const string" );
+    test2_type::master_test( "const string" );
+
+    return boost::report_errors();
+}
+
+// Tests for all of the operators added by random_access_iterator_helper
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::master_test
+(
+    char const  name[]
+)
+{
+    std::cout << "Doing test run for " << name << '.' << std::endl;
+
+    post_increment_test();
+    post_decrement_test();
+    indirect_referral_test();
+    offset_addition_test();
+    reverse_offset_addition_test();
+    offset_subtraction_test();
+    comparison_test();
+    indexing_test();
+}
+
+// Test post-increment
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::post_increment_test
+(
+)
+{
+    std::cout << "\tDoing post-increment test." << std::endl;
+
+    std::stringstream oss;
+    for ( iter_type i = fruit_begin ; i != fruit_end ; )
+    {
+        oss << *i++ << ' ';
+    }
+
+    BOOST_TEST( oss.str() == "apple orange pear peach grape plum ");
+}
+
+// Test post-decrement
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::post_decrement_test
+(
+)
+{
+    std::cout << "\tDoing post-decrement test." << std::endl;
+
+    std::stringstream oss;
+    for ( iter_type i = fruit_end ; i != fruit_begin ; )
+    {
+        i--;
+        oss << *i << ' ';
+    }
+
+    BOOST_TEST( oss.str() == "plum grape peach pear orange apple ");
+}
+
+// Test indirect structure referral
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::indirect_referral_test
+(
+)
+{
+    std::cout << "\tDoing indirect reference test." << std::endl;
+
+    std::stringstream oss;
+    for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
+    {
+        oss << i->size() << ' ';
+    }
+
+    BOOST_TEST( oss.str() == "5 6 4 5 5 4 ");
+}
+
+// Test offset addition
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::offset_addition_test
+(
+)
+{
+    std::cout << "\tDoing offset addition test." << std::endl;
+
+    std::ptrdiff_t const  two = 2;
+    std::stringstream oss;
+    for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
+    {
+        oss << *i << ' ';
+    }
+
+    BOOST_TEST( oss.str() == "apple pear grape ");
+}
+
+// Test offset addition, in reverse order
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::reverse_offset_addition_test
+(
+)
+{
+    std::cout << "\tDoing reverse offset addition test." << std::endl;
+
+    std::ptrdiff_t const  two = 2;
+    std::stringstream oss;
+    for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
+    {
+        oss << *i << ' ';
+    }
+
+    BOOST_TEST( oss.str() == "apple pear grape ");
+}
+
+// Test offset subtraction
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::offset_subtraction_test
+(
+)
+{
+    std::cout << "\tDoing offset subtraction test." << std::endl;
+
+    std::ptrdiff_t const  two = 2;
+    std::stringstream oss;
+    for ( iter_type i = fruit_end ; fruit_begin < i ; )
+    {
+        i = i - two;
+        if ( (fruit_begin < i) || (fruit_begin == i) )
+        {
+            oss << *i << ' ';
+        }
+    }
+
+    BOOST_TEST( oss.str() == "grape pear apple ");
+}
+
+// Test comparisons
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::comparison_test
+(
+)
+{
+    using std::cout;
+    using std::ptrdiff_t;
+
+    cout << "\tDoing comparison tests.\n\t\tPass:";
+
+    for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
+    {
+        ptrdiff_t const  i_offset = i - fruit_begin;
+
+        cout << ' ' << *i << std::flush;
+        for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
+        {
+            ptrdiff_t const  j_offset = j - fruit_begin;
+
+            BOOST_TEST( (i != j) == (i_offset != j_offset) );
+            BOOST_TEST( (i > j) == (i_offset > j_offset) );
+            BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
+            BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
+        }
+    }
+    cout << std::endl;
+}
+
+// Test indexing
+template <typename T, typename R, typename P>
+void
+test_opr<T, R, P>::indexing_test
+(
+)
+{
+    std::cout << "\tDoing indexing test." << std::endl;
+
+    std::stringstream oss;
+    for ( std::size_t k = 0u ; k < fruit_length ; ++k )
+    {
+        oss << fruit_begin[ k ] << ' ';
+    }
+
+    BOOST_TEST( oss.str() == "apple orange pear peach grape plum ");
+}
diff --git a/test/operators_test.cpp b/test/operators_test.cpp
new file mode 100644
index 0000000..6cf7a76
--- /dev/null
+++ b/test/operators_test.cpp
@@ -0,0 +1,936 @@
+//  Demonstrate and test boost/operators.hpp  -------------------------------//
+
+//  Copyright Beman Dawes 1999.  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/utility for documentation.
+
+//  Revision History
+//  03 Apr 08 Added convertible_to_bool (Daniel Frey)
+//  01 Oct 01 Added tests for "left" operators
+//            and new grouped operators. (Helmut Zeisel)
+//  20 May 01 Output progress messages.  Added tests for new operator
+//            templates.  Updated random number generator.  Changed tests to
+//            use Boost Test Tools library.  (Daryle Walker)
+//  04 Jun 00 Added regression test for a bug I found (David Abrahams)
+//  17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
+//  ?? ??? 00 Major update to randomly test all one- and two- argument forms by
+//            wrapping integral types and comparing the results of operations
+//            to the results for the raw types (David Abrahams)
+//  12 Dec 99 Minor update, output confirmation message.
+//  15 Nov 99 Initial version
+
+#include <boost/config.hpp>                      // for BOOST_MSVC
+#include <boost/operators.hpp>                   // for the tested items
+#include <boost/utility/detail/minstd_rand.hpp>  // for boost::detail::minstd_rand
+#include <boost/core/lightweight_test.hpp>
+
+#include <iostream>  // for std::cout (std::endl indirectly)
+
+
+namespace
+{
+    // avoiding a template version of true_value so as to not confuse VC++
+    int true_value(int x) { return x; }
+    long true_value(long x) { return x; }
+    signed char true_value(signed char x) { return x; }
+    unsigned int true_value(unsigned int x) { return x; }
+    unsigned long true_value(unsigned long x) { return x; }
+    unsigned char true_value(unsigned char x) { return x; }
+
+    // verify the minimum requirements for some operators
+    class convertible_to_bool
+    {
+    private:
+        bool _value;
+
+        typedef bool convertible_to_bool::*unspecified_bool_type;
+
+        void operator!() const;
+
+    public:
+        convertible_to_bool( const bool value ) : _value( value ) {}
+
+        operator unspecified_bool_type() const
+          { return _value ? &convertible_to_bool::_value : 0; }
+    };
+
+    // The use of operators<> here tended to obscure
+    // interactions with certain compiler bugs
+    template <class T>
+    class Wrapped1
+        : boost::operators<Wrapped1<T> >
+        , boost::shiftable<Wrapped1<T> >
+    {
+    public:
+        explicit Wrapped1( T v = T() ) : _value(v) {}
+        T value() const { return _value; }
+
+        convertible_to_bool operator<(const Wrapped1& x) const
+          { return _value < x._value; }
+        convertible_to_bool operator==(const Wrapped1& x) const
+          { return _value == x._value; }
+        
+        Wrapped1& operator+=(const Wrapped1& x)
+          { _value += x._value; return *this; }
+        Wrapped1& operator-=(const Wrapped1& x)
+          { _value -= x._value; return *this; }
+        Wrapped1& operator*=(const Wrapped1& x)
+          { _value *= x._value; return *this; }
+        Wrapped1& operator/=(const Wrapped1& x)
+          { _value /= x._value; return *this; }
+        Wrapped1& operator%=(const Wrapped1& x)
+          { _value %= x._value; return *this; }
+        Wrapped1& operator|=(const Wrapped1& x)
+          { _value |= x._value; return *this; }
+        Wrapped1& operator&=(const Wrapped1& x)
+          { _value &= x._value; return *this; }
+        Wrapped1& operator^=(const Wrapped1& x)
+          { _value ^= x._value; return *this; }
+        Wrapped1& operator<<=(const Wrapped1& x)
+          { _value <<= x._value; return *this; }
+        Wrapped1& operator>>=(const Wrapped1& x)
+          { _value >>= x._value; return *this; }
+        Wrapped1& operator++()               { ++_value; return *this; }
+        Wrapped1& operator--()               { --_value; return *this; }
+        
+    private:
+        T _value;
+    };
+    template <class T>
+    T true_value(Wrapped1<T> x) { return x.value(); }    
+
+    template <class T, class U>
+    class Wrapped2
+        : boost::operators<Wrapped2<T, U> >
+        , boost::operators2<Wrapped2<T, U>, U>
+        , boost::shiftable1<Wrapped2<T, U>
+        , boost::shiftable2<Wrapped2<T, U>, U > >
+    {
+    public:
+        explicit Wrapped2( T v = T() ) : _value(v) {}
+        T value() const { return _value; }
+
+        convertible_to_bool operator<(const Wrapped2& x) const
+          { return _value < x._value; }
+        convertible_to_bool operator==(const Wrapped2& x) const
+          { return _value == x._value; }
+        
+        Wrapped2& operator+=(const Wrapped2& x)
+          { _value += x._value; return *this; }
+        Wrapped2& operator-=(const Wrapped2& x)
+          { _value -= x._value; return *this; }
+        Wrapped2& operator*=(const Wrapped2& x)
+          { _value *= x._value; return *this; }
+        Wrapped2& operator/=(const Wrapped2& x)
+          { _value /= x._value; return *this; }
+        Wrapped2& operator%=(const Wrapped2& x)
+          { _value %= x._value; return *this; }
+        Wrapped2& operator|=(const Wrapped2& x)
+          { _value |= x._value; return *this; }
+        Wrapped2& operator&=(const Wrapped2& x)
+          { _value &= x._value; return *this; }
+        Wrapped2& operator^=(const Wrapped2& x)
+          { _value ^= x._value; return *this; }
+        Wrapped2& operator<<=(const Wrapped2& x)
+          { _value <<= x._value; return *this; }
+        Wrapped2& operator>>=(const Wrapped2& x)
+          { _value >>= x._value; return *this; }
+        Wrapped2& operator++()                { ++_value; return *this; }
+        Wrapped2& operator--()                { --_value; return *this; }
+         
+        convertible_to_bool operator<(U u) const
+          { return _value < u; }
+        convertible_to_bool operator>(U u) const
+          { return _value > u; }
+        convertible_to_bool operator==(U u) const
+          { return _value == u; }
+
+        Wrapped2& operator+=(U u) { _value += u; return *this; }
+        Wrapped2& operator-=(U u) { _value -= u; return *this; }
+        Wrapped2& operator*=(U u) { _value *= u; return *this; }
+        Wrapped2& operator/=(U u) { _value /= u; return *this; }
+        Wrapped2& operator%=(U u) { _value %= u; return *this; }
+        Wrapped2& operator|=(U u) { _value |= u; return *this; }
+        Wrapped2& operator&=(U u) { _value &= u; return *this; }
+        Wrapped2& operator^=(U u) { _value ^= u; return *this; }
+        Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
+        Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
+
+    private:
+        T _value;
+    };
+    template <class T, class U>
+    T true_value(Wrapped2<T,U> x) { return x.value(); }
+    
+    template <class T>
+    class Wrapped3
+        : boost::equivalent<Wrapped3<T> >
+        , boost::partially_ordered<Wrapped3<T> >
+        , boost::equality_comparable<Wrapped3<T> >
+    {
+    public:
+        explicit Wrapped3( T v = T() ) : _value(v) {}
+        T value() const { return _value; }
+
+        convertible_to_bool operator<(const Wrapped3& x) const
+          { return _value < x._value; }
+        
+    private:
+        T _value;
+    };
+    template <class T>
+    T true_value(Wrapped3<T> x) { return x.value(); }    
+
+    template <class T, class U>
+    class Wrapped4
+        : boost::equality_comparable1<Wrapped4<T, U>
+        , boost::equivalent1<Wrapped4<T, U>
+        , boost::partially_ordered1<Wrapped4<T, U> > > >
+        , boost::partially_ordered2<Wrapped4<T, U>, U
+        , boost::equivalent2<Wrapped4<T, U>, U
+        , boost::equality_comparable2<Wrapped4<T, U>, U> > >
+    {
+    public:
+        explicit Wrapped4( T v = T() ) : _value(v) {}
+        T value() const { return _value; }
+
+        convertible_to_bool operator<(const Wrapped4& x) const
+          { return _value < x._value; }
+         
+        convertible_to_bool operator<(U u) const
+          { return _value < u; }
+        convertible_to_bool operator>(U u) const
+          { return _value > u; }
+
+    private:
+        T _value;
+    };
+    template <class T, class U>
+    T true_value(Wrapped4<T,U> x) { return x.value(); }
+    
+    // U must be convertible to T
+    template <class T, class U>
+    class Wrapped5
+        : boost::ordered_field_operators2<Wrapped5<T, U>, U>
+        , boost::ordered_field_operators1<Wrapped5<T, U> >
+    {
+    public:
+        explicit Wrapped5( T v = T() ) : _value(v) {}
+
+        // Conversion from U to Wrapped5<T,U>
+        Wrapped5(U u) : _value(u) {}
+
+        T value() const { return _value; }
+
+        convertible_to_bool operator<(const Wrapped5& x) const
+          { return _value < x._value; }
+        convertible_to_bool operator<(U u) const
+          { return _value < u; }
+        convertible_to_bool operator>(U u) const
+          { return _value > u; }
+        convertible_to_bool operator==(const Wrapped5& u) const
+          { return _value == u._value; }
+        convertible_to_bool operator==(U u) const
+          { return _value == u; }
+
+        Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;}
+        Wrapped5& operator/=(U u) { _value /= u; return *this;}
+        Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;}
+        Wrapped5& operator*=(U u) { _value *= u; return *this;}
+        Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;}
+        Wrapped5& operator-=(U u) { _value -= u; return *this;}
+        Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;}
+        Wrapped5& operator+=(U u) { _value += u; return *this;}
+
+    private:
+        T _value;
+    };
+    template <class T, class U>
+    T true_value(Wrapped5<T,U> x) { return x.value(); }
+    
+    // U must be convertible to T
+    template <class T, class U>
+    class Wrapped6
+        : boost::ordered_euclidean_ring_operators2<Wrapped6<T, U>, U>
+        , boost::ordered_euclidean_ring_operators1<Wrapped6<T, U> >
+    {
+    public:
+        explicit Wrapped6( T v = T() ) : _value(v) {}
+
+        // Conversion from U to Wrapped6<T,U>
+        Wrapped6(U u) : _value(u) {}
+
+        T value() const { return _value; }
+
+        convertible_to_bool operator<(const Wrapped6& x) const
+          { return _value < x._value; }
+        convertible_to_bool operator<(U u) const
+          { return _value < u; }
+        convertible_to_bool operator>(U u) const
+          { return _value > u; }
+        convertible_to_bool operator==(const Wrapped6& u) const
+          { return _value == u._value; }
+        convertible_to_bool operator==(U u) const
+          { return _value == u; }
+
+        Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;}
+        Wrapped6& operator%=(U u) { _value %= u; return *this;}
+        Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;}
+        Wrapped6& operator/=(U u) { _value /= u; return *this;}
+        Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;}
+        Wrapped6& operator*=(U u) { _value *= u; return *this;}
+        Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;}
+        Wrapped6& operator-=(U u) { _value -= u; return *this;}
+        Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;}
+        Wrapped6& operator+=(U u) { _value += u; return *this;}
+
+    private:
+        T _value;
+    };
+    template <class T, class U>
+    T true_value(Wrapped6<T,U> x) { return x.value(); }
+    
+    //  MyInt uses only the single template-argument form of all_operators<>
+    typedef Wrapped1<int> MyInt;
+
+    typedef Wrapped2<long, long> MyLong;
+
+    typedef Wrapped3<signed char> MyChar;
+
+    typedef Wrapped4<short, short> MyShort;
+
+    typedef Wrapped5<double, int> MyDoubleInt;
+
+    typedef Wrapped6<long, int> MyLongInt;
+
+    template <class X1, class Y1, class X2, class Y2>
+    void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        BOOST_TEST( true_value(y1) == true_value(y2) );
+        BOOST_TEST( true_value(x1) == true_value(x2) );
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        BOOST_TEST( static_cast<bool>(x1 < y1) == static_cast<bool>(x2 < y2) );
+        BOOST_TEST( static_cast<bool>(x1 <= y1) == static_cast<bool>(x2 <= y2) );
+        BOOST_TEST( static_cast<bool>(x1 >= y1) == static_cast<bool>(x2 >= y2) );
+        BOOST_TEST( static_cast<bool>(x1 > y1) == static_cast<bool>(x2 > y2) );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_less_than_comparable_aux( x1, y1, x2, y2 );
+        test_less_than_comparable_aux( y1, x1, y2, x2 );
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        BOOST_TEST( static_cast<bool>(x1 == y1) == static_cast<bool>(x2 == y2) );
+        BOOST_TEST( static_cast<bool>(x1 != y1) == static_cast<bool>(x2 != y2) );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_equality_comparable_aux( x1, y1, x2, y2 );
+        test_equality_comparable_aux( y1, x1, y2, x2 );
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_multipliable_aux( x1, y1, x2, y2 );
+        test_multipliable_aux( y1, x1, y2, x2 );
+    }
+
+  template <class A, class B>
+  void test_value_equality(A a, B b)
+  {
+      BOOST_TEST(a.value() == b);
+  }
+  
+#define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2)
+#define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2)
+  
+    template <class X1, class Y1, class X2, class Y2>
+    void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        TEST_OP_R(+);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_addable_aux( x1, y1, x2, y2 );
+        test_addable_aux( y1, x1, y2, x2 );
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        TEST_OP_R(-);
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        TEST_OP_L(-);
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        if ( y2 != 0 )
+            TEST_OP_R(/);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        if ( x2 != 0 )
+            TEST_OP_L(/);
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        if ( y2 != 0 )
+            TEST_OP_R(%);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        if ( x2 != 0 )
+            TEST_OP_L(%);
+    }
+
+    template <class X1, class Y1, class X2, class Y2>
+    void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        TEST_OP_R(^);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_xorable_aux( x1, y1, x2, y2 );
+        test_xorable_aux( y1, x1, y2, x2 );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        TEST_OP_R(&);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_andable_aux( x1, y1, x2, y2 );
+        test_andable_aux( y1, x1, y2, x2 );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        TEST_OP_R(|);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        test_orable_aux( x1, y1, x2, y2 );
+        test_orable_aux( y1, x1, y2, x2 );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        TEST_OP_R(<<);
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        sanity_check( x1, y1, x2, y2 );
+        TEST_OP_R(>>);
+    }
+    
+    template <class X1, class X2>
+    void test_incrementable(X1 x1, X2 x2)
+    {
+        sanity_check( x1, x1, x2, x2 );
+        BOOST_TEST( (x1++).value() == x2++ );
+        BOOST_TEST( x1.value() == x2 );
+    }
+    
+    template <class X1, class X2>
+    void test_decrementable(X1 x1, X2 x2)
+    {
+        sanity_check( x1, x1, x2, x2 );
+        BOOST_TEST( (x1--).value() == x2-- );
+        BOOST_TEST( x1.value() == x2 );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        test_less_than_comparable( x1, y1, x2, y2 );
+        test_equality_comparable( x1, y1, x2, y2 );
+        test_multipliable( x1, y1, x2, y2 );
+        test_addable( x1, y1, x2, y2 );
+        test_subtractable( x1, y1, x2, y2 );
+        test_dividable( x1, y1, x2, y2 );
+        test_modable( x1, y1, x2, y2 );
+        test_xorable( x1, y1, x2, y2 );
+        test_andable( x1, y1, x2, y2 );
+        test_orable( x1, y1, x2, y2 );
+        test_left_shiftable( x1, y1, x2, y2 );
+        test_right_shiftable( x1, y1, x2, y2 );
+        test_incrementable( x1, x2 );
+        test_decrementable( x1, x2 );
+    }
+    
+    template <class X1, class Y1, class X2, class Y2>
+    void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
+    {
+        test_subtractable_left( x1, y1, x2, y2 );
+        test_dividable_left( x1, y1, x2, y2 );
+        test_modable_left( x1, y1, x2, y2 );
+     }
+
+    template <class Big, class Small>
+    struct tester
+    {
+        void operator()(boost::detail::minstd_rand& randomizer) const
+        {
+            Big    b1 = Big( randomizer() );
+            Big    b2 = Big( randomizer() );
+            Small  s = Small( randomizer() );
+            
+            test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
+            test_all( Wrapped2<Big, Small>(b1), s, b1, s );
+        }
+    };
+
+    template <class Big, class Small>
+    struct tester_left
+    {
+        void operator()(boost::detail::minstd_rand& randomizer) const
+        {
+            Big    b1 = Big( randomizer() );
+            Small  s = Small( randomizer() );
+            
+            test_left( Wrapped6<Big, Small>(b1), s, b1, s );
+         }
+    };
+
+    // added as a regression test. We had a bug which this uncovered.
+    struct Point
+        : boost::addable<Point
+        , boost::subtractable<Point> >
+    {
+        Point( int h, int v ) : h(h), v(v) {}
+        Point() :h(0), v(0) {}
+        const Point& operator+=( const Point& rhs )
+            { h += rhs.h; v += rhs.v; return *this; }
+        const Point& operator-=( const Point& rhs )
+            { h -= rhs.h; v -= rhs.v; return *this; }
+
+        int h;
+        int v;
+    };
+
+} // unnamed namespace
+
+
+// workaround for MSVC bug; for some reasons the compiler doesn't instantiate
+// inherited operator templates at the moment it must, so the following
+// explicit instantiations force it to do that.
+
+#if defined(BOOST_MSVC) && (_MSC_VER < 1300)
+template Wrapped1<int>;
+template Wrapped1<long>;
+template Wrapped1<unsigned int>;
+template Wrapped1<unsigned long>;
+
+template Wrapped2<int, int>;
+template Wrapped2<int, signed char>;
+template Wrapped2<long, signed char>;
+template Wrapped2<long, int>;
+template Wrapped2<long, long>;
+template Wrapped2<unsigned int, unsigned int>;
+template Wrapped2<unsigned int, unsigned char>;
+template Wrapped2<unsigned long, unsigned int>;
+template Wrapped2<unsigned long, unsigned char>;
+template Wrapped2<unsigned long, unsigned long>;
+
+template Wrapped6<long, int>;
+template Wrapped6<long, signed char>;
+template Wrapped6<int, signed char>;
+template Wrapped6<unsigned long, unsigned int>;
+template Wrapped6<unsigned long, unsigned char>;
+template Wrapped6<unsigned int, unsigned char>;
+#endif
+
+#define PRIVATE_EXPR_TEST(e, t)  BOOST_TEST( ((e), (t)) )
+
+int
+main()
+{
+    using std::cout;
+    using std::endl;
+
+    // Regression test.
+    Point x;
+    x = x + Point(3, 4);
+    x = x - Point(3, 4);
+    
+    cout << "Created point, and operated on it." << endl;
+    
+    for (int n = 0; n < 1000; ++n)  // was 10,000 but took too long (Beman)
+    {
+        boost::detail::minstd_rand r;
+        tester<long, int>()(r);
+        tester<long, signed char>()(r);
+        tester<long, long>()(r);
+        tester<int, int>()(r);
+        tester<int, signed char>()(r);
+        
+        tester<unsigned long, unsigned int>()(r);
+        tester<unsigned long, unsigned char>()(r);
+        tester<unsigned long, unsigned long>()(r);
+        tester<unsigned int, unsigned int>()(r);
+        tester<unsigned int, unsigned char>()(r);
+
+        tester_left<long, int>()(r);
+        tester_left<long, signed char>()(r);
+        tester_left<int, signed char>()(r);
+
+        tester_left<unsigned long, unsigned int>()(r);
+        tester_left<unsigned long, unsigned char>()(r);
+        tester_left<unsigned int, unsigned char>()(r);
+    }
+    
+    cout << "Did random tester loop." << endl;
+
+    MyInt i1(1);
+    MyInt i2(2);
+    MyInt i;
+
+    BOOST_TEST( i1.value() == 1 );
+    BOOST_TEST( i2.value() == 2 );
+    BOOST_TEST( i.value() == 0 );
+
+    cout << "Created MyInt objects.\n";
+
+    PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
+
+    BOOST_TEST( static_cast<bool>(i2 == i) );
+    BOOST_TEST( static_cast<bool>(i1 != i2) );
+    BOOST_TEST( static_cast<bool>(i1 <  i2) );
+    BOOST_TEST( static_cast<bool>(i1 <= i2) );
+    BOOST_TEST( static_cast<bool>(i <= i2) );
+    BOOST_TEST( static_cast<bool>(i2 >  i1) );
+    BOOST_TEST( static_cast<bool>(i2 >= i1) );
+    BOOST_TEST( static_cast<bool>(i2 >= i) );
+
+    PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
+    PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
+    PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
+    PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
+    PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
+    PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
+    PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
+    PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
+    PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
+    PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
+    PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
+    PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
+
+    PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
+    PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
+
+    cout << "Performed tests on MyInt objects.\n";
+
+    MyLong j1(1);
+    MyLong j2(2);
+    MyLong j;
+
+    BOOST_TEST( j1.value() == 1 );
+    BOOST_TEST( j2.value() == 2 );
+    BOOST_TEST( j.value() == 0 );
+
+    cout << "Created MyLong objects.\n";
+
+    PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
+    
+    BOOST_TEST( static_cast<bool>(j2 == j) );
+    BOOST_TEST( static_cast<bool>(2 == j) );
+    BOOST_TEST( static_cast<bool>(j2 == 2) );
+    BOOST_TEST( static_cast<bool>(j == j2) );
+    BOOST_TEST( static_cast<bool>(j1 != j2) );
+    BOOST_TEST( static_cast<bool>(j1 != 2) );
+    BOOST_TEST( static_cast<bool>(1 != j2) );
+    BOOST_TEST( static_cast<bool>(j1 <  j2) );
+    BOOST_TEST( static_cast<bool>(1 <  j2) );
+    BOOST_TEST( static_cast<bool>(j1 <  2) );
+    BOOST_TEST( static_cast<bool>(j1 <= j2) );
+    BOOST_TEST( static_cast<bool>(1 <= j2) );
+    BOOST_TEST( static_cast<bool>(j1 <= j) );
+    BOOST_TEST( static_cast<bool>(j <= j2) );
+    BOOST_TEST( static_cast<bool>(2 <= j2) );
+    BOOST_TEST( static_cast<bool>(j <= 2) );
+    BOOST_TEST( static_cast<bool>(j2 >  j1) );
+    BOOST_TEST( static_cast<bool>(2 >  j1) );
+    BOOST_TEST( static_cast<bool>(j2 >  1) );
+    BOOST_TEST( static_cast<bool>(j2 >= j1) );
+    BOOST_TEST( static_cast<bool>(2 >= j1) );
+    BOOST_TEST( static_cast<bool>(j2 >= 1) );
+    BOOST_TEST( static_cast<bool>(j2 >= j) );
+    BOOST_TEST( static_cast<bool>(2 >= j) );
+    BOOST_TEST( static_cast<bool>(j2 >= 2) );
+
+    BOOST_TEST( static_cast<bool>((j1 + 2) == 3) );
+    BOOST_TEST( static_cast<bool>((1 + j2) == 3) );
+    PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
+    
+    BOOST_TEST( static_cast<bool>((j + 2) == 5) );
+    BOOST_TEST( static_cast<bool>((3 + j2) == 5) );
+    PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
+    
+    BOOST_TEST( static_cast<bool>((j - 1) == 4) );
+    PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
+    
+    BOOST_TEST( static_cast<bool>((j * 2) == 8) );
+    BOOST_TEST( static_cast<bool>((4 * j2) == 8) );
+    PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
+    
+    BOOST_TEST( static_cast<bool>((j / 2) == 4) );
+    PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
+    
+    BOOST_TEST( static_cast<bool>((j % 3) == 1) );
+    PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
+    
+    PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
+    
+    BOOST_TEST( static_cast<bool>((1 | j2 | j) == 7) );
+    BOOST_TEST( static_cast<bool>((j1 | 2 | j) == 7) );
+    BOOST_TEST( static_cast<bool>((j1 | j2 | 4) == 7) );
+    PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
+    
+    BOOST_TEST( static_cast<bool>((7 & j2) == 2) );
+    BOOST_TEST( static_cast<bool>((j & 2) == 2) );
+    PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
+    
+    PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
+    
+    BOOST_TEST( static_cast<bool>((3 ^ j1) == 2) );
+    BOOST_TEST( static_cast<bool>((j ^ 1) == 2) );
+    PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
+    
+    PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
+
+    BOOST_TEST( static_cast<bool>((j1 << 2) == 4) );
+    BOOST_TEST( static_cast<bool>((j2 << 1) == 4) );
+    PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
+
+    BOOST_TEST( static_cast<bool>((j >> 2) == 1) );
+    BOOST_TEST( static_cast<bool>((j2 >> 1) == 1) );
+    PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
+    
+    cout << "Performed tests on MyLong objects.\n";
+
+    MyChar k1(1);
+    MyChar k2(2);
+    MyChar k;
+
+    BOOST_TEST( k1.value() == 1 );
+    BOOST_TEST( k2.value() == 2 );
+    BOOST_TEST( k.value() == 0 );
+
+    cout << "Created MyChar objects.\n";
+
+    PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
+
+    BOOST_TEST( static_cast<bool>(k2 == k) );
+    BOOST_TEST( static_cast<bool>(k1 != k2) );
+    BOOST_TEST( static_cast<bool>(k1 <  k2) );
+    BOOST_TEST( static_cast<bool>(k1 <= k2) );
+    BOOST_TEST( static_cast<bool>(k <= k2) );
+    BOOST_TEST( static_cast<bool>(k2 >  k1) );
+    BOOST_TEST( static_cast<bool>(k2 >= k1) );
+    BOOST_TEST( static_cast<bool>(k2 >= k) );
+    
+    cout << "Performed tests on MyChar objects.\n";
+
+    MyShort l1(1);
+    MyShort l2(2);
+    MyShort l;
+
+    BOOST_TEST( l1.value() == 1 );
+    BOOST_TEST( l2.value() == 2 );
+    BOOST_TEST( l.value() == 0 );
+
+    cout << "Created MyShort objects.\n";
+
+    PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
+    
+    BOOST_TEST( static_cast<bool>(l2 == l) );
+    BOOST_TEST( static_cast<bool>(2 == l) );
+    BOOST_TEST( static_cast<bool>(l2 == 2) );
+    BOOST_TEST( static_cast<bool>(l == l2) );
+    BOOST_TEST( static_cast<bool>(l1 != l2) );
+    BOOST_TEST( static_cast<bool>(l1 != 2) );
+    BOOST_TEST( static_cast<bool>(1 != l2) );
+    BOOST_TEST( static_cast<bool>(l1 <  l2) );
+    BOOST_TEST( static_cast<bool>(1 <  l2) );
+    BOOST_TEST( static_cast<bool>(l1 <  2) );
+    BOOST_TEST( static_cast<bool>(l1 <= l2) );
+    BOOST_TEST( static_cast<bool>(1 <= l2) );
+    BOOST_TEST( static_cast<bool>(l1 <= l) );
+    BOOST_TEST( static_cast<bool>(l <= l2) );
+    BOOST_TEST( static_cast<bool>(2 <= l2) );
+    BOOST_TEST( static_cast<bool>(l <= 2) );
+    BOOST_TEST( static_cast<bool>(l2 >  l1) );
+    BOOST_TEST( static_cast<bool>(2 >  l1) );
+    BOOST_TEST( static_cast<bool>(l2 >  1) );
+    BOOST_TEST( static_cast<bool>(l2 >= l1) );
+    BOOST_TEST( static_cast<bool>(2 >= l1) );
+    BOOST_TEST( static_cast<bool>(l2 >= 1) );
+    BOOST_TEST( static_cast<bool>(l2 >= l) );
+    BOOST_TEST( static_cast<bool>(2 >= l) );
+    BOOST_TEST( static_cast<bool>(l2 >= 2) );
+    
+    cout << "Performed tests on MyShort objects.\n";
+    
+    MyDoubleInt di1(1);
+    MyDoubleInt di2(2.);
+    MyDoubleInt half(0.5);
+    MyDoubleInt di;
+    MyDoubleInt tmp;
+
+    BOOST_TEST( di1.value() == 1 );
+    BOOST_TEST( di2.value() == 2 );
+    BOOST_TEST( di2.value() == 2 );
+    BOOST_TEST( di.value() == 0 );
+
+    cout << "Created MyDoubleInt objects.\n";
+
+    PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
+    
+    BOOST_TEST( static_cast<bool>(di2 == di) );
+    BOOST_TEST( static_cast<bool>(2 == di) );
+    BOOST_TEST( static_cast<bool>(di == 2) );
+    BOOST_TEST( static_cast<bool>(di1 < di2) );
+    BOOST_TEST( static_cast<bool>(1 < di2) );
+    BOOST_TEST( static_cast<bool>(di1 <= di2) );
+    BOOST_TEST( static_cast<bool>(1 <= di2) );
+    BOOST_TEST( static_cast<bool>(di2 > di1) );
+    BOOST_TEST( static_cast<bool>(di2 > 1) );
+    BOOST_TEST( static_cast<bool>(di2 >= di1) );
+    BOOST_TEST( static_cast<bool>(di2 >= 1) );
+    BOOST_TEST( static_cast<bool>(di1 / di2 == half) );
+    BOOST_TEST( static_cast<bool>(di1 / 2 == half) );
+    BOOST_TEST( static_cast<bool>(1 / di2 == half) );
+    PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp/=2) == half) );
+    PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp/=di2) == half) );
+    BOOST_TEST( static_cast<bool>(di1 * di2 == di2) );
+    BOOST_TEST( static_cast<bool>(di1 * 2 == di2) );
+    BOOST_TEST( static_cast<bool>(1 * di2 == di2) );
+    PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp*=2) == di2) );
+    PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp*=di2) == di2) );
+    BOOST_TEST( static_cast<bool>(di2 - di1 == di1) );
+    BOOST_TEST( static_cast<bool>(di2 - 1 == di1) );
+    BOOST_TEST( static_cast<bool>(2 - di1 == di1) );
+    PRIVATE_EXPR_TEST( (tmp=di2), static_cast<bool>((tmp-=1) == di1) );
+    PRIVATE_EXPR_TEST( (tmp=di2), static_cast<bool>((tmp-=di1) == di1) );
+    BOOST_TEST( static_cast<bool>(di1 + di1 == di2) );
+    BOOST_TEST( static_cast<bool>(di1 + 1 == di2) );
+    BOOST_TEST( static_cast<bool>(1 + di1 == di2) );
+    PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp+=1) == di2) );
+    PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp+=di1) == di2) );
+
+    cout << "Performed tests on MyDoubleInt objects.\n";
+
+    MyLongInt li1(1);
+    MyLongInt li2(2);
+    MyLongInt li;
+    MyLongInt tmp2;
+
+    BOOST_TEST( li1.value() == 1 );
+    BOOST_TEST( li2.value() == 2 );
+    BOOST_TEST( li.value() == 0 );
+
+    cout << "Created MyLongInt objects.\n";
+
+    PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
+    
+    BOOST_TEST( static_cast<bool>(li2 == li) );
+    BOOST_TEST( static_cast<bool>(2 == li) );
+    BOOST_TEST( static_cast<bool>(li == 2) );
+    BOOST_TEST( static_cast<bool>(li1 < li2) );
+    BOOST_TEST( static_cast<bool>(1 < li2) );
+    BOOST_TEST( static_cast<bool>(li1 <= li2) );
+    BOOST_TEST( static_cast<bool>(1 <= li2) );
+    BOOST_TEST( static_cast<bool>(li2 > li1) );
+    BOOST_TEST( static_cast<bool>(li2 > 1) );
+    BOOST_TEST( static_cast<bool>(li2 >= li1) );
+    BOOST_TEST( static_cast<bool>(li2 >= 1) );
+    BOOST_TEST( static_cast<bool>(li1 % li2 == li1) );
+    BOOST_TEST( static_cast<bool>(li1 % 2 == li1) );
+    BOOST_TEST( static_cast<bool>(1 % li2 == li1) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2%=2) == li1) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2%=li2) == li1) );
+    BOOST_TEST( static_cast<bool>(li1 / li2 == 0) );
+    BOOST_TEST( static_cast<bool>(li1 / 2 == 0) );
+    BOOST_TEST( static_cast<bool>(1 / li2 == 0) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2/=2) == 0) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2/=li2) == 0) );
+    BOOST_TEST( static_cast<bool>(li1 * li2 == li2) );
+    BOOST_TEST( static_cast<bool>(li1 * 2 == li2) );
+    BOOST_TEST( static_cast<bool>(1 * li2 == li2) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2*=2) == li2) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2*=li2) == li2) );
+    BOOST_TEST( static_cast<bool>(li2 - li1 == li1) );
+    BOOST_TEST( static_cast<bool>(li2 - 1 == li1) );
+    BOOST_TEST( static_cast<bool>(2 - li1 == li1) );
+    PRIVATE_EXPR_TEST( (tmp2=li2), static_cast<bool>((tmp2-=1) == li1) );
+    PRIVATE_EXPR_TEST( (tmp2=li2), static_cast<bool>((tmp2-=li1) == li1) );
+    BOOST_TEST( static_cast<bool>(li1 + li1 == li2) );
+    BOOST_TEST( static_cast<bool>(li1 + 1 == li2) );
+    BOOST_TEST( static_cast<bool>(1 + li1 == li2) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2+=1) == li2) );
+    PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2+=li1) == li2) );
+
+    cout << "Performed tests on MyLongInt objects.\n";
+
+    return boost::report_errors();
+}
diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp
new file mode 100644
index 0000000..290043b
--- /dev/null
+++ b/test/result_of_test.cpp
@@ -0,0 +1,322 @@
+// Boost result_of library
+
+//  Copyright Douglas Gregor 2003-2004. Use, modification and
+//  distribution is subject to the Boost Software License, Version
+//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+// Examples:
+//   To run the default test:
+//   $ cd libs/utility/test && bjam
+//   To test decltype on g++ 2.7:
+//   $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE"
+
+#include <boost/config.hpp>
+
+// For more information, see http://www.boost.org/libs/utility
+#include <boost/utility/result_of.hpp>
+#include <utility>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+struct int_result_type
+{
+  typedef int result_type;
+  result_type operator()(float);
+};
+
+struct int_result_of
+{
+  template<typename F> struct result { typedef int type; };
+  result<int_result_of(double)>::type operator()(double);
+  result<const int_result_of(double)>::type operator()(double) const;
+  result<int_result_of()>::type operator()();
+  result<volatile int_result_of()>::type operator()() volatile;
+};
+
+struct int_result_type_and_float_result_of_and_char_return
+{
+  typedef int result_type;
+  template<typename F> struct result { typedef float type; };
+  char operator()(char);
+};
+
+template<typename T>
+struct int_result_type_template
+{
+  typedef int result_type;
+  result_type operator()(float);
+};
+
+template<typename T>
+struct int_result_of_template
+{
+  template<typename F> struct result;
+  template<typename This, typename That> struct result<This(That)> { typedef int type; };
+  typename result<int_result_of_template<T>(double)>::type operator()(double);
+  typename result<const int_result_of_template<T>(double)>::type operator()(double) const;
+  typename result<int_result_of_template<T>(double)>::type operator()();
+  typename result<volatile int_result_of_template<T>(double)>::type operator()() volatile;
+};
+
+template<typename T>
+struct int_result_type_and_float_result_of_and_char_return_template
+{
+  typedef int result_type;
+  template<typename F> struct result;
+  template<typename This, typename That> struct result<This(That)> { typedef float type; };
+  char operator()(char);
+};
+
+template<typename T>
+struct cv_overload_check {};
+
+struct result_of_member_function_template
+{
+  template<typename F> struct result;
+
+  template<typename This, typename That> struct result<This(That)> { typedef That type; };
+  template<class T> typename result<result_of_member_function_template(T)>::type operator()(T);
+
+  template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; };
+  template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const;
+
+  template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; };
+  template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile;
+
+  template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; };
+  template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile;
+
+  template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; };
+  template<class T> typename result<result_of_member_function_template(T &, T)>::type operator()(T &, T);
+
+  template<typename This, typename That> struct result<This(That const &, That)> { typedef That const & type; };
+  template<class T> typename result<result_of_member_function_template(T const &, T)>::type operator()(T const &, T);
+
+  template<typename This, typename That> struct result<This(That volatile &, That)> { typedef That volatile & type; };
+  template<class T> typename result<result_of_member_function_template(T volatile &, T)>::type operator()(T volatile &, T);
+
+  template<typename This, typename That> struct result<This(That const volatile &, That)> { typedef That const volatile & type; };
+  template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T);
+};
+
+struct no_result_type_or_result
+{
+  short operator()(double);
+  cv_overload_check<const short> operator()(double) const;
+  cv_overload_check<volatile short> operator()(double) volatile;
+  cv_overload_check<const volatile short> operator()(double) const volatile;
+  int operator()();
+  cv_overload_check<const int> operator()() const;
+  cv_overload_check<volatile int> operator()() volatile;
+  cv_overload_check<const volatile int> operator()() const volatile;
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+  short operator()(int&&);
+  int operator()(int&);
+  long operator()(int const&);
+#endif
+};
+
+template<typename T>
+struct no_result_type_or_result_template
+{
+  short operator()(double);
+  cv_overload_check<const short> operator()(double) const;
+  cv_overload_check<volatile short> operator()(double) volatile;
+  cv_overload_check<const volatile short> operator()(double) const volatile;
+  int operator()();
+  cv_overload_check<const int> operator()() const;
+  cv_overload_check<volatile int> operator()() volatile;
+  cv_overload_check<const volatile int> operator()() const volatile;
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+  short operator()(int&&);
+  int operator()(int&);
+  long operator()(int const&);
+#endif
+};
+
+// sfinae_tests are derived from example code from Joel de Guzman,
+// which demonstrated the interaction between result_of and SFINAE.
+template <typename F, typename Arg>
+typename boost::result_of<F(Arg const&)>::type
+sfinae_test(F f, Arg const& arg)
+{
+    return f(arg);
+}
+
+template <typename F, typename Arg>
+typename boost::result_of<F(Arg&)>::type
+sfinae_test(F f, Arg& arg)
+{
+    return f(arg);
+}
+
+int sfinae_test_f(int& i)
+{
+    return i;
+}
+
+struct X {};
+
+int main()
+{
+  using namespace boost;
+
+  typedef int (*func_ptr)(float, double);
+  typedef int (&func_ref)(float, double);
+  typedef int (*func_ptr_0)();
+  typedef int (&func_ref_0)();
+  typedef void (*func_ptr_void)(float, double);
+  typedef void (&func_ref_void)(float, double);
+  typedef void (*func_ptr_void_0)();
+  typedef void (&func_ref_void_0)();
+  typedef int (X::*mem_func_ptr)(float);
+  typedef int (X::*mem_func_ptr_c)(float) const;
+  typedef int (X::*mem_func_ptr_v)(float) volatile;
+  typedef int (X::*mem_func_ptr_cv)(float) const volatile;
+  typedef int (X::*mem_func_ptr_0)();
+
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_type(float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_template<void>(float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of_template<void>(double)>::type, int>::value));
+
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type(float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_template<void>(float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of_template<void>(double)>::type, int>::value));
+
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(void)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of(void)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(void)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
+
+  // Prior to decltype, result_of could not deduce the return type
+  // of nullary function objects unless they exposed a result_type.
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, int>::value));
+#else
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
+#endif
+
+  // Prior to decltype, result_of ignored a nested result<> if
+  // result_type was defined. After decltype, result_of deduces the
+  // actual return type of the function object, ignoring both
+  // result<> and result_type.
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value));
+#else
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
+#endif
+
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
+
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value)); 
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value)); 
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value)); 
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value)); 
+  BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value)); 
+
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value)); 
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value)); 
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value)); 
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value)); 
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value)); 
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(void)>::type, int>::value));
+
+  BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
+
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
+
+  typedef int (*pf_t)(int);
+  BOOST_STATIC_ASSERT((is_same<result_of<pf_t(int)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<pf_t const(int)>::type,int>::value));
+
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t(int)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t const(int)>::type,int>::value));
+
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(double)>::type, short>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value));
+
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const volatile short> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value));
+
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ptr&(char, float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<func_ptr const&(char, float)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of&(double)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<int_result_of const&(double)>::type, int>::value));
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value));
+  BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value));
+#endif
+#endif
+
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
+  int i = 123;
+  sfinae_test(sfinae_test_f, i);
+#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
+
+  return 0;
+}
diff --git a/test/string_ref_from_rvalue.cpp b/test/string_ref_from_rvalue.cpp
new file mode 100644
index 0000000..6ec8a5a
--- /dev/null
+++ b/test/string_ref_from_rvalue.cpp
@@ -0,0 +1,26 @@
+/*
+   Copyright (c) Marshall Clow 2017.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+
+#include <boost/utility/string_ref.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+#error "Unsupported test"
+#endif
+
+std::string makeatemp() { return "abc"; }
+
+int main()
+{
+  boost::basic_string_ref<char> sv(makeatemp());
+  return 0;
+}
diff --git a/test/string_ref_test1.cpp b/test/string_ref_test1.cpp
new file mode 100644
index 0000000..fc88905
--- /dev/null
+++ b/test/string_ref_test1.cpp
@@ -0,0 +1,110 @@
+/*
+   Copyright (c) Marshall Clow 2012-2012.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+
+#include <boost/utility/string_ref.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+typedef boost::string_ref string_ref;
+
+//  Should be equal
+void interop ( const std::string &str, string_ref ref ) {
+//  BOOST_TEST ( str == ref );
+    BOOST_TEST ( str.size () == ref.size ());
+    BOOST_TEST ( std::equal ( str.begin (),  str.end (),  ref.begin ()));
+    BOOST_TEST ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
+    }
+
+void null_tests ( const char *p ) {
+//  All zero-length string-refs should be equal
+    string_ref sr1; // NULL, 0
+    string_ref sr2 ( NULL, 0 );
+    string_ref sr3 ( p, 0 );
+    string_ref sr4 ( p );
+    sr4.clear ();
+
+    BOOST_TEST ( sr1 == sr2 );
+    BOOST_TEST ( sr1 == sr3 );
+    BOOST_TEST ( sr2 == sr3 );
+    BOOST_TEST ( sr1 == sr4 );
+    }
+
+//  make sure that substrings work just like strings
+void test_substr ( const std::string &str ) {
+    const size_t sz = str.size ();
+    string_ref ref ( str );
+
+//  Substrings at the end
+    for ( size_t i = 0; i <= sz; ++ i )
+        interop ( str.substr ( i ), ref.substr ( i ));
+
+//  Substrings at the beginning
+    for ( size_t i = 0; i <= sz; ++ i )
+        interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
+
+//  All possible substrings
+    for ( size_t i = 0; i < sz; ++i )
+        for ( size_t j = i; j < sz; ++j )
+            interop ( str.substr ( i, j ), ref.substr ( i, j ));
+    }
+
+//  make sure that removing prefixes and suffixes work just like strings
+void test_remove ( const std::string &str ) {
+    const size_t sz = str.size ();
+    std::string work;
+    string_ref ref;
+
+    for ( size_t i = 1; i <= sz; ++i ) {
+      work = str;
+      ref  = str;
+      while ( ref.size () >= i ) {
+          interop ( work, ref );
+          work.erase ( 0, i );
+          ref.remove_prefix (i);
+          }
+      }
+
+    for ( size_t i = 1; i < sz; ++ i ) {
+      work = str;
+      ref  = str;
+      while ( ref.size () >= i ) {
+          interop ( work, ref );
+          work.erase ( work.size () - i, i );
+          ref.remove_suffix (i);
+          }
+      }
+    }
+
+const char *test_strings [] = {
+    "",
+    "1",
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+    "0123456789",
+    NULL
+    };
+
+int main()
+{
+    const char **p = &test_strings[0];
+
+    while ( *p != NULL ) {
+        interop ( *p, *p );
+        test_substr ( *p );
+        test_remove ( *p );
+        null_tests ( *p );
+
+        p++;
+        }
+
+    return boost::report_errors();
+}
diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp
new file mode 100644
index 0000000..ccb5d6d
--- /dev/null
+++ b/test/string_ref_test2.cpp
@@ -0,0 +1,319 @@
+/*
+   Copyright (c) Marshall Clow 2012-2012.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <iostream>
+#include <cstring>    // for std::strchr
+
+#include <boost/utility/string_ref.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+typedef boost::string_ref string_ref;
+
+void ends_with ( const char *arg ) {
+    const size_t sz = std::strlen ( arg );
+    string_ref sr ( arg );
+    string_ref sr2 ( arg );
+    const char *p = arg;
+
+    while ( *p ) {
+        BOOST_TEST ( sr.ends_with ( p ));
+        ++p;
+        }
+
+    while ( !sr2.empty ()) {
+        BOOST_TEST ( sr.ends_with ( sr2 ));
+        sr2.remove_prefix (1);
+        }
+
+    sr2 = arg;
+    while ( !sr2.empty ()) {
+        BOOST_TEST ( sr.ends_with ( sr2 ));
+        sr2.remove_prefix (1);
+        }
+
+    char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
+    sr2 = arg;
+    if ( sz > 0 )
+      BOOST_TEST ( sr2.ends_with ( ch ));
+    BOOST_TEST ( !sr2.ends_with ( ++ch ));
+    BOOST_TEST ( sr2.ends_with ( string_ref ()));
+    }
+
+void starts_with ( const char *arg ) {
+    const size_t sz = std::strlen ( arg );
+    string_ref sr  ( arg );
+    string_ref sr2 ( arg );
+    const char *p = arg + std::strlen ( arg ) - 1;
+    while ( p >= arg ) {
+        std::string foo ( arg, p + 1 );
+        BOOST_TEST ( sr.starts_with ( foo ));
+        --p;
+        }
+
+    while ( !sr2.empty ()) {
+        BOOST_TEST ( sr.starts_with ( sr2 ));
+        sr2.remove_suffix (1);
+        }
+
+    char ch = *arg;
+    sr2 = arg;
+  if ( sz > 0 )
+    BOOST_TEST ( sr2.starts_with ( ch ));
+    BOOST_TEST ( !sr2.starts_with ( ++ch ));
+    BOOST_TEST ( sr2.starts_with ( string_ref ()));
+    }
+
+void reverse ( const char *arg ) {
+//  Round trip
+    string_ref sr1 ( arg );
+    std::string string1 ( sr1.rbegin (), sr1.rend ());
+    string_ref sr2 ( string1 );
+    std::string string2 ( sr2.rbegin (), sr2.rend ());
+
+    BOOST_TEST ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
+    BOOST_TEST ( string2 == arg );
+    BOOST_TEST ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
+    }
+
+// This helper function eliminates signed vs. unsigned warnings
+string_ref::size_type ptr_diff ( const char *res, const char *base ) {
+    BOOST_TEST ( res >= base );
+    return static_cast<string_ref::size_type> ( res - base );
+    }
+
+void find ( const char *arg ) {
+    string_ref sr1;
+    string_ref sr2;
+    const char *p;
+
+//  Look for each character in the string(searching from the start)
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+      string_ref::size_type pos = sr1.find(*p);
+      BOOST_TEST ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
+      ++p;
+      }
+
+//  Look for each character in the string (searching from the end)
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+      string_ref::size_type pos = sr1.rfind(*p);
+      BOOST_TEST ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
+      ++p;
+      }
+
+// Look for pairs on characters (searching from the start)
+    sr1 = arg;
+    p = arg;
+    while ( *p && *(p+1)) {
+        string_ref sr3 ( p, 2 );
+        string_ref::size_type pos = sr1.find ( sr3 );
+        BOOST_TEST ( pos != string_ref::npos && pos <= static_cast<string_ref::size_type>( p - arg ));
+        p++;
+        }
+
+    sr1 = arg;
+    p = arg;
+//  for all possible chars, see if we find them in the right place.
+//  Note that strchr will/might do the _wrong_ thing if we search for NULL
+    for ( int ch = 1; ch < 256; ++ch ) {
+        string_ref::size_type pos = sr1.find(ch);
+        const char *strp = std::strchr ( arg, ch );
+        BOOST_TEST (( strp == NULL ) == ( pos == string_ref::npos ));
+        if ( strp != NULL )
+            BOOST_TEST ( ptr_diff ( strp, arg ) == pos );
+    }
+
+    sr1 = arg;
+    p = arg;
+//  for all possible chars, see if we find them in the right place.
+//  Note that strchr will/might do the _wrong_ thing if we search for NULL
+    for ( int ch = 1; ch < 256; ++ch ) {
+        string_ref::size_type pos = sr1.rfind(ch);
+        const char *strp = std::strrchr ( arg, ch );
+        BOOST_TEST (( strp == NULL ) == ( pos == string_ref::npos ));
+        if ( strp != NULL )
+            BOOST_TEST ( ptr_diff ( strp, arg ) == pos );
+    }
+
+
+//  Find everything at the start
+    p = arg;
+    sr1 = arg;
+    while ( !sr1.empty ()) {
+        string_ref::size_type pos = sr1.find(*p);
+        BOOST_TEST ( pos == 0 );
+        sr1.remove_prefix (1);
+        ++p;
+        }
+
+//  Find everything at the end
+    sr1  = arg;
+    p    = arg + std::strlen ( arg ) - 1;
+    while ( !sr1.empty ()) {
+        string_ref::size_type pos = sr1.rfind(*p);
+        BOOST_TEST ( pos == sr1.size () - 1 );
+        sr1.remove_suffix (1);
+        --p;
+        }
+
+//  Find everything at the start
+    sr1  = arg;
+    p    = arg;
+    while ( !sr1.empty ()) {
+        string_ref::size_type pos = sr1.find_first_of(*p);
+        BOOST_TEST ( pos == 0 );
+        sr1.remove_prefix (1);
+        ++p;
+        }
+
+
+//  Find everything at the end
+    sr1  = arg;
+    p    = arg + std::strlen ( arg ) - 1;
+    while ( !sr1.empty ()) {
+        string_ref::size_type pos = sr1.find_last_of(*p);
+        BOOST_TEST ( pos == sr1.size () - 1 );
+        sr1.remove_suffix (1);
+        --p;
+        }
+
+//  Basic sanity checking for "find_first_of / find_first_not_of"
+    sr1 = arg;
+    sr2 = arg;
+    while ( !sr1.empty() ) {
+        BOOST_TEST ( sr1.find_first_of ( sr2 )     == 0 );
+        BOOST_TEST ( sr1.find_first_not_of ( sr2 ) == string_ref::npos );
+        sr1.remove_prefix ( 1 );
+        }
+
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+        string_ref::size_type pos1 = sr1.find_first_of(*p);
+        string_ref::size_type pos2 = sr1.find_first_not_of(*p);
+        BOOST_TEST ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
+        if ( pos2 != string_ref::npos ) {
+            for ( size_t i = 0 ; i < pos2; ++i )
+                BOOST_TEST ( sr1[i] == *p );
+            BOOST_TEST ( sr1 [ pos2 ] != *p );
+            }
+
+        BOOST_TEST ( pos2 != pos1 );
+        ++p;
+        }
+
+//  Basic sanity checking for "find_last_of / find_last_not_of"
+    sr1 = arg;
+    sr2 = arg;
+    while ( !sr1.empty() ) {
+        BOOST_TEST ( sr1.find_last_of ( sr2 )     == ( sr1.size () - 1 ));
+        BOOST_TEST ( sr1.find_last_not_of ( sr2 ) == string_ref::npos );
+        sr1.remove_suffix ( 1 );
+        }
+
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+        string_ref::size_type pos1 = sr1.find_last_of(*p);
+        string_ref::size_type pos2 = sr1.find_last_not_of(*p);
+        BOOST_TEST ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
+        BOOST_TEST ( pos2 == string_ref::npos || pos1 < sr1.size ());
+        if ( pos2 != string_ref::npos ) {
+            for ( size_t i = sr1.size () -1 ; i > pos2; --i )
+                BOOST_TEST ( sr1[i] == *p );
+            BOOST_TEST ( sr1 [ pos2 ] != *p );
+            }
+
+        BOOST_TEST ( pos2 != pos1 );
+        ++p;
+        }
+
+    }
+
+
+void to_string ( const char *arg ) {
+    string_ref sr1;
+    std::string str1;
+    std::string str2;
+
+    str1.assign ( arg );
+    sr1 = arg;
+// str2 = sr1.to_string<std::allocator<char> > ();
+    str2 = sr1.to_string ();
+    BOOST_TEST ( str1 == str2 );
+
+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+    std::string str3 = static_cast<std::string> ( sr1 );
+    BOOST_TEST ( str1 == str3 );
+#endif
+    }
+
+void compare ( const char *arg ) {
+    string_ref sr1;
+    std::string str1;
+    std::string str2 = str1;
+
+    str1.assign ( arg );
+    sr1 = arg;
+    BOOST_TEST ( sr1  == sr1);     // compare string_ref and string_ref
+    BOOST_TEST ( sr1  == str1);    // compare string and string_ref
+    BOOST_TEST ( str1 == sr1 );    // compare string_ref and string
+    BOOST_TEST ( sr1  == arg );    // compare string_ref and pointer
+    BOOST_TEST ( arg  == sr1 );    // compare pointer and string_ref
+
+    if ( sr1.size () > 0 ) {
+        (*str1.rbegin())++;
+        BOOST_TEST ( sr1  != str1 );
+        BOOST_TEST ( str1 != sr1 );
+        BOOST_TEST ( sr1 < str1 );
+        BOOST_TEST ( sr1 <= str1 );
+        BOOST_TEST ( str1 > sr1 );
+        BOOST_TEST ( str1 >= sr1 );
+
+        (*str1.rbegin()) -= 2;
+        BOOST_TEST ( sr1  != str1 );
+        BOOST_TEST ( str1 != sr1 );
+        BOOST_TEST ( sr1 > str1 );
+        BOOST_TEST ( sr1 >= str1 );
+        BOOST_TEST ( str1 < sr1 );
+        BOOST_TEST ( str1 <= sr1 );
+        }
+    }
+
+const char *test_strings [] = {
+    "",
+    "0",
+    "abc",
+    "AAA",  // all the same
+    "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
+    "abc\0asdfadsfasf",
+    NULL
+    };
+
+int main()
+{
+    const char **p = &test_strings[0];
+
+    while ( *p != NULL ) {
+        starts_with ( *p );
+        ends_with ( *p );
+        reverse ( *p );
+        find ( *p );
+        to_string ( *p );
+        compare ( *p );
+
+        p++;
+        }
+
+    return boost::report_errors();
+}
diff --git a/test/string_ref_test_io.cpp b/test/string_ref_test_io.cpp
new file mode 100644
index 0000000..3609f91
--- /dev/null
+++ b/test/string_ref_test_io.cpp
@@ -0,0 +1,184 @@
+/*
+ *             Copyright Andrey Semashev 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file   string_ref_test_io.cpp
+ * \author Andrey Semashev
+ * \date   26.05.2013
+ *
+ * \brief  This header contains tests for stream operations of \c basic_string_ref.
+ */
+
+#include <boost/utility/string_ref.hpp>
+
+#include <iomanip>
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available.
+*/
+
+static const char* test_strings[] =
+{
+    "begin",
+    "abcd",
+    "end"
+};
+
+//! The context with test data for particular character type
+template< typename CharT >
+struct context
+{
+    typedef CharT char_type;
+    typedef std::basic_string< char_type > string_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+
+    string_type begin, abcd, end;
+
+    context()
+    {
+        boost::string_ref str = test_strings[0];
+        std::copy(str.begin(), str.end(), std::back_inserter(begin));
+
+        str = test_strings[1];
+        std::copy(str.begin(), str.end(), std::back_inserter(abcd));
+
+        str = test_strings[2];
+        std::copy(str.begin(), str.end(), std::back_inserter(end));
+    }
+};
+
+// Test regular output
+template<class CharT>
+void test_string_ref_output()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_ref< char_type > string_ref_type;
+
+    context< char_type > ctx;
+
+    ostream_type strm;
+    strm << string_ref_type(ctx.abcd);
+    BOOST_TEST(strm.str() == ctx.abcd);
+}
+
+// Test support for padding
+template<class CharT>
+void test_padding()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_ref< char_type > string_ref_type;
+
+    context< char_type > ctx;
+
+    // Test for padding
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+
+    // Test for long padding
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+
+    // Test that short width does not truncate the string
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+}
+
+// Test support for padding fill
+template<class CharT>
+void test_padding_fill()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_ref< char_type > string_ref_type;
+
+    context< char_type > ctx;
+
+    ostream_type strm_ref;
+    strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
+
+    ostream_type strm_correct;
+    strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
+
+    BOOST_TEST(strm_ref.str() == strm_correct.str());
+}
+
+// Test support for alignment
+template<class CharT>
+void test_alignment()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_ref< char_type > string_ref_type;
+
+    context< char_type > ctx;
+
+    // Left alignment
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+
+    // Right alignment
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+}
+
+template<class CharT>
+void test()
+{
+    test_string_ref_output<CharT>();
+    test_padding<CharT>();
+    test_padding_fill<CharT>();
+    test_alignment<CharT>();
+}
+
+int main()
+{
+    test<char>();
+    test<wchar_t>();
+    return boost::report_errors();
+}
diff --git a/test/string_view_constexpr_test1.cpp b/test/string_view_constexpr_test1.cpp
new file mode 100644
index 0000000..615d600
--- /dev/null
+++ b/test/string_view_constexpr_test1.cpp
@@ -0,0 +1,114 @@
+/*
+   Copyright (c) Marshall Clow 2017-2017.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <new>        // for placement new
+#include <iostream>
+#include <cstddef>    // for NULL, std::size_t, std::ptrdiff_t
+#include <cstring>    // for std::strchr and std::strcmp
+#include <cstdlib>    // for std::malloc and std::free
+
+#include <boost/config.hpp>
+#include <boost/utility/string_view.hpp>
+
+#if __cplusplus >= 201402L
+struct constexpr_char_traits
+{
+    typedef char		    char_type;
+    typedef int   			int_type;
+    typedef std::streamoff	off_type;
+    typedef std::streampos	pos_type;
+    typedef std::mbstate_t	state_type;
+
+    static void assign(char_type& c1, const char_type& c2) noexcept { c1 = c2; }
+    static constexpr bool eq(char_type c1, char_type c2) noexcept   { return c1 == c2; }
+    static constexpr bool lt(char_type c1, char_type c2) noexcept   { return c1 < c2; }
+
+    static constexpr int              compare(const char_type* s1, const char_type* s2, size_t n) noexcept;
+    static constexpr size_t           length(const char_type* s) noexcept;
+    static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a) noexcept;
+    static constexpr char_type*       move(char_type* s1, const char_type* s2, size_t n) noexcept;
+    static constexpr char_type*       copy(char_type* s1, const char_type* s2, size_t n) noexcept;
+    static constexpr char_type*       assign(char_type* s, size_t n, char_type a) noexcept;
+
+    static constexpr int_type  not_eof(int_type c) noexcept { return eq_int_type(c, eof()) ? ~eof() : c; }
+    static constexpr char_type to_char_type(int_type c) noexcept              { return char_type(c); }
+    static constexpr int_type  to_int_type(char_type c) noexcept              { return int_type(c); }
+    static constexpr bool      eq_int_type(int_type c1, int_type c2) noexcept { return c1 == c2; }
+    static constexpr int_type  eof() noexcept                                 { return EOF; }
+};
+
+//	yields:
+//		0 if for each i in [0,n), X::eq(s1[i],s2[i]) is true; 
+//		else, a negative value if, for some j in [0,n), X::lt(s1[j],s2[j]) is true and
+//			for each i in [0,j) X::eq(s2[i],s2[i]) is true;
+//		else a positive value.
+constexpr int constexpr_char_traits::compare(const char_type* s1, const char_type* s2, size_t n) noexcept
+{
+    for (; n != 0; --n, ++s1, ++s2)
+    {
+        if (lt(*s1, *s2))
+            return -1;
+        if (lt(*s2, *s1))
+            return 1;
+    }
+    return 0;
+}
+
+//	yields: the smallest i such that X::eq(s[i],charT()) is true.
+constexpr size_t constexpr_char_traits::length(const char_type* s) noexcept
+{
+    size_t len = 0;
+    for (; !eq(*s, char_type(0)); ++s)
+        ++len;
+    return len;
+}
+
+typedef boost::basic_string_view<char, constexpr_char_traits> string_view;
+
+int main()
+{
+    constexpr string_view sv1;
+    constexpr string_view sv2{"abc", 3}; // ptr, len
+    constexpr string_view sv3{"def"}; 	 // ptr
+
+	constexpr const char *s1 = "";
+	constexpr const char *s2 = "abc";
+	
+	static_assert( (sv1 == sv1), "" );
+	
+	static_assert(!(sv1 == sv2), "" );    
+	static_assert( (sv1 != sv2), "" );    
+	static_assert( (sv1 <  sv2), "" );    
+	static_assert( (sv1 <= sv2), "" );    
+	static_assert(!(sv1 >  sv2), "" );    
+	static_assert(!(sv1 >= sv2), "" );    
+
+	static_assert(!(s1 == sv2), "" );    
+	static_assert( (s1 != sv2), "" );    
+	static_assert( (s1 <  sv2), "" );    
+	static_assert( (s1 <= sv2), "" );    
+	static_assert(!(s1 >  sv2), "" );    
+	static_assert(!(s1 >= sv2), "" );    
+
+	static_assert(!(sv1 == s2), "" );    
+	static_assert( (sv1 != s2), "" );    
+	static_assert( (sv1 <  s2), "" );    
+	static_assert( (sv1 <= s2), "" );    
+	static_assert(!(sv1 >  s2), "" );    
+	static_assert(!(sv1 >= s2), "" );    
+
+	static_assert( sv1.compare(sv2)  < 0, "" );    
+	static_assert( sv1.compare(sv1) == 0, "" );    
+	static_assert( sv3.compare(sv1)  > 0, "" );    
+
+	static_assert( sv1.compare(s2)  < 0, "" );    
+	static_assert( sv1.compare(s1) == 0, "" );    
+	static_assert( sv3.compare(s1)  > 0, "" );    
+}
+#endif
diff --git a/test/string_view_from_rvalue.cpp b/test/string_view_from_rvalue.cpp
new file mode 100644
index 0000000..a764939
--- /dev/null
+++ b/test/string_view_from_rvalue.cpp
@@ -0,0 +1,26 @@
+/*
+   Copyright (c) Marshall Clow 2017.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+
+#include <boost/utility/string_view.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+#error "Unsupported test"
+#endif
+
+std::string makeatemp() { return "abc"; }
+
+int main()
+{
+  boost::basic_string_view<char> sv(makeatemp());
+  return 0;
+}
diff --git a/test/string_view_test1.cpp b/test/string_view_test1.cpp
new file mode 100644
index 0000000..9b70a7e
--- /dev/null
+++ b/test/string_view_test1.cpp
@@ -0,0 +1,110 @@
+/*
+   Copyright (c) Marshall Clow 2012-2012.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+
+#include <boost/utility/string_view.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+typedef boost::string_view string_view;
+
+//  Should be equal
+void interop ( const std::string &str, string_view ref ) {
+//  BOOST_TEST ( str == ref );
+    BOOST_TEST ( str.size () == ref.size ());
+    BOOST_TEST ( std::equal ( str.begin (),  str.end (),  ref.begin ()));
+    BOOST_TEST ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
+    }
+
+void null_tests ( const char *p ) {
+//  All zero-length string-refs should be equal
+    string_view sr1; // NULL, 0
+    string_view sr2 ( NULL, 0 );
+    string_view sr3 ( p, 0 );
+    string_view sr4 ( p );
+    sr4.clear ();
+
+    BOOST_TEST ( sr1 == sr2 );
+    BOOST_TEST ( sr1 == sr3 );
+    BOOST_TEST ( sr2 == sr3 );
+    BOOST_TEST ( sr1 == sr4 );
+    }
+
+//  make sure that substrings work just like strings
+void test_substr ( const std::string &str ) {
+    const size_t sz = str.size ();
+    string_view ref ( str );
+
+//  Substrings at the end
+    for ( size_t i = 0; i <= sz; ++ i )
+        interop ( str.substr ( i ), ref.substr ( i ));
+
+//  Substrings at the beginning
+    for ( size_t i = 0; i <= sz; ++ i )
+        interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
+
+//  All possible substrings
+    for ( size_t i = 0; i < sz; ++i )
+        for ( size_t j = i; j < sz; ++j )
+            interop ( str.substr ( i, j ), ref.substr ( i, j ));
+    }
+
+//  make sure that removing prefixes and suffixes work just like strings
+void test_remove ( const std::string &str ) {
+    const size_t sz = str.size ();
+    std::string work;
+    string_view ref;
+
+    for ( size_t i = 1; i <= sz; ++i ) {
+      work = str;
+      ref  = str;
+      while ( ref.size () >= i ) {
+          interop ( work, ref );
+          work.erase ( 0, i );
+          ref.remove_prefix (i);
+          }
+      }
+
+    for ( size_t i = 1; i < sz; ++ i ) {
+      work = str;
+      ref  = str;
+      while ( ref.size () >= i ) {
+          interop ( work, ref );
+          work.erase ( work.size () - i, i );
+          ref.remove_suffix (i);
+          }
+      }
+    }
+
+const char *test_strings [] = {
+    "",
+    "1",
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+    "0123456789",
+    NULL
+    };
+
+int main()
+{
+    const char **p = &test_strings[0];
+
+    while ( *p != NULL ) {
+        interop ( *p, *p );
+        test_substr ( *p );
+        test_remove ( *p );
+        null_tests ( *p );
+
+        p++;
+        }
+
+    return boost::report_errors();
+}
diff --git a/test/string_view_test2.cpp b/test/string_view_test2.cpp
new file mode 100644
index 0000000..2549e64
--- /dev/null
+++ b/test/string_view_test2.cpp
@@ -0,0 +1,406 @@
+/*
+   Copyright (c) Marshall Clow 2012-2012.
+
+   Distributed under the Boost Software License, Version 1.0. (See accompanying
+   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    For more information, see http://www.boost.org
+*/
+
+#include <new>        // for placement new
+#include <iostream>
+#include <cstddef>    // for NULL, std::size_t, std::ptrdiff_t
+#include <cstring>    // for std::strchr and std::strcmp
+#include <cstdlib>    // for std::malloc and std::free
+
+#include <boost/utility/string_view.hpp>
+#include <boost/config.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+typedef boost::string_view string_view;
+
+void ends_with ( const char *arg ) {
+    const size_t sz = std::strlen ( arg );
+    string_view sr ( arg );
+    string_view sr2 ( arg );
+    const char *p = arg;
+
+    while ( *p ) {
+        BOOST_TEST ( sr.ends_with ( p ));
+        ++p;
+        }
+
+    while ( !sr2.empty ()) {
+        BOOST_TEST ( sr.ends_with ( sr2 ));
+        sr2.remove_prefix (1);
+        }
+
+    sr2 = arg;
+    while ( !sr2.empty ()) {
+        BOOST_TEST ( sr.ends_with ( sr2 ));
+        sr2.remove_prefix (1);
+        }
+
+    char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
+    sr2 = arg;
+    if ( sz > 0 )
+      BOOST_TEST ( sr2.ends_with ( ch ));
+    BOOST_TEST ( !sr2.ends_with ( ++ch ));
+    BOOST_TEST ( sr2.ends_with ( string_view()));
+    }
+
+void starts_with ( const char *arg ) {
+    const size_t sz = std::strlen ( arg );
+    string_view sr  ( arg );
+    string_view sr2 ( arg );
+    const char *p = arg + std::strlen ( arg ) - 1;
+    while ( p >= arg ) {
+        std::string foo ( arg, p + 1 );
+        BOOST_TEST ( sr.starts_with ( foo ));
+        --p;
+        }
+
+    while ( !sr2.empty ()) {
+        BOOST_TEST ( sr.starts_with ( sr2 ));
+        sr2.remove_suffix (1);
+        }
+
+    char ch = *arg;
+    sr2 = arg;
+  if ( sz > 0 )
+    BOOST_TEST ( sr2.starts_with ( ch ));
+    BOOST_TEST ( !sr2.starts_with ( ++ch ));
+    BOOST_TEST ( sr2.starts_with ( string_view ()));
+    }
+
+void reverse ( const char *arg ) {
+//  Round trip
+    string_view sr1 ( arg );
+    std::string string1 ( sr1.rbegin (), sr1.rend ());
+    string_view sr2 ( string1 );
+    std::string string2 ( sr2.rbegin (), sr2.rend ());
+
+    BOOST_TEST ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
+    BOOST_TEST ( string2 == arg );
+    BOOST_TEST ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
+    }
+
+//  This helper function eliminates signed vs. unsigned warnings
+string_view::size_type ptr_diff ( const char *res, const char *base ) {
+    BOOST_TEST ( res >= base );
+    return static_cast<string_view::size_type> ( res - base );
+    }
+
+void find ( const char *arg ) {
+    string_view sr1;
+    string_view sr2;
+    const char *p;
+
+//  Look for each character in the string(searching from the start)
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+      string_view::size_type pos = sr1.find(*p);
+      BOOST_TEST ( pos != string_view::npos && ( pos <= ptr_diff ( p, arg )));
+      ++p;
+      }
+
+//  Look for each character in the string (searching from the end)
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+      string_view::size_type pos = sr1.rfind(*p);
+      BOOST_TEST ( pos != string_view::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
+      ++p;
+      }
+
+//  Look for pairs on characters (searching from the start)
+    sr1 = arg;
+    p = arg;
+    while ( *p && *(p+1)) {
+        string_view sr3 ( p, 2 );
+        string_view::size_type pos = sr1.find ( sr3 );
+        BOOST_TEST ( pos != string_view::npos && pos <= static_cast<string_view::size_type>( p - arg ));
+        p++;
+        }
+
+    sr1 = arg;
+    p = arg;
+//  for all possible chars, see if we find them in the right place.
+//  Note that strchr will/might do the _wrong_ thing if we search for NULL
+    for ( int ch = 1; ch < 256; ++ch ) {
+        string_view::size_type pos = sr1.find(ch);
+        const char *strp = std::strchr ( arg, ch );
+        BOOST_TEST (( strp == NULL ) == ( pos == string_view::npos ));
+        if ( strp != NULL )
+            BOOST_TEST ( ptr_diff ( strp, arg ) == pos );
+    }
+
+    sr1 = arg;
+    p = arg;
+//  for all possible chars, see if we find them in the right place.
+//  Note that strchr will/might do the _wrong_ thing if we search for NULL
+    for ( int ch = 1; ch < 256; ++ch ) {
+        string_view::size_type pos = sr1.rfind(ch);
+        const char *strp = std::strrchr ( arg, ch );
+        BOOST_TEST (( strp == NULL ) == ( pos == string_view::npos ));
+        if ( strp != NULL )
+            BOOST_TEST ( ptr_diff ( strp, arg ) == pos );
+    }
+
+
+//  Find everything at the start
+    p = arg;
+    sr1 = arg;
+    while ( !sr1.empty ()) {
+        string_view::size_type pos = sr1.find(*p);
+        BOOST_TEST ( pos == 0 );
+        sr1.remove_prefix (1);
+        ++p;
+        }
+
+//  Find everything at the end
+    sr1  = arg;
+    p    = arg + std::strlen ( arg ) - 1;
+    while ( !sr1.empty ()) {
+        string_view::size_type pos = sr1.rfind(*p);
+        BOOST_TEST ( pos == sr1.size () - 1 );
+        sr1.remove_suffix (1);
+        --p;
+        }
+
+//  Find everything at the start
+    sr1  = arg;
+    p    = arg;
+    while ( !sr1.empty ()) {
+        string_view::size_type pos = sr1.find_first_of(*p);
+        BOOST_TEST ( pos == 0 );
+        sr1.remove_prefix (1);
+        ++p;
+        }
+
+
+//  Find everything at the end
+    sr1  = arg;
+    p    = arg + std::strlen ( arg ) - 1;
+    while ( !sr1.empty ()) {
+        string_view::size_type pos = sr1.find_last_of(*p);
+        BOOST_TEST ( pos == sr1.size () - 1 );
+        sr1.remove_suffix (1);
+        --p;
+        }
+
+//  Basic sanity checking for "find_first_of / find_first_not_of"
+    sr1 = arg;
+    sr2 = arg;
+    while ( !sr1.empty() ) {
+        BOOST_TEST ( sr1.find_first_of ( sr2 )     == 0 );
+        BOOST_TEST ( sr1.find_first_not_of ( sr2 ) == string_view::npos );
+        sr1.remove_prefix ( 1 );
+        }
+
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+        string_view::size_type pos1 = sr1.find_first_of(*p);
+        string_view::size_type pos2 = sr1.find_first_not_of(*p);
+        BOOST_TEST ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
+        if ( pos2 != string_view::npos ) {
+            for ( size_t i = 0 ; i < pos2; ++i )
+                BOOST_TEST ( sr1[i] == *p );
+            BOOST_TEST ( sr1 [ pos2 ] != *p );
+            }
+
+        BOOST_TEST ( pos2 != pos1 );
+        ++p;
+        }
+
+//  Basic sanity checking for "find_last_of / find_last_not_of"
+    sr1 = arg;
+    sr2 = arg;
+    while ( !sr1.empty() ) {
+        BOOST_TEST ( sr1.find_last_of ( sr2 )     == ( sr1.size () - 1 ));
+        BOOST_TEST ( sr1.find_last_not_of ( sr2 ) == string_view::npos );
+        sr1.remove_suffix ( 1 );
+        }
+
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+        string_view::size_type pos1 = sr1.find_last_of(*p);
+        string_view::size_type pos2 = sr1.find_last_not_of(*p);
+        BOOST_TEST ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
+        BOOST_TEST ( pos2 == string_view::npos || pos1 < sr1.size ());
+        if ( pos2 != string_view::npos ) {
+            for ( size_t i = sr1.size () -1 ; i > pos2; --i )
+                BOOST_TEST ( sr1[i] == *p );
+            BOOST_TEST ( sr1 [ pos2 ] != *p );
+            }
+
+        BOOST_TEST ( pos2 != pos1 );
+        ++p;
+        }
+
+    }
+
+template <typename T>
+class custom_allocator {
+public:
+    typedef T value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef void* void_pointer;
+    typedef const void* const_void_pointer;
+    typedef std::size_t size_type;
+    typedef std::ptrdiff_t difference_type;
+    typedef T& reference;
+    typedef const T& const_reference;
+
+    template<class U>
+    struct rebind {
+        typedef custom_allocator<U> other;
+        };
+
+    custom_allocator() BOOST_NOEXCEPT {}
+    template <typename U>
+    custom_allocator(custom_allocator<U> const&) BOOST_NOEXCEPT {}
+
+    pointer allocate(size_type n) const {
+        return static_cast<pointer>(std::malloc(sizeof(value_type) * n));
+        }
+    void deallocate(pointer p, size_type) const BOOST_NOEXCEPT {
+        std::free(p);
+        }
+
+    pointer address(reference value) const BOOST_NOEXCEPT {
+        return &value;
+        }
+
+    const_pointer address(const_reference value) const BOOST_NOEXCEPT {
+        return &value;
+        }
+
+    BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT {
+        return (~(size_type)0u) / sizeof(value_type);
+        }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+    template <class U, class... Args>
+    void construct(U* ptr, Args&&... args) const {
+        ::new((void*)ptr) U(static_cast<Args&&>(args)...);
+        }
+#else
+    template <class U, class V>
+    void construct(U* ptr, V&& value) const {
+        ::new((void*)ptr) U(static_cast<V&&>(value));
+        }
+#endif
+#else
+    template <class U, class V>
+    void construct(U* ptr, const V& value) const {
+        ::new((void*)ptr) U(value);
+        }
+#endif
+
+    template <class U>
+    void construct(U* ptr) const {
+        ::new((void*)ptr) U();
+        }
+
+    template <class U>
+    void destroy(U* ptr) const {
+        (void)ptr;
+        ptr->~U();
+        }
+    };
+
+template <typename T, typename U>
+BOOST_CONSTEXPR bool operator==(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT {
+    return true;
+    }
+template <typename T, typename U>
+BOOST_CONSTEXPR bool operator!=(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT {
+    return false;
+    }
+
+void to_string ( const char *arg ) {
+    string_view sr1;
+    std::string str1;
+    std::string str2;
+
+    str1.assign ( arg );
+    sr1 = arg;
+//  str2 = sr1.to_string<std::allocator<char> > ();
+    str2 = sr1.to_string ();
+    BOOST_TEST ( str1 == str2 );
+
+    std::basic_string<char, std::char_traits<char>, custom_allocator<char> > str3 = sr1.to_string(custom_allocator<char>());
+    BOOST_TEST ( std::strcmp(str1.c_str(), str3.c_str()) == 0 );
+
+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+    std::string str4 = static_cast<std::string> ( sr1 );
+    BOOST_TEST ( str1 == str4 );
+#endif
+    }
+
+void compare ( const char *arg ) {
+    string_view sr1;
+    std::string str1;
+    std::string str2 = str1;
+
+    str1.assign ( arg );
+    sr1 = arg;
+    BOOST_TEST ( sr1  == sr1);    // compare string_view and string_view
+    BOOST_TEST ( sr1  == str1);   // compare string and string_view
+    BOOST_TEST ( str1 == sr1 );   // compare string_view and string
+    BOOST_TEST ( sr1  == arg );   // compare string_view and pointer
+    BOOST_TEST ( arg  == sr1 );   // compare pointer and string_view
+
+    if ( sr1.size () > 0 ) {
+        (*str1.rbegin())++;
+        BOOST_TEST ( sr1  != str1 );
+        BOOST_TEST ( str1 != sr1 );
+        BOOST_TEST ( sr1 < str1 );
+        BOOST_TEST ( sr1 <= str1 );
+        BOOST_TEST ( str1 > sr1 );
+        BOOST_TEST ( str1 >= sr1 );
+
+        (*str1.rbegin()) -= 2;
+        BOOST_TEST ( sr1  != str1 );
+        BOOST_TEST ( str1 != sr1 );
+        BOOST_TEST ( sr1 > str1 );
+        BOOST_TEST ( sr1 >= str1 );
+        BOOST_TEST ( str1 < sr1 );
+        BOOST_TEST ( str1 <= sr1 );
+        }
+    }
+
+const char *test_strings [] = {
+    "",
+    "0",
+    "abc",
+    "AAA",  // all the same
+    "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
+    "abc\0asdfadsfasf",
+    NULL
+    };
+
+int main()
+{
+    const char **p = &test_strings[0];
+
+    while ( *p != NULL ) {
+        starts_with ( *p );
+        ends_with ( *p );
+        reverse ( *p );
+        find ( *p );
+        to_string ( *p );
+        compare ( *p );
+
+        p++;
+        }
+
+    return boost::report_errors();
+}
diff --git a/test/string_view_test_io.cpp b/test/string_view_test_io.cpp
new file mode 100644
index 0000000..416ff33
--- /dev/null
+++ b/test/string_view_test_io.cpp
@@ -0,0 +1,184 @@
+/*
+ *             Copyright Andrey Semashev 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file   string_ref_test_io.cpp
+ * \author Andrey Semashev
+ * \date   26.05.2013
+ *
+ * \brief  This header contains tests for stream operations of \c basic_string_ref.
+ */
+
+#include <boost/utility/string_view.hpp>
+
+#include <iomanip>
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available.
+*/
+
+static const char* test_strings[] =
+{
+    "begin",
+    "abcd",
+    "end"
+};
+
+//! The context with test data for particular character type
+template< typename CharT >
+struct context
+{
+    typedef CharT char_type;
+    typedef std::basic_string< char_type > string_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+
+    string_type begin, abcd, end;
+
+    context()
+    {
+        boost::string_view str = test_strings[0];
+        std::copy(str.begin(), str.end(), std::back_inserter(begin));
+
+        str = test_strings[1];
+        std::copy(str.begin(), str.end(), std::back_inserter(abcd));
+
+        str = test_strings[2];
+        std::copy(str.begin(), str.end(), std::back_inserter(end));
+    }
+};
+
+// Test regular output
+template<class CharT>
+void test_string_view_output()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_view< char_type > string_view_type;
+
+    context< char_type > ctx;
+
+    ostream_type strm;
+    strm << string_view_type(ctx.abcd);
+    BOOST_TEST(strm.str() == ctx.abcd);
+}
+
+// Test support for padding
+template<class CharT>
+void test_padding()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_view< char_type > string_view_type;
+
+    context< char_type > ctx;
+
+    // Test for padding
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+
+    // Test for long padding
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::setw(100) << string_view_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+
+    // Test that short width does not truncate the string
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::setw(1) << string_view_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+}
+
+// Test support for padding fill
+template<class CharT>
+void test_padding_fill()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_view< char_type > string_view_type;
+
+    context< char_type > ctx;
+
+    ostream_type strm_ref;
+    strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
+
+    ostream_type strm_correct;
+    strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
+
+    BOOST_TEST(strm_ref.str() == strm_correct.str());
+}
+
+// Test support for alignment
+template<class CharT>
+void test_alignment()
+{
+    typedef CharT char_type;
+    typedef std::basic_ostringstream< char_type > ostream_type;
+    typedef boost::basic_string_view< char_type > string_view_type;
+
+    context< char_type > ctx;
+
+    // Left alignment
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::left << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+
+    // Right alignment
+    {
+        ostream_type strm_ref;
+        strm_ref << ctx.begin << std::right << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
+
+        ostream_type strm_correct;
+        strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
+
+        BOOST_TEST(strm_ref.str() == strm_correct.str());
+    }
+}
+
+template<class CharT>
+void test()
+{
+    test_string_view_output<CharT>();
+    test_padding<CharT>();
+    test_padding_fill<CharT>();
+    test_alignment<CharT>();
+}
+
+int main()
+{
+    test<char>();
+    test<wchar_t>();
+    return boost::report_errors();
+}
diff --git a/test/value_init_test.cpp b/test/value_init_test.cpp
new file mode 100644
index 0000000..ed7ec3d
--- /dev/null
+++ b/test/value_init_test.cpp
@@ -0,0 +1,371 @@
+// Copyright 2002-2008, Fernando Luis Cacciola Carballal.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for "boost/utility/value_init.hpp"
+//
+// 21 Ago 2002 (Created) Fernando Cacciola
+// 15 Jan 2008 (Added tests regarding compiler issues) Fernando Cacciola, Niels Dekker
+// 23 May 2008 (Added tests regarding initialized_value) Niels Dekker
+// 21 Ago 2008 (Added swap test) Niels Dekker
+
+#include <cstring>  // For memcmp.
+#include <iostream>
+#include <string>
+
+#include "boost/utility/value_init.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include <boost/core/lightweight_test.hpp>
+
+//
+// Sample POD type
+//
+struct POD
+{
+  POD () : f(0), c(0), i(0){}
+
+  POD ( char c_, int i_, float f_ ) : f(f_), c(c_), i(i_) {}
+
+  friend std::ostream& operator << ( std::ostream& os, POD const& pod )
+    { return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; }
+
+  friend bool operator == ( POD const& lhs, POD const& rhs )
+    { return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; }
+
+  float f;
+  char  c;
+  int   i;
+} ;
+
+//
+// Sample non POD type
+//
+struct NonPODBase
+{
+  virtual ~NonPODBase() {}
+} ;
+struct NonPOD : NonPODBase
+{
+  NonPOD () : id() {}
+  explicit NonPOD ( std::string const& id_) : id(id_) {}
+
+  friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod )
+    { return os << '(' << npod.id << ')' ; }
+
+  friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs )
+    { return lhs.id == rhs.id ; }
+
+  std::string id ;
+} ;
+
+//
+// Sample aggregate POD struct type
+// Some compilers do not correctly value-initialize such a struct, for example:
+// Borland C++ Report #51854, "Value-initialization: POD struct should be zero-initialized "
+// http://qc.codegear.com/wc/qcmain.aspx?d=51854
+//
+struct AggregatePODStruct
+{
+  float f;
+  char  c;
+  int   i;
+};
+
+bool operator == ( AggregatePODStruct const& lhs, AggregatePODStruct const& rhs )
+{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; }
+
+//
+// An aggregate struct that contains an std::string and an int.
+// Pavel Kuznetsov (MetaCommunications Engineering) used a struct like
+// this to reproduce the Microsoft Visual C++ compiler bug, reported as
+// Feedback ID 100744, "Value-initialization in new-expression"
+// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744
+//
+struct StringAndInt
+{
+  std::string s;
+  int i;
+};
+
+bool operator == ( StringAndInt const& lhs, StringAndInt const& rhs )
+{ return lhs.s == rhs.s && lhs.i == rhs.i ; }
+
+
+//
+// A struct that has an explicit (user defined) destructor.
+// Some compilers do not correctly value-initialize such a struct, for example:
+// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression"
+// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744
+//
+struct StructWithDestructor
+{
+  int i;
+  ~StructWithDestructor() {}
+};
+
+bool operator == ( StructWithDestructor const& lhs, StructWithDestructor const& rhs )
+{ return lhs.i == rhs.i ; }
+
+
+//
+// A struct that has a virtual function.
+// Some compilers do not correctly value-initialize such a struct either, for example:
+// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression"
+// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744
+//
+struct StructWithVirtualFunction
+{
+  int i;
+  virtual void VirtualFunction(); 
+};
+
+void StructWithVirtualFunction::VirtualFunction()
+{
+}
+
+bool operator == ( StructWithVirtualFunction const& lhs, StructWithVirtualFunction const& rhs )
+{ return lhs.i == rhs.i ; }
+
+
+//
+// A struct that is derived from an aggregate POD struct.
+// Some compilers do not correctly value-initialize such a struct, for example:
+// GCC Bugzilla Bug 30111,  "Value-initialization of POD base class doesn't initialize members",
+// reported by Jonathan Wakely, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111
+//
+struct DerivedFromAggregatePODStruct : AggregatePODStruct
+{
+  DerivedFromAggregatePODStruct() : AggregatePODStruct() {}
+};
+
+//
+// A struct that wraps an aggregate POD struct as data member.
+//
+struct AggregatePODStructWrapper
+{
+  AggregatePODStructWrapper() : dataMember() {}
+  AggregatePODStruct dataMember;
+};
+
+bool operator == ( AggregatePODStructWrapper const& lhs, AggregatePODStructWrapper const& rhs )
+{ return lhs.dataMember == rhs.dataMember ; }
+
+typedef unsigned char ArrayOfBytes[256];
+
+
+//
+// A struct that allows testing whether the appropriate copy functions are called.
+//
+struct CopyFunctionCallTester
+{
+  bool is_copy_constructed;
+  bool is_assignment_called;
+
+  CopyFunctionCallTester()
+  : is_copy_constructed(false), is_assignment_called(false) {}
+
+  CopyFunctionCallTester(const CopyFunctionCallTester & )
+  : is_copy_constructed(true), is_assignment_called(false) {}
+
+  CopyFunctionCallTester & operator=(const CopyFunctionCallTester & )
+  {
+    is_assignment_called = true ;
+    return *this ;
+  }
+};
+
+
+//
+// A struct that allows testing whether its customized swap function is called.
+//
+struct SwapFunctionCallTester
+{
+  bool is_custom_swap_called;
+  int data;
+
+  SwapFunctionCallTester()
+  : is_custom_swap_called(false), data(0) {}
+
+  SwapFunctionCallTester(const SwapFunctionCallTester & arg)
+  : is_custom_swap_called(false), data(arg.data) {}
+
+  void swap(SwapFunctionCallTester & arg)
+  {
+    std::swap(data, arg.data);
+    is_custom_swap_called = true;
+    arg.is_custom_swap_called = true;
+  }
+};
+
+void swap(SwapFunctionCallTester & lhs, SwapFunctionCallTester & rhs)
+{
+  lhs.swap(rhs);
+}
+
+
+
+template<class T>
+void check_initialized_value ( T const& y )
+{
+  T initializedValue = boost::initialized_value ;
+  BOOST_TEST ( y == initializedValue ) ;
+}
+
+#ifdef  __BORLANDC__
+#if __BORLANDC__ == 0x582
+void check_initialized_value( NonPOD const& )
+{
+  // The initialized_value check is skipped for Borland 5.82
+  // and this type (NonPOD), because the following statement
+  // won't compile on this particular compiler version:
+  //   NonPOD initializedValue = boost::initialized_value() ;
+  //
+  // This is caused by a compiler bug, that is fixed with a newer version
+  // of the Borland compiler.  The Release Notes for Delphi(R) 2007 for
+  // Win32(R) and C++Builder(R) 2007 (http://dn.codegear.com/article/36575)
+  // say about similar statements:
+  //   both of these statements now compile but under 5.82 got the error:
+  //   Error E2015: Ambiguity between 'V::V(const A &)' and 'V::V(const V &)'
+}
+#endif
+#endif
+
+//
+// This test function tests boost::value_initialized<T> for a specific type T.
+// The first argument (y) is assumed have the value of a value-initialized object.
+// Returns true on success.
+//
+template<class T>
+bool test ( T const& y, T const& z )
+{
+  const int errors_before_test = boost::detail::test_errors();
+
+  check_initialized_value(y);
+
+  boost::value_initialized<T> x ;
+  BOOST_TEST ( y == x ) ;
+  BOOST_TEST ( y == boost::get(x) ) ;
+
+  static_cast<T&>(x) = z ;
+  boost::get(x) = z ;
+  BOOST_TEST ( x == z ) ;
+
+  boost::value_initialized<T> const x_c ;
+  BOOST_TEST ( y == x_c ) ;
+  BOOST_TEST ( y == boost::get(x_c) ) ;
+  T& x_c_ref = const_cast<T&>( boost::get(x_c) ) ;
+  x_c_ref = z ;
+  BOOST_TEST ( x_c == z ) ;
+
+  boost::value_initialized<T> const copy1 = x;
+  BOOST_TEST ( boost::get(copy1) == boost::get(x) ) ;
+
+  boost::value_initialized<T> copy2;
+  copy2 = x;
+  BOOST_TEST ( boost::get(copy2) == boost::get(x) ) ;
+
+  {
+    boost::value_initialized<T> * ptr = new boost::value_initialized<T>;
+    BOOST_TEST ( y == *ptr ) ;
+    delete ptr;
+  }
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+  boost::value_initialized<T const> cx ;
+  BOOST_TEST ( y == cx ) ;
+  BOOST_TEST ( y == boost::get(cx) ) ;
+
+  boost::value_initialized<T const> const cx_c ;
+  BOOST_TEST ( y == cx_c ) ;
+  BOOST_TEST ( y == boost::get(cx_c) ) ;
+#endif
+
+  return boost::detail::test_errors() == errors_before_test ;
+}
+
+int main()
+{
+  BOOST_TEST ( test( 0,1234 ) ) ;
+  BOOST_TEST ( test( 0.0,12.34 ) ) ;
+  BOOST_TEST ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ;
+  BOOST_TEST ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ;
+
+  NonPOD NonPOD_object( std::string("NonPOD_object") );
+  BOOST_TEST ( test<NonPOD *>( 0, &NonPOD_object ) ) ;
+
+  AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 };
+  AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 };
+  BOOST_TEST ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) );
+
+  StringAndInt stringAndInt0;
+  StringAndInt stringAndInt1;
+  stringAndInt0.i = 0;
+  stringAndInt1.i = 1;
+  stringAndInt1.s = std::string("1");
+  BOOST_TEST ( test(stringAndInt0, stringAndInt1) );
+
+  StructWithDestructor structWithDestructor0;
+  StructWithDestructor structWithDestructor1;
+  structWithDestructor0.i = 0;
+  structWithDestructor1.i = 1;
+  BOOST_TEST ( test(structWithDestructor0, structWithDestructor1) );
+
+  StructWithVirtualFunction structWithVirtualFunction0;
+  StructWithVirtualFunction structWithVirtualFunction1;
+  structWithVirtualFunction0.i = 0;
+  structWithVirtualFunction1.i = 1;
+  BOOST_TEST ( test(structWithVirtualFunction0, structWithVirtualFunction1) );
+
+  DerivedFromAggregatePODStruct derivedFromAggregatePODStruct0;
+  DerivedFromAggregatePODStruct derivedFromAggregatePODStruct1;
+  static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct0) = zeroInitializedAggregatePODStruct;
+  static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct1) = nonZeroInitializedAggregatePODStruct;
+  BOOST_TEST ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) );
+
+  AggregatePODStructWrapper aggregatePODStructWrapper0;
+  AggregatePODStructWrapper aggregatePODStructWrapper1;
+  aggregatePODStructWrapper0.dataMember = zeroInitializedAggregatePODStruct;
+  aggregatePODStructWrapper1.dataMember = nonZeroInitializedAggregatePODStruct;
+  BOOST_TEST ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) );
+
+  ArrayOfBytes zeroInitializedArrayOfBytes = { 0 };
+  boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes;
+  BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0);
+
+  boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes2;
+  valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes;
+  BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0);
+
+  boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester1;
+  BOOST_TEST ( ! get(copyFunctionCallTester1).is_copy_constructed);
+  BOOST_TEST ( ! get(copyFunctionCallTester1).is_assignment_called);
+
+  boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester2 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1);
+  BOOST_TEST ( get(copyFunctionCallTester2).is_copy_constructed);
+  BOOST_TEST ( ! get(copyFunctionCallTester2).is_assignment_called);
+
+  boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester3;
+  copyFunctionCallTester3 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1);
+  BOOST_TEST ( ! get(copyFunctionCallTester3).is_copy_constructed);
+  BOOST_TEST ( get(copyFunctionCallTester3).is_assignment_called);
+
+  boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester1;
+  boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester2;
+  get(swapFunctionCallTester1).data = 1;
+  get(swapFunctionCallTester2).data = 2;
+  boost::swap(swapFunctionCallTester1, swapFunctionCallTester2);
+  BOOST_TEST( get(swapFunctionCallTester1).data == 2 );
+  BOOST_TEST( get(swapFunctionCallTester2).data == 1 );
+  BOOST_TEST( get(swapFunctionCallTester1).is_custom_swap_called );
+  BOOST_TEST( get(swapFunctionCallTester2).is_custom_swap_called );
+
+  return boost::report_errors();
+}
+
+
diff --git a/test/value_init_test_fail1.cpp b/test/value_init_test_fail1.cpp
new file mode 100644
index 0000000..789e6b3
--- /dev/null
+++ b/test/value_init_test_fail1.cpp
@@ -0,0 +1,27 @@
+// Copyright 2002, Fernando Luis Cacciola Carballal.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for "boost/utility/value_init.hpp"
+//
+// Initial: 21 Agu 2002
+
+#include <iostream>
+#include <string>
+
+#include "boost/utility/value_init.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+int main()
+{
+  boost::value_initialized<int> const x_c ;
+
+  get(x_c) = 1234 ; // this should produce an ERROR
+
+  return 0;
+}
diff --git a/test/value_init_test_fail2.cpp b/test/value_init_test_fail2.cpp
new file mode 100644
index 0000000..052a2bd
--- /dev/null
+++ b/test/value_init_test_fail2.cpp
@@ -0,0 +1,27 @@
+// Copyright 2002, Fernando Luis Cacciola Carballal.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for "boost/utility/value_init.hpp"
+//
+// Initial: 21 Agu 2002
+
+#include <iostream>
+#include <string>
+
+#include "boost/utility/value_init.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+int main()
+{
+  boost::value_initialized<int const> cx ;
+
+  get(cx) = 1234 ; // this should produce an ERROR
+
+  return 0;
+}
diff --git a/test/value_init_test_fail3.cpp b/test/value_init_test_fail3.cpp
new file mode 100644
index 0000000..1801f82
--- /dev/null
+++ b/test/value_init_test_fail3.cpp
@@ -0,0 +1,27 @@
+// Copyright 2002, Fernando Luis Cacciola Carballal.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for "boost/utility/value_init.hpp"
+//
+// Initial: 21 Agu 2002
+
+#include <iostream>
+#include <string>
+
+#include "boost/utility/value_init.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+int main()
+{
+  boost::value_initialized<int const> const cx_c ;
+
+  get(cx_c) = 1234 ; // this should produce an ERROR
+
+  return 0;
+}
diff --git a/test/value_init_workaround_test.cpp b/test/value_init_workaround_test.cpp
new file mode 100644
index 0000000..9ffdffc
--- /dev/null
+++ b/test/value_init_workaround_test.cpp
@@ -0,0 +1,163 @@
+// Copyright 2010, Niels Dekker.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test program for the boost::value_initialized<T> workaround.
+//
+// 17 June 2010 (Created) Niels Dekker
+
+// Switch the workaround off, before inluding "value_init.hpp".
+#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
+#include <boost/utility/value_init.hpp>
+
+#include <iostream>  // For cout.
+#include <cstdlib>  // For EXIT_SUCCESS and EXIT_FAILURE.
+
+namespace
+{
+  struct empty_struct
+  {
+  };
+
+  // A POD aggregate struct derived from an empty struct.
+  // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295,
+  // "VC++ does not value-initialize members of derived classes without 
+  // user-declared constructor", reported in 2009 by Sylvester Hesp:
+  // https://connect.microsoft.com/VisualStudio/feedback/details/484295
+  struct derived_struct: empty_struct
+  {
+    int data;
+  };
+
+  bool is_value_initialized(const derived_struct& arg)
+  {
+    return arg.data == 0;
+  }
+
+
+  class virtual_destructor_holder
+  {
+  public:
+    int i;
+    virtual ~virtual_destructor_holder()
+    {
+    }
+  };
+
+  bool is_value_initialized(const virtual_destructor_holder& arg)
+  {
+    return arg.i == 0;
+  }
+
+  // Equivalent to the Stats class from GCC Bug 33916,
+  // "Default constructor fails to initialize array members", reported in 2007 by
+  // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
+  // and fixed for GCC 4.2.4.
+  class private_int_array_pair
+  {
+    friend bool is_value_initialized(const private_int_array_pair& arg);
+  private:
+    int first[12];
+    int second[12];
+  };
+
+  bool is_value_initialized(const private_int_array_pair& arg)
+  {
+    for ( unsigned i = 0; i < 12; ++i)
+    {
+      if ( (arg.first[i] != 0) || (arg.second[i] != 0) )
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  struct int_pair_struct
+  {
+    int first;
+    int second;
+  };
+
+  typedef int int_pair_struct::*ptr_to_member_type;
+
+  struct ptr_to_member_struct
+  {
+    ptr_to_member_type data;
+  };
+
+  bool is_value_initialized(const ptr_to_member_struct& arg)
+  {
+    return arg.data == 0;
+  }
+
+  template <typename T>
+  bool is_value_initialized(const T(& arg)[2])
+  {
+    return
+      is_value_initialized(arg[0]) &&
+      is_value_initialized(arg[1]);
+  }
+
+  template <typename T>
+  bool is_value_initialized(const boost::value_initialized<T>& arg)
+  {
+    return is_value_initialized(arg.data());
+  }
+
+  // Returns zero when the specified object is value-initializated, and one otherwise.
+  // Prints a message to standard output if the value-initialization has failed.
+  template <class T>
+  unsigned failed_to_value_initialized(const T& object, const char *const object_name)
+  {
+    if ( is_value_initialized(object) )
+    {
+      return 0u;
+    }
+    else
+    {
+      std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl;
+      return 1u;
+    }
+  }
+
+// A macro that passed both the name and the value of the specified object to
+// the function above here.
+#define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value)
+
+  // Equivalent to the dirty_stack() function from GCC Bug 33916,
+  // "Default constructor fails to initialize array members", reported in 2007 by
+  // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
+  void dirty_stack()
+  {
+    unsigned char array_on_stack[4096];
+    for (unsigned i = 0; i < sizeof(array_on_stack); ++i)
+    {
+      array_on_stack[i] = 0x11;
+    }
+  }
+
+}
+
+
+int main()
+{
+  dirty_stack();
+
+  // TODO More types may be added later.
+  const unsigned num_failures =
+    FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<derived_struct>()) +
+    FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<virtual_destructor_holder[2]>()) +
+    FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>()) +
+    FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<ptr_to_member_struct>());
+
+#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
+  // One or more failures are expected.
+  return num_failures > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+#else
+  // No failures are expected.
+  return num_failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+#endif
+}