Boost logo

Boost-Commit :

From: steven_at_[hidden]
Date: 2008-02-12 18:45:33


Author: steven_watanabe
Date: 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
New Revision: 43228
URL: http://svn.boost.org/trac/boost/changeset/43228

Log:
Initial version of new interface
Added:
   sandbox/switch/libs/switch/alternate/
   sandbox/switch/libs/switch/alternate/switch/
   sandbox/switch/libs/switch/alternate/switch/Jamfile.v2 (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/binary_search.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/case.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/fusion.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/if_else.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/map.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/sorted_array.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/switch.hpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/test_case.cpp (contents, props changed)
   sandbox/switch/libs/switch/alternate/switch/test_speed.cpp (contents, props changed)

Added: sandbox/switch/libs/switch/alternate/switch/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/Jamfile.v2 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,22 @@
+# Switch
+#
+# Copyright (c) 2007-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
+
+import testing ;
+
+project switch_test : :
+ requirements <include>../../.. <include>$(BOOST_ROOT) <warnings>all
+;
+
+
+{
+ test-suite switch_:
+ :
+ [ run test_case.cpp $(BOOST_ROOT)/libs/test/build//boost_unit_test_framework : : : : ]
+ ;
+}

Added: sandbox/switch/libs/switch/alternate/switch/binary_search.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/binary_search.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,219 @@
+// binary_search.hpp
+//
+// Copyright (c) 2008
+// 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_BINARY_SEARCH_HPP_INCLUDED
+#define BOOST_SWITCH_BINARY_SEARCH_HPP_INCLUDED
+
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+
+namespace boost {
+
+namespace binary_search_switch {
+
+template<int N>
+struct list_at {
+ template<class L>
+ struct apply {
+ typedef typename list_at<N - 1>::template apply<L>::type::tail type;
+ };
+};
+
+template<>
+struct list_at<0> {
+ template<class L>
+ struct apply {
+ typedef L type;
+ };
+};
+
+struct list_end {};
+
+template<class T, class Tail>
+struct list {
+ typedef T element;
+ typedef Tail tail;
+};
+
+template<class List, class T>
+struct insert;
+
+template<bool>
+struct insert_impl;
+
+template<>
+struct insert_impl<true> {
+ template<class List, class T>
+ struct apply {
+ typedef list<T, List> type;
+ };
+};
+
+template<>
+struct insert_impl<false> {
+ template<class List, class T>
+ struct apply {
+ typedef list<typename List::element, typename insert<typename List::tail, T>::type> type;
+ };
+};
+
+template<class List, class T>
+struct insert {
+ typedef typename insert_impl<(T::value) < (List::element::value)>::template apply<List, T>::type type;
+};
+
+template<class T>
+struct insert<list_end, T> {
+ typedef list<T, list_end> type;
+};
+
+template<int Low, int High, class S, int Diff = (High - Low)>
+struct switch_impl {
+ static const int mid = Low + Diff / 2;
+ typedef typename list_at<mid>::template apply<S>::type::element mid_t;
+ template<class R, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ if(mid_t::value < i) {
+ return(switch_impl<mid, High, S>::template apply<R>(i, f, d));
+ } else {
+ return(switch_impl<Low, mid, S>::template apply<R>(i, f, d));
+ }
+ }
+};
+
+template<int Low, int High, class S>
+struct switch_impl<Low, High, S, 0> {
+ template<class R, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ return(d(i));
+ }
+};
+
+template<int Low, int High, class S>
+struct switch_impl<Low, High, S, 2> {
+ typedef typename list_at<Low>::template apply<S>::type::element first_t;
+ typedef typename list_at<Low + 1>::template apply<S>::type::element second_t;
+ template<class R, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ if(first_t::value == i) {
+ return(f.template apply<R>(first_t()));
+ } else if(second_t::value == i) {
+ return(f.template apply<R>(second_t()));
+ } else {
+ return(d(i));
+ }
+ }
+};
+
+template<int Low, int High, class S>
+struct switch_impl<Low, High, S, 1> {
+ typedef typename list_at<Low>::template apply<S>::type::element mid_t;
+ template<class R, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ if(mid_t::value == i) {
+ return(f.template apply<R>(mid_t()));
+ } else {
+ return(d(i));
+ }
+ }
+};
+
+template<int Low, int High, class S>
+struct switch_impl<Low, High, S, 3> {
+ static const int mid = Low + 1;
+ typedef typename list_at<mid>::template apply<S>::type::element mid_t;
+ template<class R, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ if(mid_t::value < i) {
+ return(switch_impl<mid + 1, High, S>::template apply<R>(i, f, d));
+ } else if(mid_t::value > i) {
+ return(switch_impl<Low, mid, S>::template apply<R>(i, f, d));
+ } else {
+ return(f.template apply<R>(mid_t()));
+ }
+ }
+};
+
+template<int N>
+struct sort {
+ template<class Iter>
+ struct apply {
+ typedef typename mpl::next<Iter>::type next1;
+ typedef typename mpl::next<next1>::type next2;
+ typedef typename mpl::next<next2>::type next3;
+ typedef typename mpl::next<next3>::type next4;
+ typedef typename insert<
+ typename insert<
+ typename insert<
+ typename insert<typename sort<N - 4>::template apply<next4>::type,
+ typename mpl::deref<next3>::type>::type,
+ typename mpl::deref<next2>::type>::type,
+ typename mpl::deref<next1>::type>::type,
+ typename mpl::deref<Iter>::type>::type
+ type;
+ };
+};
+
+template<>
+struct sort<0> {
+ template<class Iter>
+ struct apply {
+ typedef list_end type;
+ };
+};
+
+template<>
+struct sort<1> {
+ template<class Iter>
+ struct apply {
+ typedef list<typename mpl::deref<Iter>::type, list_end> type;
+ };
+};
+
+template<>
+struct sort<2> {
+ template<class Iter>
+ struct apply {
+ typedef typename mpl::next<Iter>::type next1;
+ typedef typename insert<
+ list<typename mpl::deref<next1>::type, list_end>,
+ typename mpl::deref<Iter>::type>::type
+ type;
+ };
+};
+
+template<>
+struct sort<3> {
+ template<class Iter>
+ struct apply {
+ typedef typename mpl::next<Iter>::type next1;
+ typedef typename mpl::next<next1>::type next2;
+ typedef typename insert<
+ typename insert<
+ list<typename mpl::deref<next2>::type, list_end>,
+ typename mpl::deref<next1>::type>::type,
+ typename mpl::deref<Iter>::type>::type
+ type;
+ };
+};
+
+template<class R, class I, class F, class D>
+R switch_(I i, const F& f, D d) {
+ typedef switch_impl<0, mpl::size<typename F::labels>::value,
+ typename sort<mpl::size<typename F::labels>::value>::template apply<typename mpl::begin<typename F::labels>::type>::type> impl;
+ return(impl::template apply<R>(i, f, d));
+}
+
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/case.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/case.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,178 @@
+// case.hpp
+//
+// 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)
+
+#ifndef BOOST_SWITCH_CASE_HPP_INCLUDED
+#define BOOST_SWITCH_CASE_HPP_INCLUDED
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/vector/vector50.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/fold.hpp>
+
+namespace boost {
+
+namespace switch_detail {
+
+struct empty_set {
+ template<class T>
+ static char lookup(T);
+};
+
+template<class Base, class T>
+struct set : Base {
+ static char (&lookup(T))[2];
+ using Base::lookup;
+ typedef set type;
+};
+
+template<class S>
+struct make_set {
+ typedef typename mpl::fold<S, empty_set, set<mpl::_, mpl::_> >::type type;
+};
+
+template<class S, class N>
+struct contains_impl {
+ typedef typename switch_detail::make_set<S>::type as_set;
+ static const bool value = (sizeof(as_set::lookup(N())) != 1);
+};
+
+}
+
+template<class Case>
+class restrict_case_t {
+public:
+ template<class T>
+ explicit restrict_case_t(T& t) : impl(t) {}
+ typedef typename Case::labels labels;
+ template<class R, class N>
+ typename boost::enable_if_c<
+ switch_detail::contains_impl<typename Case::labels, N>::value,
+ R
+ >::type apply(N n) const {
+ return(impl.template apply<R>(n));
+ }
+private:
+ Case impl;
+};
+
+template<class Case1, class Case2>
+class binary_case_t : public Case1, public Case2 {
+public:
+ template<class T>
+ explicit binary_case_t(const T& t) : Case1(t), Case2(t) {}
+ binary_case_t(const Case1& case1, const Case2& case2) :
+ Case1(case1),
+ Case2(case2) {}
+ // msvc does not like mpl::joint_view
+ typedef typename mpl::copy<
+ typename Case2::labels,
+ mpl::back_inserter<typename Case1::labels>
+ >::type labels;
+ using Case1::apply;
+ using Case2::apply;
+};
+
+template<class N, class F>
+class single_case_t {
+public:
+ single_case_t(F f) : impl(f) {}
+ typedef mpl::vector1<N> labels;
+ template<class R>
+ R apply(N n) const {
+ return(impl(n));
+ }
+private:
+ F impl;
+};
+
+template<class S, class F>
+class case_group_t {
+public:
+ case_group_t(F f) : impl(f) {}
+ typedef S labels;
+ template<class R, class N>
+ R apply(N n) const {
+ return(impl(n));
+ }
+private:
+ F impl;
+};
+
+template<class F>
+struct add_to_group {
+ template<class Prev, class Current>
+ struct apply {
+ typedef binary_case_t<Prev, single_case_t<Current, F> > type;
+ };
+};
+
+class empty_case {
+public:
+ template<class T>
+ explicit empty_case(T&) {}
+ typedef mpl::vector0<> labels;
+ void apply();
+};
+
+template<class S, class F>
+struct make_case_group {
+ typedef typename mpl::fold<S, empty_case, add_to_group<F> >::type type;
+};
+
+template<class Case>
+class expression_template_case_t {
+public:
+ typedef typename Case::labels labels;
+ template<class T>
+ explicit expression_template_case_t(T& t) : impl(t) {}
+ template<class T0, class T1>
+ expression_template_case_t(T0& t0, T1& t1) : impl(t0, t1) {}
+ template<class R, class N>
+ R apply(N n) const {
+ return(impl.template apply<R>(n));
+ }
+ Case& get() { return(impl); }
+ const Case& get() const { return(impl); }
+private:
+ Case impl;
+};
+
+template<class Case>
+expression_template_case_t<restrict_case_t<Case> > restrict_case(Case& c) {
+ return(expression_template_case_t<restrict_case_t<Case> >(c));
+}
+
+template<class Case1, class Case2>
+expression_template_case_t<binary_case_t<Case1, Case2> >
+operator,(const expression_template_case_t<Case1>& c1,
+ const expression_template_case_t<Case2>& c2) {
+ return(expression_template_case_t<binary_case_t<Case1, Case2> >(
+ c1.get(), c2.get()));
+}
+
+template<class S, class F>
+expression_template_case_t<restrict_case_t<case_group_t<S,F> > > case_(F f) {
+ return(expression_template_case_t<restrict_case_t<case_group_t<S,F> > >(f));
+}
+
+//template<class S, class F>
+//expression_template_case_t<typename make_case_group<S, F>::type> case_(F f) {
+// return(expression_template_case_t<typename make_case_group<S,F>::type>(f));
+//}
+
+template<int N, class F>
+expression_template_case_t<single_case_t<mpl::int_<N>, F> > case_c(F f) {
+ return(expression_template_case_t<single_case_t<mpl::int_<N>, F> >(f));
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/fusion.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/fusion.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,207 @@
+// fusion.hpp
+//
+// Copyright (c) 2008
+// 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_FUSION_HPP_INCLUDED
+#define BOOST_SWITCH_FUSION_HPP_INCLUDED
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/fusion/sequence/intrinsic/size.hpp>
+#include <boost/fusion/sequence/intrinsic/begin.hpp>
+#include <boost/fusion/iterator/next.hpp>
+#include <boost/fusion/iterator/deref.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+
+namespace boost {
+
+template<class S>
+class fusion_case_t;
+
+namespace switch_detail {
+
+template<int N>
+struct get_nth {
+ template<class Iter>
+ struct apply {
+ typedef typename boost::fusion::result_of::next<
+ typename get_nth<N - 1>::template apply<Iter>::type
+ >::type type;
+ static type call(const Iter& iter) {
+ return(boost::fusion::next(
+ get_nth<N - 1>::template apply<Iter>::call(iter)));
+ }
+ };
+};
+
+template<>
+struct get_nth<0> {
+ template<class Iter>
+ struct apply {
+ typedef Iter type;
+ static Iter call(const Iter& iter) {
+ return(iter);
+ }
+ };
+};
+
+template<class T, class R>
+struct internal_at;
+
+template<class T>
+struct internal_size;
+
+template<class T, class R>
+struct internal_at<fusion_case_t<T>, R> {
+ template<int N>
+ struct apply {
+ typedef typename boost::remove_cv<
+ typename boost::remove_reference<
+ typename boost::fusion::result_of::deref<
+ typename get_nth<N>::template apply<
+ typename boost::fusion::result_of::begin<S>::type
+ >::type
+ >::type
+ >::type
+ >::type f_type;
+ typedef typename f_type::label label;
+ static R call(const fusion_case_t<T>& t) {
+ return(boost::fusion::deref(get_nth<N>::template apply<
+ typename boost::fusion::result_of::begin<S>::type
+ >::call(boost::fusion::begin(t.get_seq())))());
+ }
+ static bool fallthrough() { return(f_type::fallthrough()); }
+ };
+};
+
+template<class T>
+struct internal_size<fusion_case_t<T> > : boost::fusion::result_of::size<T> {};
+
+struct fusion_case_tag {};
+
+template<class It, class End>
+struct fusion_case_iterator {
+ typedef typename boost::remove_cv<
+ typename boost::remove_reference<
+ typename boost::fusion::result_of_deref<It>::type
+ >::type
+ >::type::label type;
+ typedef typename fusion_case_iterator<
+ typename boost::fusion::result_of::next<It>::type, End
+ > next;
+};
+
+template<class End>
+struct fusion_case_iterator<End, End> {};
+
+template<class T>
+struct wrap {};
+
+struct int_map_base {
+ static void lookup();
+};
+
+template<class Key, int Value, class Base>
+struct int_map : Base {
+ static char (&lookup(wrap<Key>))[Value + 1];
+ using Base::lookup;
+};
+
+template<int N>
+struct make_index_map {
+ template<class T, int I>
+ struct apply {
+ typedef int_map<typename mpl::deref<T>::type, I,
+ typename make_index_map<N - 1>::template apply<
+ typename mpl::next<T>::type, I + 1
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct make_index_map<0> {
+ template<class T, int I>
+ struct apply {
+ typedef int_map_base type;
+ };
+};
+
+}
+
+template<class S>
+class fusion_case_t {
+public:
+ struct labels {
+ typedef fusion_case_tag tag;
+ typedef labels type;
+ typedef S impl;
+ };
+ fusion_case_t(S& sequence) : s(sequence) {}
+ S& get_seq() const { return(s); }
+ template<class R, class N>
+ R apply(N) {
+ typedef typename make_index_map<
+ mpl::size<labels>::value
+ >::template apply<typename mpl::begin<labels>::type, 0>::type map;
+ return(switch_detail::internal_at<fusion_case_t, R>::template apply<
+ sizeof(map::lookup(wrap<N>())) - 1
+ >::call());
+ }
+private:
+ S& s;
+};
+
+template<class S>
+fusion_case_t<S> fusion_case(S& s) {
+ return(fusion_case_t<S>(s));
+}
+
+template<class S>
+fusion_case_t<const S> fusion_case(const S& s) {
+ return(fusion_case_t<const S>(s));
+}
+
+namespace mpl {
+
+template<>
+struct size_impl<boost::switch_detail::fusion_case_tag> {
+ template<class T>
+ struct apply : boost::fusion::result_of::size<typename T::impl> {};
+};
+
+template<>
+struct begin_impl<boost::switch_detail::fusion_case_tag> {
+ template<class T>
+ struct apply {
+ typedef boost::switch_detail::fusion_case_iterator<
+ typename boost::fusion::result_of::begin<typename T::impl>::type,
+ typename boost::fusion::result_of::end<typename T::impl>::type
+ > type;
+ };
+};
+
+template<>
+struct end_impl<boost::switch_detail::fusion_case_tag> {
+ template<class T>
+ struct apply {
+ typedef boost::switch_detail::fusion_case_iterator<
+ typename boost::fusion::result_of::end<typename T::impl>::type,
+ typename boost::fusion::result_of::end<typename T::impl>::type
+ > type;
+ };
+};
+
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/if_else.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/if_else.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,53 @@
+// if_else.hpp
+//
+// Copyright (c) 2008
+// 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_IF_ELSE_HPP_INCLUDED
+#define BOOST_SWITCH_IF_ELSE_HPP_INCLUDED
+
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/next.hpp>
+
+namespace boost {
+
+namespace if_else_switch {
+
+template<int N>
+struct switch_impl {
+ template<class R, class Iter, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ if(mpl::deref<Iter>::type::value == i) {
+ typename mpl::deref<Iter>::type x;
+ return(f.template apply<R>(x));
+ } else {
+ return(switch_impl<N - 1>::template apply<R, typename mpl::next<Iter>::type>(i, f, d));
+ }
+ }
+};
+
+template<>
+struct switch_impl<0> {
+ template<class R, class Iter, class I, class F, class D>
+ static R apply(I i, F& f, D& d) {
+ return(d(i));
+ }
+};
+
+template<class R, class I, class F, class D>
+R switch_(I i, const F& f, D d) {
+ typedef switch_impl<mpl::size<typename F::labels>::value> impl;
+ return(impl::template apply<R, typename mpl::begin<typename F::labels>::type>(i, f, d));
+};
+
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/map.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/map.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,74 @@
+// map.hpp
+//
+// 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
+
+#ifndef BOOST_SWITCH_MAP_HPP_INCLUDED
+#define BOOST_SWITCH_MAP_HPP_INCLUDED
+
+#include <map>
+//#include <boost/thread/once.hpp>
+#include <boost/mpl/for_each.hpp>
+
+namespace boost {
+
+namespace map_switch {
+
+template<class R, class I, class F>
+struct switch_impl {
+ static std::map<I, R(*)(const F&)>* impl;
+ //static boost::once_flag init_flag;
+ struct init_impl {
+ init_impl() {
+ init();
+ }
+ };
+ static const std::map<I, R(*)(const F&)>& get() {
+ //boost::call_once(&init, init_flag);
+ static init_impl initialize;
+ return(*impl);
+ }
+ static void init() {
+ impl = new std::map<I, R(*)(const F&)>();
+ boost::mpl::for_each<typename F::labels>(do_init());
+ }
+ struct do_init {
+ template<class T>
+ void operator()(T) {
+ impl->insert(std::make_pair(static_cast<I>(T::value), &f_impl<T>::call));
+ }
+ };
+ template<class T>
+ struct f_impl {
+ static R call(const F& f) {
+ return(f.template apply<R>(T()));
+ }
+ };
+};
+
+template<class R, class I, class F>
+std::map<I, R(*)(const F&)>* switch_impl<R, I, F>::impl;
+//template<class R, class I, class F>
+//boost::once_flag switch_impl<R, I, F>::init_flag = BOOST_ONCE_INIT;
+
+template<class R, class I, class F, class Default>
+R switch_(I i, const F& f, Default default_) {
+ const std::map<I, R(*)(const F&)>& m = switch_impl<R, I, F>::get();
+ typename std::map<I, R(*)(const F&)>::const_iterator iter = m.find(i);
+ if(iter == m.end()) {
+ return(default_(i));
+ } else {
+ return(iter->second(f));
+ }
+}
+
+
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/sorted_array.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/sorted_array.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,96 @@
+// map.hpp
+//
+// 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
+
+#ifndef BOOST_SWITCH_SORTED_ARRAY_HPP_INCLUDED
+#define BOOST_SWITCH_SORTED_ARRAY_HPP_INCLUDED
+
+#include <algorithm>
+//#include <boost/thread/once.hpp>
+#include <boost/mpl/for_each.hpp>
+#include <boost/mpl/range_c.hpp>
+
+namespace boost {
+
+namespace sorted_array_switch {
+
+// requires that K and V are POD
+template<class K, class V>
+struct map_element {
+ K k;
+ V v;
+ bool operator<(const map_element& other) const {
+ return(k < other.k);
+ }
+ bool operator<(const K& other) const {
+ return(k < other);
+ }
+ friend bool operator<(const K& other, const map_element& self) {
+ return(other < self.k);
+ }
+};
+
+template<class R, class I, class F>
+struct switch_impl {
+ static map_element<I, R(*)(const F&)> impl[mpl::size<typename F::labels>::value];
+ //static boost::once_flag init_flag;
+ struct init_impl {
+ init_impl() {
+ init();
+ }
+ };
+ static R (*get(I i))(const F&) {
+ //boost::call_once(&init, init_flag);
+ static init_impl initialize;
+ map_element<I, R(*)(const F&)>* result = std::lower_bound(&impl[0], &impl[0] + mpl::size<typename F::labels>::value, i);
+ if(result == &impl[0] + mpl::size<typename F::labels>::value || result->k != i) {
+ return(0);
+ } else {
+ return(result->v);
+ }
+ }
+ static void init() {
+ boost::mpl::for_each<mpl::range_c<int, 0, mpl::size<typename F::labels>::value> >(do_init());
+ std::sort(&impl[0], &impl[0] + mpl::size<typename F::labels>::value);
+ }
+ struct do_init {
+ template<class T>
+ void operator()(T) {
+ impl[T::value].k = static_cast<I>(mpl::at_c<typename F::labels, T::value>::type::value);
+ impl[T::value].v = &f_impl<typename mpl::at_c<typename F::labels, T::value>::type>::call;
+ }
+ };
+ template<class T>
+ struct f_impl {
+ static R call(const F& f) {
+ return(f.template apply<R>(T()));
+ }
+ };
+};
+
+template<class R, class I, class F>
+map_element<I, R(*)(const F&)> switch_impl<R, I, F>::impl[mpl::size<typename F::labels>::value];
+//template<class R, class I, class F>
+//boost::once_flag switch_impl<R, I, F>::init_flag = BOOST_ONCE_INIT;
+
+template<class R, class I, class F, class Default>
+R switch_(I i, const F& f, Default default_) {
+ R (*impl)(const F&) = switch_impl<R, I, F>::get(i);
+ if(impl == 0) {
+ return(default_(i));
+ } else {
+ return(impl(f));
+ }
+}
+
+
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/switch.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/switch.hpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,128 @@
+// switch.hpp
+//
+// Copyright (c) 2006-2008
+// 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_SWITCH_HPP_INCLUDED
+#define BOOST_SWITCH_SWITCH_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/preprocessor/config/limits.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/iteration/local.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 {
+
+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>
+struct default_construct {
+ template<class Int>
+ R operator()(Int i) const {
+ 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 R, class Int, class S, class Default>
+ static R
+ apply(Int i, S&, Default d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(R)) {
+ return(d(i));
+ }
+};
+
+template<class R, class L, class T>
+R do_call(T& t) {
+ return(t.template apply<R>(L()));
+}
+
+template<class T, class R>
+struct internal_at {
+ template<int N>
+ struct apply {
+ typedef typename mpl::at_c<typename T::labels, N>::type label;
+ static R call(T& t) {
+ return(do_call<R, label>(t));
+ }
+ static bool fallthrough() { return(false); }
+ };
+};
+
+template<class T>
+struct size : mpl::size<typename T::labels> {};
+
+#define BOOST_SWITCH_CASE(z, n, data) \
+ { \
+ typedef typename impl::template apply<n> c; \
+ case c::label::value: \
+ if(!c::fallthrough()) \
+ return(c::call(s)); \
+ else c::call(s); \
+ }
+
+#define BOOST_SWITCH_IMPL(z, n, data) \
+ template<> \
+ struct switch_impl<n> { \
+ template<class R, class I, class S, class D> \
+ static R \
+ apply(I i, S& s, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(R)) { \
+ typedef internal_at<S, R> impl; \
+ switch(i) { \
+ BOOST_PP_REPEAT_##z(n, BOOST_SWITCH_CASE, ~) \
+ 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 R, class N, class S>
+inline R switch_(N n, S s BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(R)) {
+ typedef switch_detail::switch_impl<switch_detail::size<S>::value> impl;
+ switch_detail::default_construct<R> default_;
+ return(impl::template apply<R>(n, s, default_));
+}
+
+template<class R, class N, class S, class D>
+inline R switch_(N n, S s, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(R)) {
+ typedef switch_detail::switch_impl<switch_detail::size<S>::value> impl;
+ return(impl::template apply<R>(n, s, d));
+}
+
+}
+
+#endif

Added: sandbox/switch/libs/switch/alternate/switch/test_case.cpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/test_case.cpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,45 @@
+// test_case.hpp
+//
+// 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)
+
+#define BOOST_AUTO_TEST_MAIN
+
+#include "switch.hpp"
+#include "case.hpp"
+
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/vector_c.hpp>
+
+#include <boost/test/auto_unit_test.hpp>
+
+namespace {
+ struct f {
+ typedef int result_type;
+ template<class T>
+ int operator()(T) const {
+ return(T::value * T::value);
+ }
+ };
+}
+
+BOOST_AUTO_TEST_CASE(test1) {
+ using boost::case_;
+ BOOST_CHECK_EQUAL(boost::switch_<int>(2, (case_<boost::mpl::range_c<int, 0, 5> >(f()))), 4);
+}
+
+BOOST_AUTO_TEST_CASE(test2) {
+ using boost::case_;
+ BOOST_CHECK_EQUAL(boost::switch_<int>(2,
+ (case_<boost::mpl::vector_c<int, 0> >(f()),
+ case_<boost::mpl::vector_c<int, 1> >(f()),
+ case_<boost::mpl::vector_c<int, 2> >(f()),
+ case_<boost::mpl::vector_c<int, 3> >(f()),
+ case_<boost::mpl::vector_c<int, 4> >(f()),
+ case_<boost::mpl::vector_c<int, 5> >(f()))
+ ), 4);
+}

Added: sandbox/switch/libs/switch/alternate/switch/test_speed.cpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/alternate/switch/test_speed.cpp 2008-02-12 18:45:32 EST (Tue, 12 Feb 2008)
@@ -0,0 +1,123 @@
+// test_speed.hpp
+//
+// Copyright (c) 2008
+// 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)
+
+#define BOOST_SWITCH_LIMIT 250
+
+#pragma warning(disable:4307)
+
+#include "if_else.hpp"
+#include "binary_search.hpp"
+#include "switch.hpp"
+#include "map.hpp"
+#include "sorted_array.hpp"
+#include "case.hpp"
+
+#include <iostream>
+
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/transform_view.hpp>
+#include <boost/timer.hpp>
+
+#include <boost/preprocessor/repetition/enum.hpp>
+
+struct test_function {
+ template<class N>
+ int operator()(N) const {
+ return(N::value * N::value);
+ }
+};
+
+struct default_ {
+ int operator()(int) {
+ return(-1);
+ }
+};
+
+int x;
+
+#define CASE(z, n, data) boost::case_c<n * n>(data)
+
+struct square {
+ template<class T>
+ struct apply {
+ typedef boost::mpl::int_<T::value * T::value> type;
+ };
+};
+
+template<class F>
+void do_test(const char* name, F f) {
+
+ std::cout << name << ":\n";
+
+ {
+ boost::timer timer;
+
+ for(int i = 0; i < 100000000; ++i) {
+ x = f(i * 13 % BOOST_SWITCH_LIMIT, boost::case_<boost::mpl::range_c<int, 0, BOOST_SWITCH_LIMIT> >(test_function()), default_());
+ }
+
+ std::cout << "consecutive: " << timer.elapsed() << std::endl;
+ }
+
+ {
+ boost::timer timer;
+
+ for(int i = 0; i < 100000000; ++i) {
+ x = f((i * 13 % BOOST_SWITCH_LIMIT) * (i * 13 % BOOST_SWITCH_LIMIT), boost::case_<boost::mpl::transform_view<boost::mpl::range_c<int, 0, BOOST_SWITCH_LIMIT>, square> >(test_function()), default_());
+ //x = f((i % BOOST_SWITCH_LIMIT) * (i % BOOST_SWITCH_LIMIT), (BOOST_PP_ENUM(BOOST_SWITCH_LIMIT, CASE, test_function())), default_());
+ }
+
+ std::cout << "spread out: " << timer.elapsed() << std::endl;
+
+ }
+
+}
+
+struct test_switch {
+ template<class I, class Case, class Default>
+ int operator()(I i, const Case& case_, const Default& default_) {
+ return(boost::switch_<int>(i, case_, default_));
+ }
+};
+
+struct test_if_else {
+ template<class I, class Case, class Default>
+ int operator()(I i, const Case& case_, const Default& default_) {
+ return(boost::if_else_switch::switch_<int>(i, case_, default_));
+ }
+};
+
+struct test_binary_search {
+ template<class I, class Case, class Default>
+ int operator()(I i, const Case& case_, const Default& default_) {
+ return(boost::binary_search_switch::switch_<int>(i, case_, default_));
+ }
+};
+
+struct test_map {
+ template<class I, class Case, class Default>
+ int operator()(I i, const Case& case_, const Default& default_) {
+ return(boost::map_switch::switch_<int>(i, case_, default_));
+ }
+};
+
+struct test_sorted_array {
+ template<class I, class Case, class Default>
+ int operator()(I i, const Case& case_, const Default& default_) {
+ return(boost::sorted_array_switch::switch_<int>(i, case_, default_));
+ }
+};
+
+int main() {
+ do_test("switch", test_switch());
+ do_test("if/else", test_if_else());
+ do_test("binary_search", test_binary_search());
+ do_test("std::map", test_map());
+ do_test("sorted_array", test_sorted_array());
+}


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