Boost logo

Boost-Commit :

From: steven_at_[hidden]
Date: 2008-04-05 16:34:13


Author: steven_watanabe
Date: 2008-04-05 16:34:12 EDT (Sat, 05 Apr 2008)
New Revision: 44065
URL: http://svn.boost.org/trac/boost/changeset/44065

Log:
Reorganized documentation
Added:
   sandbox/switch/libs/switch/example/
   sandbox/switch/libs/switch/example/Jamfile.v2 (contents, props changed)
   sandbox/switch/libs/switch/example/apply_visitor.cpp (contents, props changed)
Text files modified:
   sandbox/switch/libs/switch/doc/switch.qbk | 126 +++++++++++++++------------------------
   1 files changed, 50 insertions(+), 76 deletions(-)

Modified: sandbox/switch/libs/switch/doc/switch.qbk
==============================================================================
--- sandbox/switch/libs/switch/doc/switch.qbk (original)
+++ sandbox/switch/libs/switch/doc/switch.qbk 2008-04-05 16:34:12 EDT (Sat, 05 Apr 2008)
@@ -1,5 +1,6 @@
 [library Boost.Switch
- [version 1.0]
+ [quickbook 1.4]
+ [version 2.0]
   [authors [Watanabe, Steven]]
   [copyright 2007 Steven Watanabe]
   [license
@@ -10,16 +11,37 @@
   [purpose generates a switch statement]
 ]
 
+[def __CaseConcept [link boost_switch.reference.Concepts.CaseConcept Case Concept]]
+
 [section:introduction Introduction]
 
 The built in C/C++ switch statement is very efficient.
 Unfortunately, unlike a chained if/else construct there
 is no easy way to use it when the number of cases depends
-on a template parameter. This library attempts to provide
-for such usage.
+on a template parameter. Such uses are important for
+code generation using template metaprogramming. This
+library attempts to provide for these use cases.
+
+[endsect]
+
+[section:Examples Examples]
+
+Here is an example of using Switch to implement the apply_visitor
+function from Boost.Variant. The implementation is fairly straghtforward,
+albeit containing a lot of boilerplate.
+
+[import ../example/apply_visitor.cpp]
+
+[apply_visitor_implementation]
+
+Now, it can be used exactly like the original `boost::apply_visitor`
+
+[apply_visitor_usage]
 
 [endsect]
 
+[section:reference Reference]
+
 [section:Concepts Concepts]
 
 [section:CaseConcept Case Concept]
@@ -64,103 +86,53 @@
 [section:switch_ switch_]
 
     namespace boost {
+ namespace control {
 
- template<class Result, class Int, class Case>
- Result switch_(Int n, Case case);
+ template<class Result, class Int, class Case>
+ Result switch_(Int n, Case case);
 
- template<class Result, class Int, class Case, class Default>
- Result switch_(Int n, Case f, Default default_);
+ template<class Result, class Int, class Case, class Default>
+ Result switch_(Int n, Case case, Default default_);
 
     }
+ }
 
 [*Header]
 
- #include <boost/switch.hpp>
+ #include <boost/control/switch.hpp>
 
 [variablelist Parameters
     [[[^Result]][The type to return.]]
- [[[^n]][Must be of a built-in integal or enumeration type. Statements of the
- form switch(n) {} must be legal.]]
- [[[^case]][Model of the Case concept.]]
+ [[[^n]][Must be of a built-in integal or enumeration type.]]
+ [[[^case]][Model of the __CaseConcept.]]
     [[[^default_]][Unary function object such that default_(n) returns a type convertible to the result type]]
 ]
 
 Generates a switch statement. If the nested ::value of one
 of the elements of `Case::labels` is equal to `n`, then this function
-will return the result of calling case.apply<Result> with a default constructed
+will return the result of calling `case.apply<Result>` with a default constructed
 parameter of that type. Otherwise it will pass `n` to `default_`.
 If no default was specified, a default constructed instance of Result
-wee be returned.
+will be returned.
 
-Thus, `switch<R>(n, case, default_)` is equivalent to
+Thus, `switch_<R>(n, case, default_)` is equivalent to
 
     switch(n) {
- case mpl::at_c<Case::labels, 0>::type::value: return(case.apply<R>(mpl::at_c<Case::labels, 0>::type()));
- case mpl::at_c<Case::labels, 1>::type::value: return(case.apply<R>(mpl::at_c<Case::labels, 1>::type()));
- case mpl::at_c<Case::labels, 2>::type::value: return(case.apply<R>(mpl::at_c<Case::labels, 2>::type()));
- ...
- case mpl::at_c<Case::labels, N>::type::value: return(case.apply<R>(mpl::at_c<Case::labels, N>::type()));
- default: return(default_(n));
- }
+ typedef typename mpl::at_c<Case::labels, 0>::type case0;
+ case case0::value: return(case.apply<R>(case0()));
 
-For example
+ typedef typename mpl::at_c<Case::labels, 1>::type case1;
+ case case1::value: return(case.apply<R>(case1()));
 
- template<class FusionSequence>
- struct print_nth_function {
- typedef void result_type;
- template<class Case>
- void operator()(Case) const {
- std::cout << fusion::at<Case>(sequence) << std::endl;
- }
- print_nth(const FusionSequence& s) : sequence(s) {}
- const FusionSequence& sequence;
- };
-
- struct throw_out_of_range {
- template<class Int>
- void operator()(Int) const {
- throw(std::out_of_range());
- }
- };
-
- template<class FusionSequence>
- void print_nth(const FusionSequence& s, std::size_t n) {
- typedef typename fusion::result_of::size<FusionSequence>::type size;
- typedef mpl::range_c<std::size_t, 0, size::value> range;
- switch_<void>(n, case<range>(print_nth_function(s)), throw_out_of_range());
- }
+ typedef typename mpl::at_c<Case::labels, 2>::type case2;
+ case case2::value: return(case.apply<R>(case2()));
 
-prints the nth element of a fusion sequence.
+ ...
 
-Here is a more realistic example of using Switch to implement the apply_visitor
-function from Boost.Variant.
+ typedef typename mpl::at_c<Case::labels, N>::type caseN;
+ case caseN::value: return(case.apply<R>(caseN()));
 
- template<class Variant, class Visitor>
- struct apply_visitor_function {
- public:
- apply_visitor_function(Variant& variant, Visitor& visitor) : variant_(variant), visitor_(visitor) {}
- template<int N>
- typedef Visitor::result_type operator()(N) {
- return(visitor_(boost::get<typename mpl::at<typename Variant::type, N> >(variant_)));
- }
- private:
- Variant variant_;
- Visitor visitor_;
- };
-
- template<class R>
- struct never_called {
- template<class Int>
- R operator()(Int) {
- BOOST_ASSERT(!"this function should never be called.");
- }
- };
-
- template<class Variant, class Visitor>
- typename Visitor::result_type apply_visitor(Variant& variant, Visitor visitor) {
- apply_visitor_function<Variant, Visitor> f(variant, visitor);
- never_called<typename Visitor::result_type> default_;
- return(switch_<typename Visitor::result_type>(variant.which(), case_<mpl::range_c<int, 0, mpl::size<Variant::types>::value> >, default_));
+ default: return(default_(n));
     }
 
 [endsect]
@@ -171,7 +143,7 @@
 
 [*Header]
 
- #include <boost/switch.hpp>
+ #include <boost/control/switch.hpp>
 
 Specifies the maximum number of cases supported.
 The default value of 50 can be overridden as long
@@ -179,6 +151,8 @@
 
 [endsect]
 
+[endsect]
+
 [section:Alternatives Alternatives]
 
 [section:Map Map]

Added: sandbox/switch/libs/switch/example/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/example/Jamfile.v2 2008-04-05 16:34:12 EDT (Sat, 05 Apr 2008)
@@ -0,0 +1,16 @@
+# Jamfile.v2
+#
+# Copyright (c) 2008
+# Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 10.0 (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project switch_examples : :
+ requirements <include>../../.. <include>$(BOOST_ROOT)
+;
+
+test-suite example :
+ [ run apply_visitor.cpp ]
+;

Added: sandbox/switch/libs/switch/example/apply_visitor.cpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/example/apply_visitor.cpp 2008-04-05 16:34:12 EDT (Sat, 05 Apr 2008)
@@ -0,0 +1,88 @@
+// apply_visitor.cpp
+//
+// Copyright (c) 2008
+// 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
+
+//[apply_visitor_implementation
+
+#include <boost/variant/variant.hpp>
+#include <boost/variant/get.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/control/switch.hpp>
+#include <boost/control/case.hpp>
+
+#include <iostream>
+
+// bring switch_ and case_ into scope.
+using namespace boost::control;
+
+// index based function object which wraps the type based
+// static visitor, to make it usable by switch_.
+template<class Variant, class Visitor>
+struct apply_visitor_function {
+public:
+ apply_visitor_function(Variant& variant, Visitor& visitor)
+ : variant_(variant), visitor_(visitor) {}
+ template<class N>
+ typename Visitor::result_type operator()(N) {
+ // N is the index of the type that the variant currently holds.
+ // Extract the object of that type and call the user's visitor.
+ typedef typename Variant::types types;
+ typedef typename boost::mpl::at<types, N>::type contained_type;
+ return(visitor_(boost::get<contained_type>(variant_)));
+ }
+private:
+ Variant& variant_;
+ Visitor& visitor_;
+};
+
+// One of the cases should always be selected. If the
+// the default is executed it must be an error.
+template<class R>
+struct never_called {
+ template<class Int>
+ R operator()(Int) {
+ BOOST_ASSERT(!"this function should never be called.");
+ }
+};
+
+// implementation of boost::apply_visitor using switch_.
+template<class Visitor, class Variant>
+typename Visitor::result_type apply_visitor(Visitor visitor, Variant& variant) {
+ typedef typename Visitor::result_type result_type;
+ typedef boost::mpl::size<Variant::types> size;
+ typedef boost::mpl::range_c<int, 0, size::value> cases;
+ apply_visitor_function<Variant, Visitor> f(variant, visitor);
+ never_called<typename Visitor::result_type> default_;
+ return(switch_<result_type>(variant.which(), case_<cases>(f), default_));
+}
+
+//]
+
+//[apply_visitor_usage
+
+struct my_visitor : boost::static_visitor<> {
+ void operator()(int) const {
+ std::cout << "Got an int!" << std::endl;
+ }
+ void operator()(double) const {
+ std::cout << "Got a double!" << std::endl;
+ }
+ void operator()(char) const {
+ std::cout << "Got a char!" << std::endl;
+ }
+};
+
+int main() {
+ boost::variant<int, char, double> my_variant(1.0);
+ ::apply_visitor(my_visitor(), my_variant);
+}
+
+//]


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