]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/type_erasure/test/test_assign.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / type_erasure / test / test_assign.cpp
index 5196e3b2a9657cdb81a4ce11865b5a08668881bd..7e68a505a321d0267cf85bbced664690d9417358 100644 (file)
@@ -8,6 +8,12 @@
 //
 // $Id$
 
+#include <boost/config.hpp>
+
+#ifdef BOOST_MSVC
+#pragma warning(disable:4244) // conversion from double to int
+#endif
+
 #include <boost/type_erasure/any.hpp>
 #include <boost/type_erasure/tuple.hpp>
 #include <boost/type_erasure/builtin.hpp>
 #include <boost/type_erasure/relaxed.hpp>
 #include <boost/mpl/vector.hpp>
 
-#define BOOST_TEST_MAIN
-#include <boost/test/unit_test.hpp>
+#define BOOST_TEST_MAIN
+#include <boost/test/unit_test.hpp>
+
+using namespace boost::type_erasure;
+using boost::core::demangle;
+
+template<class T = _self>
+struct common : ::boost::mpl::vector<
+    copy_constructible<T>,
+    typeid_<T>
+> {};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T = _self>
+struct movable_common : ::boost::mpl::vector<
+    destructible<T>,
+    constructible<T(T&&)>,
+    typeid_<T>
+> {};
+
+template<class T = _self, class U = T>
+struct move_assignable : ::boost::mpl::vector<
+    assignable<T, U&&>
+> {};
+
+#endif
+
+template<class T, bool CCtor, bool MoveCtor, bool CAssign, bool MoveAssign>
+struct test_class
+{
+    explicit test_class(T n) : value(n) {}
+    test_class(const test_class& src) : value(src.value)
+    {
+        BOOST_STATIC_ASSERT_MSG(CCtor, "Copy constructor not allowed.");
+    }
+    test_class& operator=(const test_class& src)
+    {
+        BOOST_STATIC_ASSERT_MSG(CAssign, "Copy assignment not allowed.");
+        value = src.value;
+        return *this;
+    }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    test_class(test_class&& src) : value(src.value)
+    {
+        BOOST_STATIC_ASSERT_MSG(MoveCtor, "Move constructor not allowed.");
+        src.value = 0;
+    }
+    test_class& operator=(test_class&& src)
+    {
+        BOOST_STATIC_ASSERT_MSG(MoveAssign, "Move assignment not allowed.");
+        value = src.value;
+        src.value = 0;
+        return *this;
+    }
+#endif
+    bool operator==(T n) const { return value == n; }
+    T value;
+};
+
+template<class T, bool CCtor, bool MoveCtor, bool CAssign, bool MoveAssign>
+std::ostream& operator<<(std::ostream& os, const test_class<T, CCtor, MoveCtor, CAssign, MoveAssign>& t)
+{
+    return os << t.value;
+}
+
+enum copy_info {
+    id_lvalue = 1,
+    id_const_lvalue = 2,
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    id_rvalue = 3,
+    id_maybe_const_lvalue = id_lvalue, // used for the id of construction from a raw value
+#else
+    id_rvalue = id_const_lvalue,
+    id_maybe_const_lvalue = id_const_lvalue,
+#endif
+    id_construct = 4,
+    id_assign = 8,
+    id_copy = 16,
+    id_int = 32
+};
+
+#ifdef BOOST_MSVC
+#pragma warning(disable:4521) // multiple copy constructors specified
+#pragma warning(disable:4522) // multiple assignment operators specified
+#endif
+
+template<class T>
+struct copy_tracker
+{
+    copy_tracker(const copy_tracker& src) : value(src.value), info(id_const_lvalue | id_construct | id_copy), moved_from(false) {}
+    copy_tracker(copy_tracker& src) : value(src.value), info(id_lvalue | id_construct | id_copy), moved_from(false) {}
+    copy_tracker& operator=(const copy_tracker& src) { value = (src.value); info = (id_const_lvalue | id_assign | id_copy); moved_from = false; return *this; }
+    copy_tracker& operator=(copy_tracker& src) { value = (src.value); info = (id_lvalue | id_assign | id_copy); moved_from = false; return *this; }
+    copy_tracker(const T& src) : value(src), info(id_const_lvalue | id_construct | id_int), moved_from(false) {}
+    copy_tracker(T& src) : value(src), info(id_lvalue | id_construct | id_int), moved_from(false) {}
+    copy_tracker& operator=(const T& src) { value = (src); info = (id_const_lvalue | id_assign | id_int); moved_from = false; return *this; }
+    copy_tracker& operator=(T& src) { value = (src); info = (id_lvalue | id_assign | id_int); moved_from = false; return *this; }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    copy_tracker(copy_tracker&& src) : value(std::move(src.value)), info(id_rvalue | id_construct | id_copy), moved_from(false) { src.moved_from = true; }
+    copy_tracker& operator=(copy_tracker&& src) { value = std::move(src.value); info = (id_rvalue | id_assign | id_copy); moved_from = false; src.moved_from = true; return *this; }
+    copy_tracker(T&& src) : value(std::move(src)), info(id_rvalue | id_construct | id_int), moved_from(false) {}
+    copy_tracker& operator=(T&& src) { value = std::move(src); info = (id_rvalue | id_assign | id_int); moved_from = false; return *this; }
+#endif
+    template<class U>
+    explicit copy_tracker(const U& src) : value(src), info(id_const_lvalue | id_construct | id_int), moved_from(false) {}
+    T value;
+    int info;
+    bool moved_from;
+};
+
+template<class T>
+struct value_holder
+{
+    typedef copy_tracker<T> type;
+    typedef copy_tracker<T> unwrapped_type;
+    template<class U>
+    value_holder(const U& u) : value(u) {}
+    type value;
+    type get() { return value; }
+    const unwrapped_type& unwrap() { return value; }
+    template<class U>
+    const U& unwrap() { return value; }
+};
+
+template<class C, class P>
+struct value_holder<any<C, P> >
+{
+    typedef any<C, P> type;
+    typedef any<C, P> unwrapped_type;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    template<class U>
+    value_holder(U&& u) : value(std::forward<U>(u)) {}
+#else
+    template<class U>
+    value_holder(U& u) : value(u) {}
+    template<class U>
+    value_holder(const U& u) : value(u) {}
+#endif
+    type value;
+    type get() { return value; }
+    const unwrapped_type& unwrap() { return value; }
+    template<class U>
+    const U& unwrap() { return any_cast<const U&>(value); }
+};
+
+template<class T>
+struct value_holder<T&>
+{
+    typedef typename value_holder<T>::type& type;
+    typedef typename value_holder<T>::unwrapped_type unwrapped_type;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    template<class U>
+    value_holder(U&& u) : impl(std::forward<U>(u)) {}
+#else
+    template<class U>
+    value_holder(U& u) : impl(u) {}
+    template<class U>
+    value_holder(const U& u) : impl(u) {}
+#endif
+    value_holder<T> impl;
+    type get() { return impl.value; }
+    const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); }
+    template<class U>
+    const U& unwrap() { return impl.template unwrap<unwrapped_type>(); }
+};
+
+template<class T>
+struct value_holder<const T&>
+{
+    typedef const typename value_holder<T>::type& type;
+    typedef typename value_holder<T>::unwrapped_type unwrapped_type;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    template<class U>
+    value_holder(U&& u) : impl(std::forward<U>(u)) {}
+#else
+    template<class U>
+    value_holder(U& u) : impl(u) {}
+    template<class U>
+    value_holder(const U& u) : impl(u) {}
+#endif
+    value_holder<T> impl;
+    type get() { return impl.value; }
+    const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); }
+    template<class U>
+    const U& unwrap() { return impl.template unwrap<unwrapped_type>(); }
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T>
+struct value_holder<T&&>
+{
+    typedef typename value_holder<T>::type&& type;
+    typedef typename value_holder<T>::unwrapped_type unwrapped_type;
+    template<class U>
+    value_holder(U&& u) : impl(std::forward<U>(u)) {}
+    value_holder<T> impl;
+    type get() { return std::move(impl.value); }
+    const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); }
+    template<class U>
+    const U& unwrap() { return impl.template unwrap<unwrapped_type>(); }
+};
+
+#endif
+
+template<class T, class A>
+struct value_holder<T(A)>
+{
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    template<class U>
+    value_holder(U&& u) : init(std::forward<U>(u)), impl(init.get()) {}
+#else
+    template<class U>
+    value_holder(U& u) : init(u), impl(init.get()) {}
+    template<class U>
+    value_holder(const U& u) : init(u), impl(init.get()) {}
+#endif
+    value_holder<A> init;
+    value_holder<T> impl;
+    typedef typename value_holder<T>::type type;
+    typedef typename value_holder<A>::unwrapped_type unwrapped_type;
+    type get() { return impl.get(); }
+    const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); }
+    template<class U>
+    const U& unwrap() { return impl.template unwrap<unwrapped_type>(); }
+};
+
+#define TEST_ASSIGNMENT_I(LHS, RHS, result, ptr_op, R)                      \
+    try                                                                     \
+    {                                                                       \
+        value_holder<LHS> lhs(17);                                          \
+        value_holder<RHS> rhs(23);                                          \
+        const void * original = any_cast<const void*>(&lhs.get());          \
+        lhs.get() = rhs.get();                                              \
+        typedef value_holder<R>::unwrapped_type expected_type;              \
+        if(const expected_type* ptr =                                       \
+            any_cast<const expected_type*>(&lhs.get()))                     \
+        {                                                                   \
+            BOOST_TEST(ptr->value == 23);                                   \
+            BOOST_TEST(ptr->info == (result));                              \
+            BOOST_TEST(ptr ptr_op original);                                \
+        }                                                                   \
+        else                                                                \
+        {                                                                   \
+            BOOST_ERROR("Wrong type: Expected "                             \
+                << boost::core::demangle(typeid(expected_type).name())      \
+                << " but got "                                              \
+                << boost::core::demangle(typeid_of(lhs.get()).name()));     \
+        }                                                                   \
+    }                                                                       \
+    catch(bad_function_call&)                                               \
+    {                                                                       \
+        BOOST_ERROR("bad_function_call in "                                 \
+            << demangle(typeid(value_holder<LHS>::type).name())             \
+            << " = "                                                        \
+            << demangle(typeid(value_holder<RHS>::type).name()));           \
+    }
+
+#define TEST_ASSIGNMENT_id_dispatch(LHS, RHS, result)                       \
+    TEST_ASSIGNMENT_I(LHS, RHS, result, ==, LHS)
+
+#define TEST_ASSIGNMENT_id_fallback(LHS, RHS, result)                       \
+    TEST_ASSIGNMENT_I(LHS, RHS, result, !=, RHS)
+
+#define TEST_ASSIGNMENT_id_throw(LHS, RHS, result)                          \
+    {                                                                       \
+        value_holder<LHS> lhs(17);                                          \
+        value_holder<RHS> rhs(23);                                          \
+        BOOST_CHECK_THROW(lhs.get() = rhs.get(), bad_function_call);        \
+    }
+
+#define TEST_ASSIGNMENT(LHS, RHS, tag, result)                              \
+    BOOST_PP_CAT(TEST_ASSIGNMENT_, tag)(LHS, RHS, result)
+
+BOOST_AUTO_TEST_CASE(test_nothing)
+{
+    // Nothing to test.  Assignment is entirely illegal
+}
+
+BOOST_AUTO_TEST_CASE(test_nothing_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        constructible<_self(int)>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, false, false, false, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+
+    // different stored type
+
+    // raw value
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+
+    // assignment to an rvalue reference
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_assignable)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        assignable<>,
+        constructible<_self(int)>
+    > test_concept;
+    typedef test_class<int, false, false, true, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type (undefined behavior)
+
+    // raw value (compile error)
+
+    // assignment to a reference
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type (undefined behavior)
+
+    // reference with raw value (compile error)
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type (undefined behavior)
+
+    // rvalue reference with raw value (compile error)
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_assignable_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        assignable<>,
+        constructible<_self(int)>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, false, false, true, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(long), id_throw, 0);
+#endif
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_throw, 0);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to a reference
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(long), id_throw, 0);
+#endif
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_throw, );
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+#endif
+}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+BOOST_AUTO_TEST_CASE(test_move_assignable)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        move_assignable<>,
+        constructible<_self(int)>
+    > test_concept;
+    typedef test_class<int, false, false, false, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type
+
+    // raw value
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // reference with a different type
+
+    // reference with raw value
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);;
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+
+    // rvalue reference with raw value
+}
+
+BOOST_AUTO_TEST_CASE(test_move_assignable_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        move_assignable<>,
+        constructible<_self(int)>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, false, false, false, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(long), id_throw, 0);
+
+    // raw value
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+}
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        assignable<>,
+        move_assignable<>,
+        constructible<_self(int)>
+    > test_concept;
+    typedef test_class<int, false, false, true, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type (undefined behavior)
+
+    // raw value (compile error)
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type (undefined behavior)
+
+    // reference with raw value (compile error)
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type (undefined behavior)
+
+    // rvalue reference with raw value (compile error)
+}
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        assignable<>,
+        move_assignable<>,
+        constructible<_self(int)>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, false, false, true, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >();
+    any_val v1(test_binding, 1);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val&&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_throw, 0);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+}
+
+#endif // BOOST_NO_CXX11_REF_QUALIFIERS
+
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+BOOST_AUTO_TEST_CASE(test_copy_constructible_only)
+{
+    // Nothing to test.  Assignment is entirely illegal
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_constructible_only_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, true, false, false, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to an rvalue reference
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_copy)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<>
+    > test_concept;
+    typedef test_class<int, true, false, true, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type (undefined behavior)
+
+    // raw value (compile error)
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type (undefined behavior)
+
+    // reference with raw value (compile error)
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type (undefined behavior)
+
+    // rvalue reference with raw value (compile error)
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, true, false, true, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+#endif
+}
+
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+BOOST_AUTO_TEST_CASE(test_copy_constructable_move_assignable)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        move_assignable<>
+    > test_concept;
+    typedef test_class<int, true, false, false, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type const&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type
+
+    // raw value
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // reference with a different type
+
+    // reference with raw value
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);;
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+
+    // rvalue reference with raw value
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_constructable_move_assignable_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        move_assignable<>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, true, false, false, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
+}
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+
+BOOST_AUTO_TEST_CASE(test_copy_constructible_move_and_copy_assignable)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<>,
+        move_assignable<>
+    > test_concept;
+    typedef test_class<int, true, false, true, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
 
-using namespace boost::type_erasure;
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
 
-template<class T = _self>
-struct common : ::boost::mpl::vector<
-    copy_constructible<T>,
-    typeid_<T>
-> {};
+    // different stored type (undefined behavior)
+
+    // raw value (compile error)
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type (undefined behavior)
+
+    // reference with raw value (compile error)
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type (undefined behavior)
 
-BOOST_AUTO_TEST_CASE(test_basic)
+    // rvalue reference with raw value (compile error)
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_constructible_move_and_copy_assignable_relaxed)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<> > test_concept;
-    any<test_concept> x(1);
-    int* ip = any_cast<int*>(&x);
-    any<test_concept> y(2);
-    x = y;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
-    // make sure that we're actually using assignment
-    // of the underlying object, not copy and swap.
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<>,
+        move_assignable<>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, true, false, true, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment to a reference
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // reference with a different type
+    TEST_ASSIGNMENT(any_ref&(int&), any_val(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0);
+
+    // reference with raw value
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int);
+
+    typedef any<test_concept, _self&&> any_rref;
+
+    // rvalue reference as the rhs
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0);
+    TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0);
+
+    // assignment to an rvalue reference (same dispatching behavior as lvalue reference)
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // rvalue reference with a different type
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int);
+
+    // rvalue reference with raw value
+    TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int);
+    TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int);
 }
 
-BOOST_AUTO_TEST_CASE(test_basic_relaxed)
+#endif // BOOST_NO_CXX11_REF_QUALIFIERS
+
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_only)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<>, relaxed > test_concept;
-    any<test_concept> x(1);
-    int* ip = any_cast<int*>(&x);
-    any<test_concept> y(2);
-    x = y;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
-    // make sure that we're actually using assignment
-    // of the underlying object, not copy and swap.
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
+    // Nothing to test.  Assignment is entirely illegal
 }
 
-BOOST_AUTO_TEST_CASE(test_relaxed_no_copy)
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_only_relaxed)
 {
     typedef ::boost::mpl::vector<
-        destructible<>,
-        typeid_<>,
+        common<>,
+        movable_common<>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, true, true, false, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_fallback, id_rvalue | id_construct | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+}
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_copy_assignable)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        movable_common<>,
+        assignable<>
+    > test_concept;
+    typedef test_class<int, true, true, true, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type (undefined behavior)
+}
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_copy_assignable_relaxed)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        movable_common<>,
         assignable<>,
         relaxed
     > test_concept;
-    any<test_concept> x(1);
-    int* ip = any_cast<int*>(&x);
-    any<test_concept> y(2);
-    x = y;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
-    // make sure that we're actually using assignment
-    // of the underlying object, not copy and swap.
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
+    typedef test_class<int, true, true, true, false> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+}
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructable_move_assignable)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        movable_common<>,
+        move_assignable<>
+    > test_concept;
+    typedef test_class<int, true, true, false, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type const&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type
+
+    // raw value
 }
 
-BOOST_AUTO_TEST_CASE(test_relaxed_no_assign)
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructable_move_assignable_relaxed)
 {
     typedef ::boost::mpl::vector<
         common<>,
+        movable_common<>,
+        move_assignable<>,
         relaxed
     > test_concept;
-    any<test_concept> x(1);
-    any<test_concept> y(2);
-    x = y;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
+    typedef test_class<int, true, true, false, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
 }
 
-BOOST_AUTO_TEST_CASE(test_dynamic_fallback)
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_move_and_copy_assignable)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<>, relaxed> test_concept;
-    any<test_concept> x(1);
-    any<test_concept> y(2.0);
-    x = y;
-    BOOST_CHECK_EQUAL(any_cast<double>(x), 2.0);
+    typedef ::boost::mpl::vector<
+        common<>,
+        movable_common<>,
+        assignable<>,
+        move_assignable<>
+    > test_concept;
+    typedef test_class<int, true, true, true, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type (undefined behavior)
 }
 
-BOOST_AUTO_TEST_CASE(test_dynamic_fail)
+BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_move_and_copy_assignable_relaxed)
 {
-    typedef ::boost::mpl::vector<destructible<>, typeid_<>, assignable<>, relaxed> test_concept;
-    any<test_concept> x(1);
-    any<test_concept> y(2.0);
-    BOOST_CHECK_THROW(x = y, bad_function_call);
+    typedef ::boost::mpl::vector<
+        common<>,
+        movable_common<>,
+        assignable<>,
+        move_assignable<>,
+        relaxed
+    > test_concept;
+    typedef test_class<int, true, true, true, true> test_type;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+    typedef any<test_concept, const _self&> any_cref;
+    typedef any<test_concept, _self&&> any_rref;
+
+    // Compile-time check.
+    TEST_ASSIGNMENT(any_val&(int), test_type, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+
+    // assignment of same type
+    TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);
+
+    // different stored type
+    TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy);
+
+    // raw value
+    TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy);
 }
 
+#endif // BOOST_NO_RVALUE_REFERENCES || BOOST_NO_CXX11_REF_QUALIFIERS
+
 BOOST_AUTO_TEST_CASE(test_basic_int)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<_self, int> > test_concept;
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<_self, copy_tracker<int> >
+    > test_concept;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    TEST_ASSIGNMENT(any_val&(int), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    
+    TEST_ASSIGNMENT(any_ref&(int&), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    typedef any<test_concept, _self&&> any_rref;
+    TEST_ASSIGNMENT(any_rref&(int&&), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_basic_relaxed_int)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<_self, copy_tracker<int> >,
+        relaxed
+    > test_concept;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    TEST_ASSIGNMENT(any_val&(int), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    
+    TEST_ASSIGNMENT(any_ref&(int&), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    typedef any<test_concept, _self&&> any_rref;
+    TEST_ASSIGNMENT(any_rref&(int&&), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_relaxed_no_copy_int)
+{
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        assignable<_self, copy_tracker<int> >,
+        relaxed
+    > test_concept;
+
+    typedef any<test_concept> any_val;
+    typedef any<test_concept, _self&> any_ref;
+
+    TEST_ASSIGNMENT(any_val&(int), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_val&(int), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    
+    TEST_ASSIGNMENT(any_ref&(int&), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_ref&(int&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+    typedef any<test_concept, _self&&> any_rref;
+    TEST_ASSIGNMENT(any_rref&(int&&), int, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+    TEST_ASSIGNMENT(any_rref&(int&&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_relaxed_no_assign_int)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        relaxed
+    > test_concept;
     any<test_concept> x(1);
-    int* ip = any_cast<int*>(&x);
     x = 2;
     BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
+}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+struct move_only_assign_int
+{
+    explicit move_only_assign_int(int i)
+        : value(i) {}
+    move_only_assign_int(move_only_assign_int&& other)
+        : value(other.value) { other.value = 0; }
+    move_only_assign_int& operator=(move_only_assign_int&& other)
+        { value = other.value; other.value = 0; return *this; }
+    move_only_assign_int& operator=(int&& i)
+        { value = i; return *this; }
+    int value;
+private:
+    move_only_assign_int(const move_only_assign_int&);
+    move_only_assign_int& operator=(const move_only_assign_int&);
+};
+
+struct only_assign_int
+{
+    explicit only_assign_int(int i)
+        : value(i) {}
+    only_assign_int& operator=(int&& i)
+        { value = i; return *this; }
+    int value;
+private:
+    only_assign_int(only_assign_int&&);
+    only_assign_int(const only_assign_int&);
+    only_assign_int& operator=(only_assign_int&&);
+    only_assign_int& operator=(const only_assign_int&);
+};
+
+struct move_and_copy_assign_int
+{
+    explicit move_and_copy_assign_int(int i)
+        : value(i) {}
+    move_and_copy_assign_int& operator=(move_and_copy_assign_int&& other)
+        { value = other.value; other = 0; return *this; }
+    move_and_copy_assign_int& operator=(const move_and_copy_assign_int& other)
+        { value = other.value; return *this; }
+    move_and_copy_assign_int& operator=(int&& i)
+        { value = i; return *this; }
+    move_and_copy_assign_int& operator=(const int& i)
+        { value = i; return *this; }
+    int value;
+private:
+    move_and_copy_assign_int(move_and_copy_assign_int&&);
+    move_and_copy_assign_int(const move_and_copy_assign_int&);
+};
+
+struct move_and_copy_construct_assign_int
+{
+    explicit move_and_copy_construct_assign_int(int i)
+        : value(i) {}
+    move_and_copy_construct_assign_int(move_and_copy_construct_assign_int&& other)
+        : value(other.value) { other.value = 0; }
+    move_and_copy_construct_assign_int(const move_and_copy_construct_assign_int& other)
+        : value(other.value) {}
+    move_and_copy_construct_assign_int& operator=(move_and_copy_construct_assign_int&& other)
+        { value = other.value; other = 0; return *this; }
+    move_and_copy_construct_assign_int& operator=(const move_and_copy_construct_assign_int& other)
+        { value = other.value; return *this; }
+    move_and_copy_construct_assign_int& operator=(int&& i)
+        { value = i; return *this; }
+    move_and_copy_construct_assign_int& operator=(const int& i)
+        { value = i; return *this; }
+    int value;
+};
+
+struct copy_only_assign_int
+{
+    explicit copy_only_assign_int(int i)
+        : value(i) {}
+    copy_only_assign_int(const copy_only_assign_int& other)
+        : value(other.value) {}
+    copy_only_assign_int& operator=(const copy_only_assign_int& other)
+        { value = other.value; return *this; }
+    copy_only_assign_int& operator=(int&& i)
+        { value = i; return *this; }
+    copy_only_assign_int& operator=(const int& i)
+        { value = i; return *this; }
+    int value;
+private:
+    copy_only_assign_int(copy_only_assign_int&&);
+    copy_only_assign_int& operator=(copy_only_assign_int&&);
+};
+
+struct copy_only_assign_double
+{
+    explicit copy_only_assign_double(double i)
+        : value(i) {}
+    copy_only_assign_double(const copy_only_assign_double& other)
+        : value(other.value) {}
+    copy_only_assign_double& operator=(const copy_only_assign_double& other)
+        { value = other.value; return *this; }
+    copy_only_assign_double& operator=(double&& i)
+        { value = i; return *this; }
+    copy_only_assign_double& operator=(const double& i)
+        { value = i; return *this; }
+    double value;
+private:
+    copy_only_assign_double(copy_only_assign_double&&);
+    copy_only_assign_double& operator=(copy_only_assign_double&&);
+};
+
+BOOST_AUTO_TEST_CASE(test_movable_basic_int)
+{
+    typedef ::boost::mpl::vector<
+        movable_common<>,
+        move_assignable<_self, int>
+    > test_concept;
+    typedef move_only_assign_int test_type;
+    test_type source_x(1);
+
+    any<test_concept> x(std::move(source_x));
+    test_type* ip = any_cast<test_type*>(&x);
+    x = std::move(2);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2);
     // make sure that we're actually using assignment
     // of the underlying object, not copy and swap.
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
 }
 
-BOOST_AUTO_TEST_CASE(test_basic_relaxed_int)
+BOOST_AUTO_TEST_CASE(test_movable_basic_relaxed_int)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<_self, int>, relaxed > test_concept;
-    any<test_concept> x(1);
-    int* ip = any_cast<int*>(&x);
-    x = 2;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
+    typedef ::boost::mpl::vector<
+        movable_common<>,
+        move_assignable<_self, int>,
+        relaxed
+    > test_concept;
+    typedef move_only_assign_int test_type;
+    test_type source_x(1);
+
+    any<test_concept> x(std::move(source_x));
+    test_type* ip = any_cast<test_type*>(&x);
+    x = std::move(2);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2);
     // make sure that we're actually using assignment
     // of the underlying object, not copy and swap.
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
 }
 
-BOOST_AUTO_TEST_CASE(test_relaxed_no_copy_int)
+BOOST_AUTO_TEST_CASE(test_relaxed_no_constructible_int)
 {
     typedef ::boost::mpl::vector<
         destructible<>,
         typeid_<>,
-        assignable<_self, int>,
+        constructible<_self(int)>,
+        move_assignable<_self, int>,
         relaxed
     > test_concept;
-    any<test_concept> x(1);
-    int* ip = any_cast<int*>(&x);
-    x = 2;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
+    typedef only_assign_int test_type;
+
+    typedef ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > type;
+    any<test_concept> x(binding<test_concept>(make_binding<type>()), 1);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 1);
+    test_type* ip = any_cast<test_type*>(&x);
+    x = std::move(2);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2);
     // make sure that we're actually using assignment
     // of the underlying object, not copy and swap.
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
 }
 
-BOOST_AUTO_TEST_CASE(test_relaxed_no_assign_int)
+BOOST_AUTO_TEST_CASE(test_movable_relaxed_no_assign_int)
 {
     typedef ::boost::mpl::vector<
-        common<>,
+        movable_common<>,
         relaxed
     > test_concept;
-    any<test_concept> x(1);
-    x = 2;
-    BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
+    typedef move_only_assign_int test_type;
+    test_type source_x(1);
+
+    any<test_concept> x(std::move(source_x));
+    x = test_type(2);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2);
 }
 
-BOOST_AUTO_TEST_CASE(test_basic_ref)
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+
+BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable_int)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<> > test_concept;
-    int i = 1;
-    any<test_concept, _self&> x(i);
-    any<test_concept> y(2);
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        constructible<_self(int)>,
+        assignable<_self, _self>,
+        move_assignable<_self, _self>,
+        assignable<_self, int>,
+        move_assignable<_self, int>,
+        relaxed
+    > test_concept;
+    typedef move_and_copy_assign_int test_type;
+    typedef ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > type;
+
+    any<test_concept> x(binding<test_concept>(make_binding<type>()), 1);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 1);
+
+    any<test_concept> y(binding<test_concept>(make_binding<type>()), 2);
     x = y;
-    BOOST_CHECK_EQUAL(i, 2);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2);
+
+    any<test_concept> z(binding<test_concept>(make_binding<type>()), 3);
+    x = std::move(z);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 3);
+
+    x = 4;
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 4);
+
+    x = std::move(5);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 5);
 }
 
-BOOST_AUTO_TEST_CASE(test_basic_relaxed_ref)
+BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable_copy_construct_int)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<>, relaxed > test_concept;
-    int i = 1;
-    any<test_concept, _self&> x(i);
-    any<test_concept> y(2);
+    typedef ::boost::mpl::vector<
+        common<>,
+        assignable<_self, _self>,
+        move_assignable<_self, _self>,
+        assignable<_self, int>,
+        move_assignable<_self, int>,
+        relaxed
+    > test_concept;
+    typedef move_and_copy_construct_assign_int test_type;
+    test_type source_x(1);
+    test_type source_y(2);
+    test_type source_z(3);
+
+    any<test_concept> x(source_x);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 1);
+    test_type* ip = any_cast<test_type*>(&x);
+
+    any<test_concept> y(source_y);
     x = y;
-    BOOST_CHECK_EQUAL(i, 2);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2);
+    // make sure that we're actually using assignment
+    // of the underlying object, not copy and swap.
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
+
+    any<test_concept> z(source_z);
+    x = std::move(z);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 3);
+    // make sure that we're actually using move-assignment
+    // of the underlying object, not copy and swap.
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
+
+    x = 4;
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 4);
+    // make sure that we're actually using assignment
+    // of the underlying object, not copy and swap.
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
+
+    x = std::move(5);
+    BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 5);
+    // make sure that we're actually using move-assignment
+    // of the underlying object, not copy and swap.
+    BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip);
 }
 
-BOOST_AUTO_TEST_CASE(test_relaxed_no_assign_ref)
+#endif // BOOST_NO_CXX11_REF_QUALIFIERS
+
+BOOST_AUTO_TEST_CASE(test_assignable_with_conversion)
 {
     typedef ::boost::mpl::vector<
-        common<>,
+        destructible<>,
+        typeid_<>,
+        assignable<_self, int>,
         relaxed
     > test_concept;
-    int i = 1;
-    any<test_concept, _self&> x(i);
-    any<test_concept> y(2);
-    x = y;
-    BOOST_CHECK_EQUAL(i, 1);
-    BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y));
+    typedef move_and_copy_construct_assign_int test_type1;
+    typedef copy_only_assign_int               test_type2;
+    typedef copy_only_assign_double            test_type3;
+
+    test_type1 source_x(1);
+    any<test_concept> x(source_x);
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 1);
+
+    // assigning raw values is supported because "relaxed" is in concept.
+    test_type2 source_y(2);
+    x = source_y;
+    BOOST_CHECK_EQUAL(any_cast<const test_type2&>(x).value, 2);
+
+    // move-assigning raw values is supported because "relaxed" is in concept.
+    x = test_type1(3);
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 3);
+
+    // assigning int is supported because appropriate "assignable" is in concept.
+    int int4 = 4;
+    x = int4;
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 4);
+    int int5 = 5;
+    x = std::move(int5);
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 5);
+
+    // assigning double (which is implicitly convertible to int) is supported
+    // because appropriate "assignable" is in concept.
+    double double6 = 6.5;
+    x = double6;  // truncates value
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 6);
+    double double7 = 7.5;
+    x = std::move(double7);  // truncates value
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 7);
+
+    // assigning raw values is supported because "relaxed" is in concept.
+    test_type3 source_z(8.5);
+    x = source_z;
+    BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 8.5);
+
+    // assigning double (which is implicitly convertible to int) is supported
+    // because appropriate "assignable" is in concept.
+    double double9 = 9.5;
+    x = double9;  // truncates value
+    BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 9.0);
+    double double10 = 10.5;
+    x = std::move(double10);  // truncates value
+    BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 10.0);
 }
 
-BOOST_AUTO_TEST_CASE(test_dynamic_fallback_ref)
+BOOST_AUTO_TEST_CASE(test_move_assignable_with_conversion)
 {
-    typedef ::boost::mpl::vector<common<>, assignable<>, relaxed> test_concept;
-    int i = 1;
-    any<test_concept, _self&> x(i);
-    any<test_concept> y(2.0);
-    x = y;
-    BOOST_CHECK_EQUAL(any_cast<double>(x), 2.0);
+    typedef ::boost::mpl::vector<
+        destructible<>,
+        typeid_<>,
+        move_assignable<_self, int>,
+        relaxed
+    > test_concept;
+    typedef move_and_copy_construct_assign_int test_type1;
+    typedef copy_only_assign_int               test_type2;
+    typedef copy_only_assign_double            test_type3;
+
+    test_type1 source_x(1);
+    any<test_concept> x(source_x);
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 1);
+
+    // assigning raw values is supported because "relaxed" is in concept.
+    test_type2 source_y(2);
+    x = source_y;
+    BOOST_CHECK_EQUAL(any_cast<const test_type2&>(x).value, 2);
+
+    // move-assigning raw values is supported because "relaxed" is in concept.
+    x = test_type1(3);
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 3);
+
+    // move-assigning int is supported because appropriate "move_assignable" is in concept.
+    int int4 = 4;
+    x = std::move(int4);
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 4);
+    // copy-assigning int is assigning a raw_value.
+    int int5 = 5;
+    x = int5;
+    BOOST_CHECK_EQUAL(any_cast<const int&>(x), 5);
+    x = source_x;  // reset.
+
+    // move-assigning double (which is implicitly convertible to int) is supported
+    // because appropriate "move_assignable" is in concept.
+    double double6 = 6.5;
+    x = std::move(double6);  // truncates value
+    BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 6);
+
+    // assigning raw values is supported because "relaxed" is in concept.
+    test_type3 source_z(8.5);
+    x = source_z;
+    BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 8.5);
+
+    // move-assigning double (which is implicitly convertible to int) is supported
+    // because appropriate "move_assignable" is in concept.
+    double double9 = 9.5;
+    x = std::move(double9);  // truncates value
+    BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 9.0);
 }
+
+#endif