$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80622 - in sandbox/type_erasure/libs/type_erasure: doc example
From: steven_at_[hidden]
Date: 2012-09-21 16:50:45
Author: steven_watanabe
Date: 2012-09-21 16:50:44 EDT (Fri, 21 Sep 2012)
New Revision: 80622
URL: http://svn.boost.org/trac/boost/changeset/80622
Log:
Try to improve documentation based on the review comments.
Text files modified: 
   sandbox/type_erasure/libs/type_erasure/doc/type_erasure.qbk |   198 ++++++++++++++++++++++++--------------- 
   sandbox/type_erasure/libs/type_erasure/example/basic.cpp    |    69 +++++++++++++                           
   sandbox/type_erasure/libs/type_erasure/example/custom.cpp   |    20 ++-                                     
   sandbox/type_erasure/libs/type_erasure/example/overload.cpp |    11 +                                       
   4 files changed, 203 insertions(+), 95 deletions(-)
Modified: sandbox/type_erasure/libs/type_erasure/doc/type_erasure.qbk
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/doc/type_erasure.qbk	(original)
+++ sandbox/type_erasure/libs/type_erasure/doc/type_erasure.qbk	2012-09-21 16:50:44 EDT (Fri, 21 Sep 2012)
@@ -65,31 +65,70 @@
 [def __random_access_iterator [classref boost::type_erasure::random_access_iterator random_access_iterator]]
 [def __same_type [classref boost::type_erasure::same_type same_type]]
 
+[def __BOOST_TYPE_ERASURE_MEMBER [macroref BOOST_TYPE_ERASURE_MEMBER]]
+[def __BOOST_TYPE_ERASURE_FREE [macroref BOOST_TYPE_ERASURE_FREE]]
 
 [section:introduction Introduction]
 
-C++ provides runtime polymorphism through virtual
-functions.  They are a very useful feature, but
-they do have some limitations.
-
-* They are intrusive.  In generic programming, we can
-  design an interface which allows third-party types
-  to be adapted to it.
-* They require dynamic memory management.  Of course,
-  most of the problems can be avoided by using an
-  appropriate smart pointer type. Even so, it still
-  acts like a pointer rather than a value.
-* Virtual functions' ability to apply multiple
-  independent concepts to a single object is limited.
-
-The Boost.TypeErasure library solves these problems
-allowing us to mirror static generic programming
-at runtime.
+The TypeErasure library provides runtime polymorphism
+in C++, superior to that provided by the core language.
 
-[note TypeErasure is not an official Boost library.]
-
-[import ../example/intro.cpp]
-[intro]
+We have two distinct kinds of polymorphism built in to C++,
+virtual functions and templates, which each have
+their own advantages and disadvantages.
+
+* Virtual functions are not resolved until runtime,
+  while templates are always resolved at compile
+  time.  If your types can vary at runtime (for
+  example, if they depend on user input), then
+  static polymorphism with templates doesn't help much.
+* Virtual functions can be used with separate compilation.
+  The body of a template has to be available
+  in every translation unit in which it is used,
+  slowing down compiles and increasing rebuilds.
+* Virtual function automatically make the requirements
+  on the aruments explicit.  Templates are only
+  checked when they're instantiated, requiring
+  extra work in testing, assertions, and documentation.
+* The compiler creates a new copy of each function
+  template every time it is instantiated.  This
+  allows better optimization, because the compiler
+  knows everything statically, but it also causes
+  a significant increase of binary sizes.
+* Templates support Value semantics.  Objects that
+  "behave like an int" and are not shared are easier
+  to reason about.  To use virtual functions, on
+  the other hand, you have to use (smart) pointers
+  or references.
+* Template libraries can allow third-party types to
+  be adapted non-intrusively for seamless interoperability.
+  With virtual functions, you have to create a wrapper
+  that inherits from the base class.
+* Templates can handle constraints involving
+  multiple types.  For example, std::for_each
+  takes an iterator range and a function that
+  can be called on the elements of the range.
+  Virtual functions aren't really able to
+  express such constraints.
+
+The Boost.TypeErasure library provides another set
+of trade-offs.  As with virtual functions, dispatching
+occurs at runtime and you can define a function once
+in a source file.  The requirements are stated up front
+in the form of a Concept.  Like templates, the library
+supports value semantics, non-intrusive adaptation, and
+requirements across multiple types.
+
+Boost includes several special cases of this kind
+of polymorphism:
+
+* `boost::any` for CopyConstructible types.
+* `boost::function` for objects that can be called like functions.
+* Boost.Range provides `any_iterator`.
+
+Boost.TypeErasure generalizes this to support arbitrary
+requirements and provides a
+[link boost_typeerasure.predef predefined set of common concepts]
 
 [endsect]
 
@@ -104,20 +143,34 @@
 [endsect]
 
 [section:basic Basic Usage]
+
 [import ../example/basic.cpp]
 [basic]
-[endsect]
 
-[section:multi Functions with Multiple Arguments]
-[import ../example/multi.cpp]
-[multi]
+[section Composing Concepts]
+[import ../example/compose.cpp]
+[compose]
 [endsect]
 
-[section:convert Conversions]
+[section Conversions]
 [import ../example/convert.cpp]
 [convert]
 [endsect]
 
+[endsect]
+
+[section:concept Concepts in Depth]
+
+[section:custom Defining Custom Concepts]
+[import ../example/custom.cpp]
+[custom]
+[endsect]
+
+[section:overload Overloading]
+[import ../example/overload.cpp]
+[overload]
+[endsect]
+
 [section:references Using References]
 [import ../example/references.cpp]
 [references]
@@ -128,16 +181,9 @@
 [construction]
 [endsect]
 
-[section:concept Concepts in Depth]
-
-[section:custom Defining Custom Concepts]
-[import ../example/custom.cpp]
-[custom]
-[endsect]
-
-[section:compose Composing Concepts]
-[import ../example/compose.cpp]
-[compose]
+[section:multi Functions with Multiple Arguments]
+[import ../example/multi.cpp]
+[multi]
 [endsect]
 
 [section:concept_map Concept Maps]
@@ -145,11 +191,6 @@
 [concept_map]
 [endsect]
 
-[section:overload Overloading]
-[import ../example/overload.cpp]
-[overload]
-[endsect]
-
 [section:overload Associated Types]
 [import ../example/associated.cpp]
 [associated]
@@ -217,29 +258,6 @@
 
 [endsect]
 
-[section:reserved Reserved Identifiers]
-
-The library reserves all names begining with
-`_boost_type_erasure` for use as members.  No
-class shall contain such a member except
-those defined by the library.
-
-The library reserves all identifiers begining
-with `BOOST_TYPE_ERASURE` for any use.
-
-FIXME: this is too broad.
-The library reserves all identifiers that
-are either a single upper case letter,
-a single upper case letter followed by
-a sequence of digits, in CamelCase, or
-underscore_separated for use in namespace
-`boost::type_erasure`. Such identifiers may
-not be defined as macros.  (Macros defined
-in system headers that I know about are
-excepted for the sake of pragmatism.).
-
-[endsect]
-
 [section:predef Predefined Concepts]
 
 In the following tables, `T` and `U` are the types that the operation
@@ -332,6 +350,19 @@
 with anything that a user might want.
 [endsect]
 
+[section:placeholder Why are the placeholders called `_a`, `_b` and not `_1` `_2`]
+
+An earlier version of the library used the names `_1`, `_2`, etc.
+instead of `_a`, `_b`, etc.  This caused a certain amount
+of confusion because the numbered placeholders are
+already used with a somewhat different meaning by several
+other libraries including Boost/Std Bind, Boost.Phoenix,
+and Boost.MPL.  I eventually decided that since the
+placeholders represented named parameters instead of positional parameters,
+letters were more appropriate than numbers.
+
+[endsect]
+
 [endsect]
 
 [section:design Design Notes]
@@ -515,19 +546,6 @@
 
 [endsect]
 
-[section:placeholder Placeholder Names]
-
-An earlier version of the library used the names `_1`, `_2`, etc.
-instead of `_a`, `_b`, etc.  This caused a certain amount
-of confusion because the numbered placeholders are
-already used by several other libraries including
-Boost/Std Bind, Boost.Phoenix, and Boost.MPL.  I
-eventually decided that since the placeholders represented
-named parameters instead of positional parameters,
-letters were more appropriate than numbers.
-
-[endsect]
-
 [endsect]
 
 [section:feedback Feedback Wanted]
@@ -594,7 +612,29 @@
 
 [section:acknowledgements Acknowledgements]
 
-* The name `any` was taken from Alexander Nasonov's
-  DynamicAny library.
+The name `any` was taken from Alexander Nasonov's
+DynamicAny library.
+
+Thanks to review manager, Lorenzo Caminiti
+and all who participated in the formal review:
+
+* Christophe Henry
+* Paul Bristow
+* Karsten Ahnert
+* Pete Bartlett
+* Sebastian Redl
+* Hossein Haeri
+* Trigve Siver
+* Julien Nitard
+* Eric Niebler
+* Fabio Fracassi
+* Joel de Guzman
+* Alec Chapman
+* Larry Evans
+* Vincente J. Botet Escriba
+* Marcus Werle
+* Andrey Semashev
+* Dave Abrahams
+* Thomas Jordan
 
 [endsect]
Modified: sandbox/type_erasure/libs/type_erasure/example/basic.cpp
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/example/basic.cpp	(original)
+++ sandbox/type_erasure/libs/type_erasure/example/basic.cpp	2012-09-21 16:50:44 EDT (Fri, 21 Sep 2012)
@@ -22,11 +22,11 @@
     //[basic1
     /*`
         The main class in the library is __any.  We can just pass
-        it an MPL sequence containing all the concepts that we
-        wish to use.
+        it an MPL sequence specifying all the requirements on
+        the types that it can hold.
 
         [note The MPL sequence combines multiple concepts.
-        In the rare case when we only want one concept, it doesn't
+        In the rare case when we only want a single concept, it doesn't
         need to be wrapped in an MPL sequence.]
     */
     any<mpl::vector<copy_constructible<>, typeid_<> > > x(10);
@@ -44,7 +44,8 @@
     /*`
         Now, this example doesn't do very much.  `x` is approximately
         equivalent to a [@boost:/libs/any/index.html boost::any].
-        Let's add a few more features.
+        We can make it more interesting by adding some operators,
+        such as `operator++` and `operator<<`
     */
     any<
         mpl::vector<
@@ -59,9 +60,69 @@
     //]
 }
 
+//[basic3
+/*`
+    The library provides a full set of operators, but this
+    obviously won't cover all use cases;  we often need to
+    define our own requirements.  Let's take the `push_back`
+    method, defined by several STL containers.
+*/
+
+BOOST_TYPE_ERASURE_MEMBER((has_push_back), push_back, 1)
+
+void append_many(any<has_push_back<void(int)>, _self&> container) {
+    for(int i = 0; i < 10; ++i)
+        container.push_back(i);
+}
+
+/*`
+    There are a few things to note about this.  First,
+    we use the macro __BOOST_TYPE_ERASURE_MEMBER to
+    define a concept called `has_push_back` for a
+    member function called `push_back` which takes
+    one argument.  When we use `has_push_back`, we have to
+    give it the signature of the function, `void(int)`.
+    This means that we expect to find a function
+    that looks like:
+
+    ``
+    void push_back(int);
+    ``
+
+    Thus, we could call `append_many` with `std::vector<int>`,
+    `std::list<int>`, or `std::vector<long>` (because `int` is
+    convertible to `long`), but not `std::list<std::string>`
+    or `std::set<int>`.
+
+    Also, note the use of `_self&` as the second argument of
+    __any.  `_self` is a __placeholder.  By using it here,
+    we indicate that the __any stores a reference
+    to another object instead of owning its own object.
+*/
+
+/*`
+    For free functions, we can use __BOOST_TYPE_ERASURE_FREE.
+*/
+
+BOOST_TYPE_ERASURE_FREE((has_swap), swap, 2);
+template<class T = _self>
+struct swappable : mpl::vector<has_swap<void(T&, T&)> > {};
+
+/*`
+    We use the __placeholder `_self` here to indicate which arguments
+    of `swap` should be any's.  When we use swap, we want it
+    to look like `has_swap<void(_self&, _self&)>`, since `swap`
+    takes two arguments of the same type by reference.  Since
+    the signature of swap always looks like this, we define
+    `swappable<>` as a convenient short-cut.
+*/
+
+//]
+
 //[basic
 //` (For the source of the examples in this section see
 //` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp])
 //` [basic1]
 //` [basic2]
+//` [basic3]
 //]
Modified: sandbox/type_erasure/libs/type_erasure/example/custom.cpp
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/example/custom.cpp	(original)
+++ sandbox/type_erasure/libs/type_erasure/example/custom.cpp	2012-09-21 16:50:44 EDT (Fri, 21 Sep 2012)
@@ -18,14 +18,16 @@
 
 //[custom1
 /*`
-    Let's define a concept to allow push_back on a sequence.
-    To do this, we create a class template with a template
-    parameter for each argument, and a static member function
+    Earlier, we used __BOOST_TYPE_ERASURE_MEMBER to define
+    a concept for containers that support `push_back`.  Let's
+    take a look at what this actually entails.  The first thing
+    we need is a class template with a template parameter for
+    each argument, and a static member function
     called `apply` that calls `push_back`.
 */
 
 template<class C, class T>
-struct push_back
+struct has_push_back
 {
     static void apply(C& cont, const T& arg) { cont.push_back(arg); }
 };
@@ -48,10 +50,10 @@
 namespace boost {
 namespace type_erasure {
 template<class C, class T, class Base>
-struct concept_interface< ::push_back<C, T>, Base, C> : Base
+struct concept_interface<has_push_back<C, T>, Base, C> : Base
 {
     void push_back(typename rebind_any<Base, const T&>::type arg)
-    { call(::push_back<C, T>(), *this, arg); }
+    { call(has_push_back<C, T>(), *this, arg); }
 };
 }
 }
@@ -64,9 +66,9 @@
         __call to dispatch the operation.
     */
     std::vector<int> vec;
-    any<push_back<_self, int>, _self&> c(vec);
+    any<has_push_back<_self, int>, _self&> c(vec);
     int i = 10;
-    call(push_back<_self, int>(), c, i);
+    call(has_push_back<_self, int>(), c, i);
     // vec is [10].
     //]
 }
@@ -81,7 +83,7 @@
         now becomes
     */
     std::vector<int> vec;
-    any<push_back<_self, int>, _self&> c(vec);
+    any<has_push_back<_self, int>, _self&> c(vec);
     c.push_back(10);
     /*`
         which is what we want.
Modified: sandbox/type_erasure/libs/type_erasure/example/overload.cpp
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/example/overload.cpp	(original)
+++ sandbox/type_erasure/libs/type_erasure/example/overload.cpp	2012-09-21 16:50:44 EDT (Fri, 21 Sep 2012)
@@ -19,8 +19,10 @@
 
 //[overload1
 /*`
-    Sometimes we want to use the same concept several times
-    with different parameters.  Specializing __concept_interface
+    __concept_interface allows us to inject arbitrary declarations
+    into an __any.  This is very flexible, but there are some pitfalls
+    to watch out for.  Sometimes we want to use the same concept several
+    times with different parameters.  Specializing __concept_interface
     in a way that handles overloads correctly is a bit tricky.
     Given a concept foo, we'd like the following to work:
 
@@ -147,7 +149,10 @@
     __rebind_any, then we could end up violating the one definition
     rule by defining the same function twice.  Similarly, we use
     SFINAE in the second specialization to make sure that bar is
-    only defined once when both arguments are placeholders.
+    only defined once when both arguments are placeholders.  It's
+    possible to merge the two specializations with a bit of metaprogramming,
+    but unless you have a lot of arguments, it's probably not
+    worth while.
     
     At first I tried overloading `bar` at namespace scope.  This
     seems like a more obvious solution at first.  Don't use it.