Boost logo

Boost-Commit :

From: steven_at_[hidden]
Date: 2007-11-19 10:38:29


Author: steven_watanabe
Date: 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
New Revision: 41228
URL: http://svn.boost.org/trac/boost/changeset/41228

Log:
Initial import
Added:
   sandbox/switch/
   sandbox/switch/boost/
   sandbox/switch/boost/switch.hpp (contents, props changed)
   sandbox/switch/libs/
   sandbox/switch/libs/switch/
   sandbox/switch/libs/switch/boost.png (contents, props changed)
   sandbox/switch/libs/switch/doc/
   sandbox/switch/libs/switch/doc/Jamfile.v2 (contents, props changed)
   sandbox/switch/libs/switch/doc/switch.qbk (contents, props changed)
   sandbox/switch/libs/switch/test/
   sandbox/switch/libs/switch/test/Jamfile.v2 (contents, props changed)
   sandbox/switch/libs/switch/test/test_switch.cpp (contents, props changed)

Added: sandbox/switch/boost/switch.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/boost/switch.hpp 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,129 @@
+// switch.hpp
+//
+// Copyright (c) 2006-2007
+// Steven Watanabe
+//
+// Distriuted 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)
+
+#ifndef BOOST_SWITCH_HPP_INCLUDED
+#define BOOST_SWITCH_HPP_INCLUDED
+
+#include <stdexcept>
+#include <string>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/preprocessor/config/limits.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/at.hpp>
+
+#ifndef BOOST_SWITCH_LIMIT
+ #define BOOST_SWITCH_LIMIT 50
+#endif
+
+#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT
+ #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit
+#endif
+#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION
+ #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit
+#endif
+
+namespace boost {
+
+class bad_switch : public std::runtime_error {
+public:
+ template<class Int>
+ explicit bad_switch(Int v) :
+ std::runtime_error(
+ "boost::switch_ default case called -- none provided. value is: " +
+ boost::lexical_cast<std::string>(v)) {}
+};
+
+namespace switch_detail {
+
+// Avoid the need to create all the specializations of switch_impl
+// twice. Just pass this to switch_impl<N>::apply(...) when no
+// default is supplied.
+
+template<class R>
+R forced_return(R* r = 0) {
+ return(*r);
+}
+
+// Thanks to Stjepan Rajko for catching this.
+template<>
+void forced_return<void>(void*) {}
+
+template<class R>
+struct throw_exception {
+ template<class Int>
+ R operator()(Int i) const {
+ boost::throw_exception(bad_switch(i));
+ return(switch_detail::forced_return<R>());
+ }
+};
+
+// N is the number of cases not including the default
+template<int N>
+struct switch_impl;
+
+// specialize for 0 separately to avoid warnings
+template<>
+struct switch_impl<0> {
+ template<class V, class Int, class F, class Default>
+ static typename F::result_type
+ apply(Int i, F, Default d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+ return(d(i));
+ }
+};
+
+#define BOOST_SWITCH_CASE(z, n, data) \
+ case boost::mpl::at_c<data, n>::type::value: { \
+ typename boost::mpl::at_c<data, n>::type arg; \
+ return(f(arg)); \
+ }
+
+#define BOOST_SWITCH_IMPL(z, n, data) \
+ template<> \
+ struct switch_impl<n> { \
+ template<class V, class I, class F, class D> \
+ static typename F::result_type \
+ apply(I i, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) { \
+ switch(i) { \
+ BOOST_PP_REPEAT_##z(n, BOOST_SWITCH_CASE, V) \
+ default: return(d(i)); \
+ } \
+ } \
+ };
+
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_SWITCH_LIMIT)
+#define BOOST_PP_LOCAL_MACRO(n) BOOST_SWITCH_IMPL(1, n, ~)
+#include BOOST_PP_LOCAL_ITERATE()
+
+#undef BOOST_SWITCH_IMPL
+#undef BOOST_SWITCH_CASE
+
+}
+
+template<class V, class N, class F>
+inline typename F::result_type
+switch_(N n, F f BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+ typedef switch_detail::switch_impl<boost::mpl::size<V>::value> impl;
+ switch_detail::throw_exception<typename F::result_type> default_;
+ return(impl::template apply<V>(n, f, default_));
+}
+
+template<class V, class N, class F, class D>
+inline typename F::result_type
+switch_(N n, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+ typedef switch_detail::switch_impl<boost::mpl::size<V>::value> impl;
+ return(impl::template apply<V>(n, f, d));
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/boost.png
==============================================================================
Binary file. No diff available.

Added: sandbox/switch/libs/switch/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/doc/Jamfile.v2 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,14 @@
+# Switch documentation Jamfile
+#
+# Copyright (c) 2007
+# 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
+
+using quickbook ;
+
+xml switch_ : switch.qbk ;
+
+boostbook standalone : switch_ ;

Added: sandbox/switch/libs/switch/doc/switch.qbk
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/doc/switch.qbk 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,109 @@
+[library Boost.Switch
+ [version 1.0]
+ [authors [Watanabe, Steven]]
+ [copyright 2007 Steven Watanabe]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ <ulink href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)
+ ]
+ [purpose generates a switch statement]
+]
+
+[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.
+
+[endsect]
+
+[section:switch_ switch_]
+
+ namespace boost {
+
+ template<class Cases, class Int, class F>
+ typename F::result_type switch_(Int n, F f);
+
+ template<class Cases, class Int, class F, class Default>
+ typename F::result_type switch_(Int n, F f, Default default_);
+
+ }
+
+[*Header]
+
+ #include <boost/switch.hpp>
+
+[variablelist Parameters
+ [[[^Cases]][MPL Forward Sequence of integer constants]]
+ [[[^n]][Integer]]
+ [[[^f]][Function object]]
+ [[[^default_]][Function object]]
+]
+
+Generates a switch statement. If the value of one
+of the elements of `Cases` is equal to `n`, then this function
+will call `f` with a parameter of that type. Otherwise
+it will pass `n` to `default_` or throw an exception depending
+on whether `default_` was specified. For example
+
+ 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_<range>(n, print_nth_function(s), throw_out_of_range());
+ }
+
+prints the nth element of a fusion sequence.
+
+[endsect]
+
+[section:bad_switch bad_switch]
+
+ namespace boost {
+
+ class bad_switch : public std::runtime_error {};
+
+ }
+
+[*Header]
+
+ #include <boost/switch.hpp>
+
+Thrown when the default case is executed
+and no default was provided.
+
+[endsect]
+
+[section:BOOST_SWITCH_LIMIT BOOST_SWITCH_LIMIT]
+
+ #define BOOST_SWITCH_LIMIT 50
+
+[*Header]
+
+ #include <boost/switch.hpp>
+
+Specifies the maximum number of cases supported.
+The default value of 50 can be overridden as long
+as it is the same in every translation unit.
+
+[endsect]

Added: sandbox/switch/libs/switch/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/test/Jamfile.v2 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,22 @@
+# Switch
+#
+# Copyright (c) 2007
+# 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
+
+import testing ;
+
+project switch_test : :
+ requirements <include>../../.. <warnings>all
+;
+
+
+{
+ test-suite switch_:
+ :
+ [ run test_switch.cpp $(BOOST_ROOT)/libs/test/build//boost_unit_test_framework : : : : ]
+ ;
+}

Added: sandbox/switch/libs/switch/test/test_switch.cpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/test/test_switch.cpp 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,113 @@
+// test_switch.cpp
+//
+// Copyright (c) 2007
+// 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)
+
+#define BOOST_AUTO_TEST_MAIN
+
+#include <boost/switch.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/vector_c.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
+namespace {
+ typedef boost::mpl::vector_c<int, 0, 2, 1, 4, 5, 6, 3> values;
+ struct f {
+ typedef int result_type;
+ template<class Index>
+ int operator()(Index) {
+ return(boost::mpl::at<values, Index>::type::value);
+ }
+ };
+ int default_(int i) {
+ return(i);
+ }
+ typedef boost::mpl::range_c<int, 0, 0> empty_range;
+ typedef boost::mpl::vector_c<int, 1, 0, 5> non_sequential_range;
+ typedef boost::mpl::range_c<int, 0, 7> test_range;
+
+ struct limit_test {
+ typedef int result_type;
+ template<class Index>
+ int operator()(Index) {
+ return(-Index::value);
+ }
+ };
+ typedef boost::mpl::range_c<int, 0, BOOST_SWITCH_LIMIT> limit_range;
+ const int limit_value = BOOST_SWITCH_LIMIT - 1;
+
+ struct void_return {
+ typedef void result_type;
+ template<class Index>
+ void operator()(Index) {
+ // Do Nothing.
+ }
+ };
+}
+
+BOOST_AUTO_TEST_CASE(without_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<test_range>(5, f())), 6);
+ BOOST_CHECK_EQUAL((boost::switch_<test_range>(1, f())), 2);
+
+ BOOST_CHECK_THROW((boost::switch_<test_range>(-1, f())), boost::bad_switch);
+ BOOST_CHECK_THROW((boost::switch_<test_range>(7, f())), boost::bad_switch);
+}
+
+BOOST_AUTO_TEST_CASE(with_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<test_range>(5, f(), &default_)), 6);
+ BOOST_CHECK_EQUAL((boost::switch_<test_range>(1, f(), &default_)), 2);
+
+ BOOST_CHECK_EQUAL((boost::switch_<test_range>(-1, f(), &default_)), -1);
+ BOOST_CHECK_EQUAL((boost::switch_<test_range>(7, f(), &default_)), 7);
+}
+
+BOOST_AUTO_TEST_CASE(non_sequential_without_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(5, f())), 6);
+ BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(1, f())), 2);
+
+ BOOST_CHECK_THROW((boost::switch_<non_sequential_range>(-1, f())), boost::bad_switch);
+ BOOST_CHECK_THROW((boost::switch_<non_sequential_range>(7, f())), boost::bad_switch);
+}
+
+BOOST_AUTO_TEST_CASE(non_sequential_with_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(5, f(), &default_)), 6);
+ BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(1, f(), &default_)), 2);
+
+ BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(-1, f(), &default_)), -1);
+ BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(7, f(), &default_)), 7);
+}
+
+BOOST_AUTO_TEST_CASE(zero_params_without_default) {
+ BOOST_CHECK_THROW((boost::switch_<empty_range>(5, f())), boost::bad_switch);
+ BOOST_CHECK_THROW((boost::switch_<empty_range>(1, f())), boost::bad_switch);
+ BOOST_CHECK_THROW((boost::switch_<empty_range>(0, f())), boost::bad_switch);
+
+ BOOST_CHECK_THROW((boost::switch_<empty_range>(-1, f())), boost::bad_switch);
+ BOOST_CHECK_THROW((boost::switch_<empty_range>(7, f())), boost::bad_switch);
+}
+
+BOOST_AUTO_TEST_CASE(zero_params_with_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<empty_range>(5, f(), &default_)), 5);
+ BOOST_CHECK_EQUAL((boost::switch_<empty_range>(1, f(), &default_)), 1);
+ BOOST_CHECK_EQUAL((boost::switch_<empty_range>(0, f(), &default_)), 0);
+
+ BOOST_CHECK_EQUAL((boost::switch_<empty_range>(-1, f(), &default_)), -1);
+ BOOST_CHECK_EQUAL((boost::switch_<empty_range>(7, f(), &default_)), 7);
+}
+
+BOOST_AUTO_TEST_CASE(limit_without_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<limit_range>(limit_value, limit_test())), -limit_value);
+}
+
+BOOST_AUTO_TEST_CASE(limit_with_default) {
+ BOOST_CHECK_EQUAL((boost::switch_<limit_range>(limit_value, limit_test(), &default_)), -limit_value);
+}
+
+BOOST_AUTO_TEST_CASE(test_void) {
+ boost::switch_<test_range>(0, void_return());
+}


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