$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80914 - in sandbox/type_erasure: boost/type_erasure libs/type_erasure/test
From: steven_at_[hidden]
Date: 2012-10-09 17:39:19
Author: steven_watanabe
Date: 2012-10-09 17:39:19 EDT (Tue, 09 Oct 2012)
New Revision: 80914
URL: http://svn.boost.org/trac/boost/changeset/80914
Log:
Handle conversion sequence rank for param.
Text files modified: 
   sandbox/type_erasure/boost/type_erasure/any.hpp            |   402 ++++++++++++++++++++++++++++++++++++++++
   sandbox/type_erasure/boost/type_erasure/param.hpp          |    45 ++++                                    
   sandbox/type_erasure/libs/type_erasure/test/test_param.cpp |   129 ++++++++++++                            
   3 files changed, 570 insertions(+), 6 deletions(-)
Modified: sandbox/type_erasure/boost/type_erasure/any.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/any.hpp	(original)
+++ sandbox/type_erasure/boost/type_erasure/any.hpp	2012-10-09 17:39:19 EDT (Tue, 09 Oct 2012)
@@ -1433,6 +1433,408 @@
     table_type table;
 };
 
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+template<class Concept, class T>
+class any<Concept, T&&> :
+    public ::boost::type_erasure::detail::compute_bases<
+        ::boost::type_erasure::any<Concept, T&&>,
+        Concept,
+        T
+    >::type
+{
+    typedef ::boost::type_erasure::binding<Concept> table_type;
+public:
+    /** INTERNAL ONLY */
+    typedef Concept _boost_type_erasure_concept_type;
+    /** INTERNAL ONLY */
+    any(const ::boost::type_erasure::detail::storage& data_arg,
+        const table_type& table_arg)
+      : data(data_arg),
+        table(table_arg)
+    {}
+    /**
+     * Constructs an @ref any from a reference.
+     *
+     * \param arg The object to bind the reference to.
+     *
+     * \pre @c U is a model of @c Concept.
+     * \pre @c Concept must not refer to any placeholder besides @c T.
+     *
+     * \throws Nothing.
+     */
+    template<class U>
+    explicit any(U&& arg
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        ,  typename ::boost::disable_if<
+            ::boost::mpl::or_<
+                ::boost::is_reference<U>,
+                ::boost::is_const<U>,
+                ::boost::type_erasure::detail::is_any<U>
+            >
+        >::type* = 0
+#endif
+        )
+      : table((
+            BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U),
+            ::boost::type_erasure::make_binding<
+                ::boost::mpl::map< ::boost::mpl::pair<T, U> >
+            >()
+        ))
+    {
+        data.data = ::boost::addressof(arg);
+    }
+    /**
+     * Constructs an @ref any from a reference.
+     *
+     * \param arg The object to bind the reference to.
+     * \param binding Specifies the actual types that
+     *        all the placeholders should bind to.
+     *
+     * \pre @c U is a model of @c Concept.
+     * \pre @c Map is an MPL map with an entry for every
+     *         placeholder referred to by @c Concept.
+     *
+     * \throws Nothing.
+     */
+    template<class U, class Map>
+    any(U&& arg, const static_binding<Map>& binding_arg)
+      : table((
+            BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map),
+            binding_arg
+        ))
+    {
+        BOOST_MPL_ASSERT((::boost::is_same<
+            typename ::boost::mpl::at<Map, T>::type, U>));
+        data.data = ::boost::addressof(arg);
+    }
+    /**
+     * Constructs an @ref any from another rvalue reference.
+     *
+     * \param other The reference to copy.
+     *
+     * \throws Nothing.
+     */
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+    any(any&& other)
+      : data(other.data),
+        table(std::move(other.table))
+    {}
+#endif
+    /**
+     * Constructs an @ref any from another @ref any.
+     *
+     * \param other The object to bind the reference to.
+     *
+     * \throws Nothing.
+     */
+    any(any<Concept, T>&& other)
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(std::move(::boost::type_erasure::detail::access::table(other)))
+    {}
+    /**
+     * Constructs an @ref any from another rvalue reference.
+     *
+     * \param other The reference to copy.
+     *
+     * \pre @c Concept must not refer to any placeholder besides @c T.
+     * \pre After substituting @c T for @c Tag2, the requirements of
+     *      @c Concept2 must be a superset of of the requirements of
+     *      @c Concept.
+     *
+     * \throws std::bad_alloc
+     */
+    template<class Concept2, class Tag2>
+    any(any<Concept2, Tag2&&>&& other
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename ::boost::disable_if<
+            ::boost::mpl::or_<
+                ::boost::is_reference<Tag2>,
+                ::boost::is_same<Concept, Concept2>,
+                ::boost::is_const<Tag2>
+            >
+        >::type* = 0
+#endif
+        )
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(
+            std::move(::boost::type_erasure::detail::access::table(other)),
+            ::boost::mpl::map<
+                ::boost::mpl::pair<
+                    T,
+                    Tag2
+                >
+            >())
+    {}
+    /**
+     * Constructs an @ref any from another @ref any.
+     *
+     * \param other The object to bind the reference to.
+     *
+     * \pre @c Concept must not refer to any placeholder besides @c T.
+     * \pre After substituting @c T for @c Tag2, the requirements of
+     *      @c Concept2 must be a superset of of the requirements of
+     *      @c Concept.
+     *
+     * \throws std::bad_alloc
+     */
+    template<class Concept2, class Tag2>
+    any(any<Concept2, Tag2>&& other
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename ::boost::disable_if<
+            ::boost::mpl::or_<
+                ::boost::is_same<Concept, Concept2>,
+                ::boost::is_const<typename ::boost::remove_reference<Tag2>::type>
+            >
+        >::type* = 0
+#endif
+        )
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(
+            std::move(::boost::type_erasure::detail::access::table(other)),
+            ::boost::mpl::map<
+                ::boost::mpl::pair<
+                    T,
+                    typename ::boost::remove_reference<Tag2>::type
+                >
+            >())
+    {}
+    /**
+     * Constructs an @ref any from another reference.
+     *
+     * \param other The reference to copy.
+     * \param binding Specifies the mapping between the two concepts.
+     *
+     * \pre @c Map must be an MPL map with keys for all the placeholders
+     *      used by @c Concept and values for the corresponding
+     *      placeholders in @c Concept2.
+     * \pre After substituting placeholders according to @c Map, the
+     *      requirements of @c Concept2 must be a superset of of the
+     *      requirements of @c Concept.
+     *
+     * \throws std::bad_alloc
+     */
+    template<class Concept2, class Tag2, class Map>
+    any(any<Concept2, Tag2&&>&& other, const static_binding<Map>& binding_arg
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename ::boost::disable_if< ::boost::is_const<Tag2> >::type* = 0
+#endif
+        )
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(std::move(::boost::type_erasure::detail::access::table(other)), binding_arg)
+    {}
+    /**
+     * Constructs an @ref any from another @ref any.
+     *
+     * \param other The object to bind the reference to.
+     * \param binding Specifies the mapping between the two concepts.
+     *
+     * \pre @c Map must be an MPL map with keys for all the placeholders
+     *      used by @c Concept and values for the corresponding
+     *      placeholders in @c Concept2.
+     * \pre After substituting placeholders according to @c Map, the
+     *      requirements of @c Concept2 must be a superset of of the
+     *      requirements of @c Concept.
+     *
+     * \throws std::bad_alloc
+     */
+    template<class Concept2, class Tag2, class Map>
+    any(any<Concept2, Tag2>&& other, const static_binding<Map>& binding_arg
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename ::boost::disable_if<
+            ::boost::is_const<typename ::boost::remove_reference<Tag2>::type>
+        >::type* = 0
+#endif
+        )
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(::boost::type_erasure::detail::access::table(other), binding_arg)
+    {}
+    /**
+     * Constructs an @ref any from another rvalue reference.
+     *
+     * \param other The reference to copy.
+     * \param binding Specifies the bindings of placeholders to actual types.
+     *
+     * \pre The type stored in @c other must match the type expected by
+     *      @c binding.
+     *
+     * \post binding_of(*this) == @c binding
+     *
+     * \throws Nothing.
+     */
+    template<class Concept2, class Tag2>
+    any(const any<Concept2, Tag2&&>&& other, const binding<Concept>& binding_arg
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename ::boost::disable_if<
+            ::boost::is_const<Tag2>
+        >::type* = 0
+#endif
+        )
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(binding_arg)
+    {}
+    /**
+     * Constructs an @ref any from another @ref any.
+     *
+     * \param other The object to bind the reference to.
+     * \param binding Specifies the bindings of placeholders to actual types.
+     *
+     * \pre The type stored in @c other must match the type expected by
+     *      @c binding.
+     *
+     * \post binding_of(*this) == @c binding
+     *
+     * \throws Nothing.
+     */
+    template<class Concept2, class Tag2>
+    any(any<Concept2, Tag2>& other, const binding<Concept>& binding_arg
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename ::boost::disable_if<
+            ::boost::is_const<typename ::boost::remove_reference<Tag2>::type>
+        >::type* = 0
+#endif
+        )
+      : data(::boost::type_erasure::detail::access::data(other)),
+        table(binding_arg)
+    {}
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * If an appropriate overload of @ref assignable is not available
+     * and @ref relaxed_match is in @c Concept, falls back on
+     * constructing from @c other.
+     *
+     * \throws Whatever the assignment operator of the contained
+     *         type throws.  When falling back on construction,
+     *         throws @c std::bad_alloc.  In this case assignment
+     *         provides the strong exception guarantee.  When
+     *         calling the assignment operator of the contained type,
+     *         the exception guarantee is whatever the contained type provides.
+     */
+    any& operator=(const any& other)
+    {
+        _boost_type_erasure_resolve_assign(other);
+        return *this;
+    }
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * If an appropriate overload of @ref assignable is not available
+     * and @ref relaxed_match is in @c Concept, falls back on
+     * constructing from @c other.
+     *
+     * \throws Whatever the assignment operator of the contained
+     *         type throws.  When falling back on construction,
+     *         throws @c std::bad_alloc.  In this case assignment
+     *         provides the strong exception guarantee.  When
+     *         calling the assignment operator of the contained type,
+     *         the exception guarantee is whatever the contained type provides.
+     */
+    template<class U>
+    any& operator=(U& other)
+    {
+        _boost_type_erasure_resolve_assign(other);
+        return *this;
+    }
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * If an appropriate overload of @ref assignable is not available
+     * and @ref relaxed_match is in @c Concept, falls back on
+     * constructing from @c other.
+     *
+     * \throws Whatever the assignment operator of the contained
+     *         type throws.  When falling back on construction,
+     *         throws @c std::bad_alloc.  In this case assignment
+     *         provides the strong exception guarantee.  When
+     *         calling the assignment operator of the contained type,
+     *         the exception guarantee is whatever the contained type provides.
+     */
+    template<class U>
+    any& operator=(const U& other)
+    {
+        _boost_type_erasure_resolve_assign(other);
+        return *this;
+    }
+    
+#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
+    /** INTERNAL ONLY */
+    operator param<Concept, T&&>() const { return param<Concept, T&&>(data, table); }
+#endif
+private:
+
+    /** INTERNAL ONLY */
+    void _boost_type_erasure_swap(any& other)
+    {
+        ::std::swap(data, other.data);
+        ::std::swap(table, other.table);
+    }
+    /** INTERNAL ONLY */
+    template<class Other>
+    void _boost_type_erasure_resolve_assign(Other& other)
+    {
+        _boost_type_erasure_assign_impl(
+            other,
+            false? this->_boost_type_erasure_deduce_assign(
+                ::boost::type_erasure::detail::make_fallback(
+                    other,
+                    ::boost::mpl::bool_<
+                        sizeof(
+                            ::boost::type_erasure::detail::check_overload(
+                                ::boost::declval<any&>().
+                                    _boost_type_erasure_deduce_assign(other)
+                            )
+                        ) == sizeof(::boost::type_erasure::detail::yes)
+                    >()
+                )
+            ) : 0,
+            ::boost::type_erasure::is_relaxed<Concept>()
+        );
+    }
+    /** INTERNAL ONLY */
+    template<class Other, class U>
+    void _boost_type_erasure_assign_impl(
+        Other& other,
+        const assignable<T, U>*,
+        ::boost::mpl::false_)
+    {
+        ::boost::type_erasure::call(assignable<T, U>(), *this, other);
+    }
+    /** INTERNAL ONLY */
+    template<class Other, class U>
+    void _boost_type_erasure_assign_impl(
+        Other& other,
+        const assignable<T, U>*,
+        ::boost::mpl::true_)
+    {
+        if(::boost::type_erasure::check_match(assignable<T, U>(), *this, other)) {
+            ::boost::type_erasure::unchecked_call(assignable<T, U>(), *this, other);
+        } else {
+            any temp(other);
+            _boost_type_erasure_swap(temp);
+        }
+    }
+    /** INTERNAL ONLY */
+    template<class Other>
+    void _boost_type_erasure_assign_impl(
+        Other& other,
+        const void*,
+        ::boost::mpl::true_)
+    {
+        any temp(other);
+        _boost_type_erasure_swap(temp);
+    }
+
+    friend struct ::boost::type_erasure::detail::access;
+    ::boost::type_erasure::detail::storage data;
+    table_type table;
+};
+
+#endif
+
 }
 }
 
Modified: sandbox/type_erasure/boost/type_erasure/param.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/param.hpp	(original)
+++ sandbox/type_erasure/boost/type_erasure/param.hpp	2012-10-09 17:39:19 EDT (Tue, 09 Oct 2012)
@@ -53,10 +53,26 @@
 template<class T>
 struct placeholder_conversion<const T&, const T&> : boost::mpl::true_ {};
 
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class T>
+struct placeholder_conversion<T&&, T> : boost::mpl::true_ {};
+template<class T>
+struct placeholder_conversion<T&&, const T&> : boost::mpl::true_ {};
+template<class T>
+struct placeholder_conversion<T&&, T&&> : boost::mpl::true_ {};
+#endif
+
 }
 
+#ifdef __clang__
+#if !__has_feature(cxx_reference_qualified_functions)
+/** INTERNAL ONLY */
+#define BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
+#endif
+#else
 /** INTERNAL ONLY */
 #define BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
+#endif
 
 /**
  * \brief A proxy to help with overload resolution for functions
@@ -106,8 +122,6 @@
     /** INTERNAL ONLY */
     typedef param _boost_type_erasure_derived_type;
 
-#ifdef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
-
     template<class U>
     param(any<Concept, U>& a
 #ifndef BOOST_TYPE_ERASURE_DOXYGEN
@@ -131,7 +145,20 @@
         )
       : _impl(a)
     {}
-
+#ifndef BOOST_NO_RVALUE_REFERENCES
+    template<class U>
+    param(any<Concept, U>&& a
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+        , typename boost::enable_if<
+            ::boost::type_erasure::detail::placeholder_conversion<
+                U&&,
+                T
+            >
+        >::type* = 0
+#endif
+        )
+      : _impl(std::move(a))
+    {}
 #endif
 
     /** Returns the stored @ref any. */
@@ -145,6 +172,10 @@
 template<class Concept, class T>
 class param<Concept, const T&> {
 public:
+    param(const ::boost::type_erasure::detail::storage& data,
+          const ::boost::type_erasure::binding<Concept>& table)
+      : _impl(data, table)
+    {}
     template<class U>
     param(U& u, typename boost::enable_if< ::boost::is_same<U, const any<Concept, T> > >::type* = 0) : _impl(u) {}
     any<Concept, const T&> get() const { return _impl; }
@@ -155,6 +186,10 @@
 template<class Concept, class T>
 class param<Concept, T&> : public param<Concept, const T&> {
 public:
+    param(const ::boost::type_erasure::detail::storage& data,
+          const ::boost::type_erasure::binding<Concept>& table)
+      : param<Concept, const T&>(data, table)
+    {}
     any<Concept, T&> get() const
     {
         return any<Concept, T&>(
@@ -168,6 +203,10 @@
 template<class Concept, class T>
 class param<Concept, T&&> : public param<Concept, const T&> {
 public:
+    param(const ::boost::type_erasure::detail::storage& data,
+          const ::boost::type_erasure::binding<Concept>& table)
+      : param<Concept, const T&>(data, table)
+    {}
     any<Concept, T&&> get() const
     {
         return any<Concept, T&&>(
Modified: sandbox/type_erasure/libs/type_erasure/test/test_param.cpp
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/test/test_param.cpp	(original)
+++ sandbox/type_erasure/libs/type_erasure/test/test_param.cpp	2012-10-09 17:39:19 EDT (Tue, 09 Oct 2012)
@@ -1,6 +1,6 @@
 // Boost.TypeErasure library
 //
-// Copyright 2011 Steven Watanabe
+// Copyright 2012 Steven Watanabe
 //
 // Distributed under the Boost Software License Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
@@ -55,6 +55,21 @@
 
     BOOST_STATIC_ASSERT(sizeof(f1(i)) == 2);
     BOOST_STATIC_ASSERT(sizeof(f1(1)) == 2);
+
+    // Make sure that the constructors are actually instantiated
+    param<copy_constructible<>, _self&> c1 = a1;
+    // param<copy_constructible<>, _self&> c2 = a2;
+    param<copy_constructible<>, _self&> c3 = a3;
+    param<copy_constructible<>, _self&> c4 = a4;
+    // param<copy_constructible<>, _self&> c5 = a5;
+    // param<copy_constructible<>, _self&> c6 = a6;
+    
+    // param<copy_constructible<>, _self&> c7 = a7();
+    // param<copy_constructible<>, _self&> c8 = a8();
+    param<copy_constructible<>, _self&> c9 = a9();
+    param<copy_constructible<>, _self&> c10 = a10();
+    // param<copy_constructible<>, _self&> c11 = a11();
+    // param<copy_constructible<>, _self&> c12 = a12();
 }
 
 size<1>::type f2(param<copy_constructible<>, const _self&>);
@@ -77,6 +92,21 @@
 
     BOOST_STATIC_ASSERT(sizeof(f2(i)) == 2);
     BOOST_STATIC_ASSERT(sizeof(f2(1)) == 2);
+
+    // Make sure that the constructors are actually instantiated
+    param<copy_constructible<>, const _self&> c1 = a1;
+    param<copy_constructible<>, const _self&> c2 = a2;
+    param<copy_constructible<>, const _self&> c3 = a3;
+    param<copy_constructible<>, const _self&> c4 = a4;
+    param<copy_constructible<>, const _self&> c5 = a5;
+    param<copy_constructible<>, const _self&> c6 = a6;
+    
+    param<copy_constructible<>, const _self&> c7 = a7();
+    param<copy_constructible<>, const _self&> c8 = a8();
+    param<copy_constructible<>, const _self&> c9 = a9();
+    param<copy_constructible<>, const _self&> c10 = a10();
+    param<copy_constructible<>, const _self&> c11 = a11();
+    param<copy_constructible<>, const _self&> c12 = a12();
 }
 
 size<1>::type f3(param<copy_constructible<>, _self>);
@@ -99,9 +129,24 @@
 
     BOOST_STATIC_ASSERT(sizeof(f3(i)) == 2);
     BOOST_STATIC_ASSERT(sizeof(f3(1)) == 2);
+
+    // Make sure that the constructors are actually instantiated
+    param<copy_constructible<>, _self> c1 = a1;
+    param<copy_constructible<>, _self> c2 = a2;
+    param<copy_constructible<>, _self> c3 = a3;
+    param<copy_constructible<>, _self> c4 = a4;
+    param<copy_constructible<>, _self> c5 = a5;
+    param<copy_constructible<>, _self> c6 = a6;
+    
+    param<copy_constructible<>, _self> c7 = a7();
+    param<copy_constructible<>, _self> c8 = a8();
+    param<copy_constructible<>, _self> c9 = a9();
+    param<copy_constructible<>, _self> c10 = a10();
+    param<copy_constructible<>, _self> c11 = a11();
+    param<copy_constructible<>, _self> c12 = a12();
 }
 
-#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
+#ifndef BOOST_NO_RVALUE_REFERENCES
 
 size<1>::type f4(param<copy_constructible<>, _self&&>);
 size<2>::type f4(...);
@@ -115,7 +160,7 @@
     BOOST_STATIC_ASSERT(sizeof(f4(a6)) == 2);
     
     BOOST_STATIC_ASSERT(sizeof(f4(a7())) == 1);
-    BOOST_STATIC_ASSERT(sizeof(f4(a8())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f4(a8())) == 2);
     BOOST_STATIC_ASSERT(sizeof(f4(a9())) == 2);
     BOOST_STATIC_ASSERT(sizeof(f4(a10())) == 2);
     BOOST_STATIC_ASSERT(sizeof(f4(a11())) == 2);
@@ -123,6 +168,84 @@
 
     BOOST_STATIC_ASSERT(sizeof(f4(i)) == 2);
     BOOST_STATIC_ASSERT(sizeof(f4(1)) == 2);
+
+    // Make sure that the constructors are actually instantiated
+    // param<copy_constructible<>, _self&&> c1 = a1;
+    // param<copy_constructible<>, _self&&> c2 = a2;
+    // param<copy_constructible<>, _self&&> c3 = a3;
+    // param<copy_constructible<>, _self&&> c4 = a4;
+    // param<copy_constructible<>, _self&&> c5 = a5;
+    // param<copy_constructible<>, _self&&> c6 = a6;
+    
+    param<copy_constructible<>, _self&&> c7 = a7();
+    // param<copy_constructible<>, _self&&> c8 = a8();
+    // param<copy_constructible<>, _self&&> c9 = a9();
+    // param<copy_constructible<>, _self&&> c10 = a10();
+    // param<copy_constructible<>, _self&&> c11 = a11();
+    // param<copy_constructible<>, _self&&> c12 = a12();
+}
+
+#endif
+
+#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
+
+// Test conversion sequence rank
+
+size<1>::type f5(param<copy_constructible<>, _self&>);
+size<2>::type f5(param<copy_constructible<>, const _self&>);
+
+void test_ref_cref() {
+    BOOST_STATIC_ASSERT(sizeof(f5(a1)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f5(a2)) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f5(a3)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f5(a4)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f5(a5)) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f5(a6)) == 2);
+    
+    BOOST_STATIC_ASSERT(sizeof(f5(a7())) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f5(a8())) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f5(a9())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f5(a10())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f5(a11())) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f5(a12())) == 2);
+}
+
+size<1>::type f6(param<copy_constructible<>, _self&>);
+size<2>::type f6(param<copy_constructible<>, _self&&>);
+
+void test_ref_rref() {
+    BOOST_STATIC_ASSERT(sizeof(f6(a1)) == 1);
+    // BOOST_STATIC_ASSERT(sizeof(f6(a2)) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f6(a3)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f6(a4)) == 1);
+    // BOOST_STATIC_ASSERT(sizeof(f6(a5)) == 2);
+    // BOOST_STATIC_ASSERT(sizeof(f6(a6)) == 2);
+    
+    BOOST_STATIC_ASSERT(sizeof(f6(a7())) == 2);
+    // BOOST_STATIC_ASSERT(sizeof(f6(a8())) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f6(a9())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f6(a10())) == 1);
+    // BOOST_STATIC_ASSERT(sizeof(f6(a11())) == 2);
+    // BOOST_STATIC_ASSERT(sizeof(f6(a12())) == 2);
+}
+
+size<1>::type f7(param<copy_constructible<>, const _self&>);
+size<2>::type f7(param<copy_constructible<>, _self&&>);
+
+void test_cref_rref() {
+    BOOST_STATIC_ASSERT(sizeof(f7(a1)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a2)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a3)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a4)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a5)) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a6)) == 1);
+    
+    BOOST_STATIC_ASSERT(sizeof(f7(a7())) == 2);
+    BOOST_STATIC_ASSERT(sizeof(f7(a8())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a9())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a10())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a11())) == 1);
+    BOOST_STATIC_ASSERT(sizeof(f7(a12())) == 1);
 }
 
 #endif