Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80910 - in sandbox/type_erasure: boost/type_erasure boost/type_erasure/detail libs/type_erasure/example
From: steven_at_[hidden]
Date: 2012-10-08 19:37:01


Author: steven_watanabe
Date: 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
New Revision: 80910
URL: http://svn.boost.org/trac/boost/changeset/80910

Log:
Allow mutating functions to be called on const any<C, P&>.
Added:
   sandbox/type_erasure/boost/type_erasure/detail/const.hpp (contents, props changed)
Text files modified:
   sandbox/type_erasure/boost/type_erasure/call.hpp | 14 +++++++++
   sandbox/type_erasure/boost/type_erasure/detail/access.hpp | 12 +++++++
   sandbox/type_erasure/boost/type_erasure/free.hpp | 3 +
   sandbox/type_erasure/boost/type_erasure/member.hpp | 38 +++++++++++++++++++-----
   sandbox/type_erasure/boost/type_erasure/operators.hpp | 62 +++++++++++++++++++++++++++++++++------
   sandbox/type_erasure/libs/type_erasure/example/references.cpp | 19 ------------
   6 files changed, 110 insertions(+), 38 deletions(-)

Modified: sandbox/type_erasure/boost/type_erasure/call.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/call.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/call.hpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -92,6 +92,20 @@
 
 template<class Concept, class T>
 ::boost::type_erasure::detail::storage&
+convert_arg(const any_base<any<Concept, T&> >& arg, boost::mpl::true_)
+{
+ return ::boost::type_erasure::detail::access::data(arg);
+}
+
+template<class Concept, class T>
+const ::boost::type_erasure::detail::storage&
+convert_arg(const any_base<any<Concept, const T&> >& arg, boost::mpl::true_)
+{
+ return ::boost::type_erasure::detail::access::data(arg);
+}
+
+template<class Concept, class T>
+::boost::type_erasure::detail::storage&
 convert_arg(param<Concept, T>& arg, boost::mpl::true_)
 {
     return ::boost::type_erasure::detail::access::data(arg);

Modified: sandbox/type_erasure/boost/type_erasure/detail/access.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/detail/access.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/detail/access.hpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -59,6 +59,18 @@
     }
     template<class Concept, class T>
     static ::boost::type_erasure::detail::storage&
+ data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >& arg)
+ {
+ return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any<Concept, T&>&>(arg).data);
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, const T&> >& arg)
+ {
+ return static_cast<const ::boost::type_erasure::any<Concept, const T&>&>(arg).data;
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
     data(::boost::type_erasure::param<Concept, T>& arg)
     {
         return arg._impl.data;

Added: sandbox/type_erasure/boost/type_erasure/detail/const.hpp
==============================================================================
--- (empty file)
+++ sandbox/type_erasure/boost/type_erasure/detail/const.hpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -0,0 +1,97 @@
+// Boost.TypeErasure library
+//
+// Copyright 2012 Steven Watanabe
+//
+// Distributed under the Boost Software License Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// $Id$
+
+#ifndef BOOST_TYPE_ERASURE_DETAIL_CONST_HPP_INCLUDED
+#define BOOST_TYPE_ERASURE_DETAIL_CONST_HPP_INCLUDED
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_erasure/placeholder_of.hpp>
+#include <boost/type_erasure/derived.hpp>
+
+namespace boost {
+namespace type_erasure {
+namespace detail {
+
+template<class T>
+struct is_non_const_ref : boost::mpl::false_ {};
+template<class T>
+struct is_non_const_ref<T&> : boost::mpl::true_ {};
+template<class T>
+struct is_non_const_ref<const T&> : boost::mpl::false_ {};
+
+template<class Placeholder, class Base>
+struct should_be_const :
+ ::boost::mpl::or_<
+ ::boost::is_const<Placeholder>,
+ ::boost::type_erasure::detail::is_non_const_ref<
+ typename ::boost::type_erasure::placeholder_of<Base>::type
+ >
+ >
+{};
+
+template<class Placeholder, class Base>
+struct should_be_non_const :
+ ::boost::mpl::and_<
+ ::boost::mpl::not_< ::boost::is_const<Placeholder> >,
+ ::boost::mpl::not_<
+ ::boost::is_reference<
+ typename ::boost::type_erasure::placeholder_of<Base>::type
+ >
+ >
+ >
+{};
+
+template<class Base>
+struct non_const_this_param
+{
+ typedef typename ::boost::type_erasure::placeholder_of<Base>::type placeholder;
+ typedef typename ::boost::type_erasure::derived<Base>::type plain_type;
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_same<
+ placeholder,
+ typename ::boost::remove_cv<
+ typename ::boost::remove_reference<placeholder>::type
+ >::type&
+ >,
+ const plain_type,
+ plain_type
+ >::type type;
+};
+
+template<class T>
+struct uncallable {};
+
+template<class Placeholder, class Base>
+struct maybe_const_this_param
+{
+ typedef typename ::boost::type_erasure::derived<Base>::type plain_type;
+ typedef typename ::boost::mpl::if_<
+ ::boost::type_erasure::detail::should_be_non_const<Placeholder, Base>,
+ plain_type&,
+ typename ::boost::mpl::if_<
+ ::boost::type_erasure::detail::should_be_const<Placeholder, Base>,
+ const plain_type&,
+ uncallable<plain_type>
+ >::type
+ >::type type;
+};
+
+}
+}
+}
+
+#endif

Modified: sandbox/type_erasure/boost/type_erasure/free.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/free.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/free.hpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -24,6 +24,7 @@
 #include <boost/mpl/int.hpp>
 #include <boost/mpl/next.hpp>
 #include <boost/type_erasure/detail/macro.hpp>
+#include <boost/type_erasure/detail/const.hpp>
 #include <boost/type_erasure/config.hpp>
 #include <boost/type_erasure/derived.hpp>
 #include <boost/type_erasure/rebind_any.hpp>
@@ -70,7 +71,7 @@
 /** INTERNAL ONLY */
 #define BOOST_TYPE_ERASURE_FREE_PARAM_TYPE(z, n, data) \
     typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
- ::boost::type_erasure::derived<Base>, \
+ ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
         ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
>::type BOOST_PP_CAT(t, n)
 

Modified: sandbox/type_erasure/boost/type_erasure/member.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/member.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/member.hpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -21,6 +21,7 @@
 #include <boost/preprocessor/seq/size.hpp>
 #include <boost/preprocessor/seq/elem.hpp>
 #include <boost/type_erasure/detail/macro.hpp>
+#include <boost/type_erasure/detail/const.hpp>
 #include <boost/type_erasure/rebind_any.hpp>
 #include <boost/type_erasure/placeholder.hpp>
 #include <boost/type_erasure/call.hpp>
@@ -61,7 +62,13 @@
         class T, class Base, class Enable> \
     struct concept_interface< \
         BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
- Base, T, Enable> : Base \
+ Base, \
+ typename ::boost::enable_if< \
+ ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
+ typename ::boost::remove_const<T>::type \
+ >::type, \
+ Enable \
+ > : Base \
     { \
         typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
         typename rebind_any<Base, R>::type member( \
@@ -76,22 +83,33 @@
         class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class A), \
         class T, class Base, class Enable> \
     struct concept_interface< \
- BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID_C(qual_name, N), \
- Base, T, Enable> : Base \
+ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
+ Base, \
+ typename ::boost::enable_if< \
+ ::boost::type_erasure::detail::should_be_const<T, Base>, \
+ typename ::boost::remove_const<T>::type \
+ >::type, \
+ Enable \
+ > : Base \
     { \
         typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
         typename rebind_any<Base, R>::type member( \
             BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~)) const \
         { \
             return ::boost::type_erasure::call( \
- BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID_C(qual_name, N)(), \
+ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
                 *this BOOST_PP_ENUM_TRAILING_PARAMS(N, a)); \
         } \
     }; \
     template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class A), class T, class Base> \
     struct concept_interface< \
         BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
- Base, T, typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
+ Base, \
+ typename ::boost::enable_if< \
+ ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
+ typename ::boost::remove_const<T>::type \
+ >::type, \
+ typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
     { \
         using Base::member; \
         typename rebind_any<Base, R>::type member( \
@@ -104,8 +122,12 @@
     }; \
     template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class A), class T, class Base> \
     struct concept_interface< \
- BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID_C(qual_name, N), \
- Base, T, \
+ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
+ Base, \
+ typename ::boost::enable_if< \
+ ::boost::type_erasure::detail::should_be_const<T, Base>, \
+ typename ::boost::remove_const<T>::type \
+ >::type, \
         typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
     { \
         using Base::member; \
@@ -113,7 +135,7 @@
             BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~)) const \
         { \
             return ::boost::type_erasure::call( \
- BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID_C(qual_name, N)(), \
+ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
                 *this BOOST_PP_ENUM_TRAILING_PARAMS(N, a)); \
         } \
     }; \

Modified: sandbox/type_erasure/boost/type_erasure/operators.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/operators.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/operators.hpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -13,6 +13,7 @@
 
 #include <iosfwd>
 #include <boost/utility/enable_if.hpp>
+#include <boost/type_erasure/detail/const.hpp>
 #include <boost/type_erasure/call.hpp>
 #include <boost/type_erasure/concept_interface.hpp>
 #include <boost/type_erasure/placeholder.hpp>
@@ -40,7 +41,11 @@
     }; \
                                                                                     \
     template<class T, class Base> \
- struct concept_interface<name<T>, Base, T> : Base \
+ struct concept_interface<name<T>, Base, T, \
+ typename ::boost::enable_if< \
+ detail::should_be_non_const<T, Base> \
+ >::type \
+ > : Base \
     { \
         typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
         _derived& operator op() \
@@ -55,6 +60,28 @@
             ::boost::type_erasure::call(name<T>(), *this); \
             return result; \
         } \
+ }; \
+ \
+ template<class T, class Base> \
+ struct concept_interface<name<T>, Base, T, \
+ typename ::boost::enable_if< \
+ detail::should_be_const<T, Base> \
+ >::type \
+ > : Base \
+ { \
+ typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
+ const _derived& operator op() const \
+ { \
+ ::boost::type_erasure::call(name<T>(), *this); \
+ return static_cast<const _derived&>(*this); \
+ } \
+ typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) const \
+ { \
+ typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
+ static_cast<const _derived&>(*this)); \
+ ::boost::type_erasure::call(name<T>(), *this); \
+ return result; \
+ } \
     };
 
 /**
@@ -179,10 +206,17 @@
     }; \
                                                                             \
     template<class T, class U, class Base> \
- struct concept_interface<name<T, U>, Base, T> : Base \
+ struct concept_interface<name<T, U>, Base, T, \
+ typename ::boost::disable_if< \
+ ::boost::is_same< \
+ typename ::boost::type_erasure::placeholder_of<Base>::type, \
+ const T& \
+ > \
+ >::type \
+ > : Base \
     { \
- friend typename derived<Base>::type& \
- operator op(typename derived<Base>::type& lhs, \
+ friend typename detail::non_const_this_param<Base>::type& \
+ operator op(typename detail::non_const_this_param<Base>::type& lhs, \
                     typename as_param<Base, const U&>::type rhs) \
         { \
             ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
@@ -392,7 +426,11 @@
 /// \cond show_operators
 
 template<class R, class T, class N, class Base>
-struct concept_interface<subscriptable<R, T, N>, Base, T> : Base
+struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
+ typename ::boost::enable_if<
+ ::boost::type_erasure::detail::should_be_non_const<T, Base>
+ >::type
+> : Base
 {
     typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
         typename ::boost::type_erasure::as_param<Base, const N&>::type index)
@@ -402,7 +440,11 @@
 };
 
 template<class R, class T, class N, class Base>
-struct concept_interface<subscriptable<R, const T, N>, Base, T> : Base
+struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
+ typename ::boost::enable_if<
+ ::boost::type_erasure::detail::should_be_const<T, Base>
+ >::type
+> : Base
 {
     typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
         typename ::boost::type_erasure::as_param<Base, const N&>::type index) const
@@ -428,8 +470,8 @@
 template<class Base, class Os, class T>
 struct concept_interface<ostreamable<Os, T>, Base, Os> : Base
 {
- friend typename ::boost::type_erasure::derived<Base>::type&
- operator<<(typename ::boost::type_erasure::derived<Base>::type& lhs,
+ friend typename detail::non_const_this_param<Base>::type&
+ operator<<(typename detail::non_const_this_param<Base>::type& lhs,
                typename ::boost::type_erasure::as_param<Base, const T&>::type rhs)
     {
         ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
@@ -472,8 +514,8 @@
 template<class Base, class Is, class T>
 struct concept_interface<istreamable<Is, T>, Base, Is> : Base
 {
- friend typename ::boost::type_erasure::derived<Base>::type&
- operator>>(typename ::boost::type_erasure::derived<Base>::type& lhs,
+ friend typename detail::non_const_this_param<Base>::type&
+ operator>>(typename detail::non_const_this_param<Base>::type& lhs,
                typename ::boost::type_erasure::as_param<Base, T&>::type rhs)
     {
         ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);

Modified: sandbox/type_erasure/libs/type_erasure/example/references.cpp
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/example/references.cpp (original)
+++ sandbox/type_erasure/libs/type_erasure/example/references.cpp 2012-10-08 19:37:00 EDT (Mon, 08 Oct 2012)
@@ -126,25 +126,6 @@
 
             any<incrementable<>, _self&> z(y); // error
             ++y; // error
-
- There is one subtlety about this. The proxy reference
- can have its own const qualifiers. In most cases,
- the effect is cumulative.
- */
- const any<incrementable<>, _self&> z(x);
- /*`
- `z` is treated as a reference to const even though we
- used `_self&` instead of `const _self&`.
-
- ++z; // error
-
- The one exception to this is the constructor. The
- following is well-formed, even though `z` is const.
- */
- any<incrementable<>, _self&> w(z);
- /*`
- This behavior is not ideal, but anything else
- is much too difficult to implement.
      */
     //]
 }


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