You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
172 lines
5.2 KiB
172 lines
5.2 KiB
/*============================================================================= |
|
Copyright (c) 2001-2007 Joel de Guzman |
|
|
|
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 PHOENIX_STATEMENT_DETAIL_SWITCH_HPP |
|
#define PHOENIX_STATEMENT_DETAIL_SWITCH_HPP |
|
|
|
#include <boost/spirit/home/phoenix/core/nothing.hpp> |
|
#include <boost/fusion/include/vector.hpp> |
|
#include <boost/fusion/include/as_vector.hpp> |
|
#include <boost/fusion/include/push_back.hpp> |
|
#include <boost/fusion/include/push_front.hpp> |
|
#include <boost/fusion/include/begin.hpp> |
|
#include <boost/fusion/include/size.hpp> |
|
#include <boost/fusion/include/value_of.hpp> |
|
#include <boost/fusion/include/is_sequence.hpp> |
|
#include <boost/mpl/identity.hpp> |
|
#include <boost/mpl/bool.hpp> |
|
#include <boost/mpl/eval_if.hpp> |
|
#include <boost/mpl/if.hpp> |
|
|
|
namespace boost { namespace phoenix |
|
{ |
|
|
|
template <typename Actor, typename K, K Value> |
|
struct switch_case; |
|
|
|
template <typename Actor> |
|
struct default_case; |
|
|
|
namespace detail |
|
{ |
|
template <typename T> |
|
struct is_default_case : mpl::bool_<T::is_default> {}; |
|
|
|
template <typename A0, typename A1> |
|
struct compose_case_a |
|
{ |
|
// here, A0 and A1 are both switch cases |
|
typedef typename |
|
mpl::if_< |
|
is_default_case<A1> |
|
, fusion::vector<actor<A1>, actor<A0> > |
|
, fusion::vector<actor<A0>, actor<A1> > |
|
>::type |
|
type; |
|
|
|
static type |
|
eval(A0 const& _0, A1 const& _1, mpl::false_) |
|
{ |
|
return type(_0, _1); |
|
} |
|
|
|
static type |
|
eval(A0 const& _0, A1 const& _1, mpl::true_) |
|
{ |
|
return type(_1, _0); |
|
} |
|
|
|
static type |
|
eval(A0 const& _0, A1 const& _1) |
|
{ |
|
return eval(_0, _1, is_default_case<A1>()); |
|
} |
|
}; |
|
|
|
template <typename Seq, typename Case> |
|
struct compose_case_b |
|
{ |
|
typedef typename fusion::result_of::as_vector< |
|
typename mpl::eval_if< |
|
is_default_case<Case> |
|
, fusion::result_of::push_front<Seq const, actor<Case> > |
|
, fusion::result_of::push_back<Seq const, actor<Case> > |
|
>::type>::type |
|
type; |
|
|
|
static type |
|
eval(Seq const& seq, Case const& case_, mpl::false_) |
|
{ |
|
return fusion::as_vector( |
|
fusion::push_back(seq, actor<Case>(case_))); |
|
} |
|
|
|
static type |
|
eval(Seq const& seq, Case const& case_, mpl::true_) |
|
{ |
|
return fusion::as_vector( |
|
fusion::push_front(seq, actor<Case>(case_))); |
|
} |
|
|
|
static type |
|
eval(Seq const& seq, Case const& case_) |
|
{ |
|
return eval(seq, case_, is_default_case<Case>()); |
|
} |
|
}; |
|
|
|
template <typename Cases> |
|
struct ensure_default |
|
{ |
|
typedef |
|
is_default_case< |
|
typename fusion::result_of::value_of< |
|
typename fusion::result_of::begin<Cases>::type |
|
>::type |
|
> |
|
is_default_case_; |
|
|
|
typedef typename |
|
mpl::eval_if< |
|
is_default_case_ |
|
, mpl::identity<Cases> |
|
, fusion::result_of::push_front< |
|
Cases const, actor<default_case<actor<null_actor> > > > |
|
>::type |
|
type; |
|
|
|
static type |
|
eval(Cases const& cases, mpl::false_); |
|
|
|
static type |
|
eval(Cases const& cases, mpl::true_) |
|
{ |
|
return cases; |
|
} |
|
|
|
static type |
|
eval(Cases const& cases) |
|
{ |
|
return eval(cases, is_default_case_()); |
|
} |
|
}; |
|
|
|
template <typename Cond, typename Cases> |
|
struct switch_composite |
|
{ |
|
BOOST_STATIC_ASSERT(fusion::traits::is_sequence<Cases>::value); |
|
typedef ensure_default<Cases> ensure_default_; |
|
|
|
typedef typename |
|
fusion::result_of::as_vector< |
|
typename fusion::result_of::push_front< |
|
typename ensure_default_::type, Cond>::type |
|
>::type |
|
tuple_type; |
|
|
|
typedef |
|
composite< |
|
detail::switch_eval<fusion::result_of::size<tuple_type>::value-2> |
|
, tuple_type> |
|
type; |
|
|
|
static type |
|
eval(Cond const& cond, Cases const& cases) |
|
{ |
|
return fusion::as_vector( |
|
fusion::push_front(ensure_default_::eval(cases), cond)); |
|
} |
|
}; |
|
|
|
template <typename Cond, typename Cases> |
|
struct switch_composite_actor |
|
{ |
|
typedef actor<typename switch_composite<Cond, Cases>::type> type; |
|
}; |
|
} |
|
}} |
|
|
|
#endif
|
|
|