📄 alternative.hpp
字号:
// Copyright (c) 2001-2008 Hartmut Kaiser// 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)#if !defined(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM#if defined(_MSC_VER) && (_MSC_VER >= 1020)#pragma once // MS compatible compilers support #pragma once#endif#include <boost/spirit/home/support/unused.hpp>#include <boost/spirit/home/support/attribute_of.hpp>#include <boost/spirit/home/karma/domain.hpp>#include <boost/utility/enable_if.hpp>#include <boost/mpl/find_if.hpp>#include <boost/mpl/deref.hpp>#include <boost/mpl/distance.hpp>#include <boost/type_traits/is_same.hpp>#include <boost/type_traits/is_convertible.hpp>#include <boost/variant.hpp>namespace boost { namespace spirit { namespace karma { /////////////////////////////////////////////////////////////////////////// struct sequence; // forward declaration only namespace detail{ /////////////////////////////////////////////////////////////////////////// // A component is compatible to a given parameter type if the parameter // is the same as the expected type of the component /////////////////////////////////////////////////////////////////////////// template <typename Expected, typename Parameter> struct compute_compatible_component { typedef typename Parameter::types types; typedef typename mpl::end<types>::type end; typedef typename mpl::begin<types>::type begin; typedef typename mpl::find_if<types, is_same<mpl::_1, Expected> >::type iter; typedef typename mpl::not_<is_same<iter, end> >::type type; enum { value = type::value }; }; template <typename Expected> struct compute_compatible_component<Expected, unused_type> : mpl::false_ {}; /////////////////////////////////////////////////////////////////////////// // execute a generator if the given parameter type is compatible /////////////////////////////////////////////////////////////////////////// // this get's instantiated if the parameter type is _not_ compatible with // the generator template <typename Component, typename Parameter, typename Expected, typename Enable = void> struct alternative_generate { template <typename OutputIterator, typename Context, typename Delimiter> static bool call(Component const&, OutputIterator&, Context&, Delimiter const&, Parameter const&) { return false; } }; template <typename Component> struct alternative_generate<Component, unused_type, unused_type> { template <typename OutputIterator, typename Context, typename Delimiter> static bool call(Component const& component, OutputIterator& sink, Context& ctx, Delimiter const& delim, unused_type const&) { // return true if any of the generators succeed typedef typename Component::director director; return director::generate(component, sink, ctx, delim, unused); } }; // this get's instantiated if there is no parameter given for the // alternative generator template <typename Component, typename Expected> struct alternative_generate<Component, unused_type, Expected> : alternative_generate<Component, unused_type, unused_type> {}; // this get's instantiated if the generator does not expect to receive a // parameter (the generator is self contained). template <typename Component, typename Parameter> struct alternative_generate<Component, Parameter, unused_type> : alternative_generate<Component, unused_type, unused_type> {}; // this get's instantiated if the parameter type is compatible to the // generator template <typename Component, typename Parameter, typename Expected> struct alternative_generate< Component, Parameter, Expected, typename enable_if< compute_compatible_component<Expected, Parameter> >::type > { // If this alternative is a sequence, we wrap the attribute into a // fusion sequence. template <typename Parameter_> static fusion::vector<Parameter_ const&> wrap_attribute(Parameter_ const& param, mpl::true_) { return fusion::vector<Parameter const&>(param); } // If this alternative is not a sequence the parameter is passed // through unchanged. template <typename Parameter_> static Parameter_ const& wrap_attribute(Parameter_ const& param, mpl::false_) { return param; } template <typename OutputIterator, typename Context, typename Delimiter> static bool call(Component const& component, OutputIterator& sink, Context& ctx, Delimiter const& delim, Parameter const& param) { typedef compute_compatible_component<Expected, Parameter> component_type; typedef typename mpl::distance< typename component_type::begin, typename component_type::iter >::type distance_type; // make sure, the content of the passed variant matches our // expectations if (param.which() != distance_type::value) return false; // returns true if any of the generators succeed typedef typename mpl::deref< typename component_type::iter >::type compatible_type; typedef typename Component::director director; typedef typename is_same<director, sequence>::type is_sequence; return director::generate(component, sink, ctx, delim, wrap_attribute(get<compatible_type>(param), is_sequence())); } }; /////////////////////////////////////////////////////////////////////////// // alternative_generate_functor: a functor supplied to spirit::any which // will be executed for every generator in a given alternative generator // expression /////////////////////////////////////////////////////////////////////////// template <typename OutputIterator, typename Context, typename Delimiter, typename Parameter> struct alternative_generate_functor { alternative_generate_functor(OutputIterator& sink_, Context& ctx_, Delimiter const& d, Parameter const& p) : sink(sink_), ctx(ctx_), delim(d), param(p) { } template <typename Component> bool operator()(Component const& component) { typedef typename traits::attribute_of< karma::domain, Component, Context>::type expected; typedef alternative_generate<Component, Parameter, expected> generate; return generate::call(component, sink, ctx, delim, param); } OutputIterator& sink; Context& ctx; Delimiter const& delim; Parameter const& param; };}}}}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -