| // Copyright (c) 2001-2010 Hartmut Kaiser |
| // |
| // 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(BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM) |
| #define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM |
| |
| #include <boost/config.hpp> |
| #include <boost/type_traits/is_empty.hpp> |
| |
| namespace boost { namespace spirit { namespace iterator_policies |
| { |
| /////////////////////////////////////////////////////////////////////////// |
| // The purpose of the multi_pass_unique template is to eliminate |
| // empty policy classes (policies not containing any data items) from the |
| // multiple inheritance chain. This is necessary since some compilers |
| // fail to apply the empty base optimization if multiple inheritance is |
| // involved. |
| // Additionally this can be used to combine separate policies into one |
| // single multi_pass_policy as required by the multi_pass template |
| /////////////////////////////////////////////////////////////////////////// |
| |
| #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) |
| // without partial template specialization there is nothing much to do in |
| // terms of empty base optimization anyways... |
| template <typename T, typename Ownership, typename Checking, |
| typename Input, typename Storage> |
| struct multi_pass_unique |
| : Ownership, Checking, Input, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T& x) : Input(x) {} |
| multi_pass_unique(T const& x) : Input(x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Ownership::destroy(mp); |
| Checking::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Ownership::swap(x); |
| this->Checking::swap(x); |
| this->Input::swap(x); |
| this->Storage::swap(x); |
| } |
| }; |
| #else |
| /////////////////////////////////////////////////////////////////////////// |
| // select the correct derived classes based on if a policy is empty |
| template <typename T |
| , typename Ownership, typename Checking, typename Input, typename Storage |
| , bool OwnershipIsEmpty = boost::is_empty<Ownership>::value |
| , bool CheckingIsEmpty = boost::is_empty<Checking>::value |
| , bool InputIsEmpty = boost::is_empty<Input>::value> |
| struct multi_pass_unique; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , false, false, false> |
| : Ownership, Checking, Input, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T& x) : Input(x) {} |
| multi_pass_unique(T const& x) : Input(x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Ownership::destroy(mp); |
| Checking::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Ownership::swap(x); |
| this->Checking::swap(x); |
| this->Input::swap(x); |
| this->Storage::swap(x); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , false, false, true> |
| : Ownership, Checking, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T const& x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Ownership::destroy(mp); |
| Checking::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Ownership::swap(x); |
| this->Checking::swap(x); |
| this->Storage::swap(x); |
| } |
| |
| // implement input policy functions by forwarding to the Input type |
| template <typename MultiPass> |
| inline static void advance_input(MultiPass& mp) |
| { Input::advance_input(mp); } |
| |
| template <typename MultiPass> |
| inline static typename MultiPass::reference get_input(MultiPass& mp) |
| { return Input::get_input(mp); } |
| |
| template <typename MultiPass> |
| inline static bool input_at_eof(MultiPass const& mp) |
| { return Input::input_at_eof(mp); } |
| |
| template <typename MultiPass, typename TokenType> |
| inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) |
| { return Input::input_is_valid(mp, curtok); } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , false, true, false> |
| : Ownership, Input, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T& x) : Input(x) {} |
| multi_pass_unique(T const& x) : Input(x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Ownership::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Ownership::swap(x); |
| this->Input::swap(x); |
| this->Storage::swap(x); |
| } |
| |
| // checking policy functions are forwarded to the Checking type |
| template <typename MultiPass> |
| inline static void docheck(MultiPass const& mp) |
| { Checking::docheck(mp); } |
| |
| template <typename MultiPass> |
| inline static void clear_queue(MultiPass& mp) |
| { Checking::clear_queue(mp); } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , false, true, true> |
| : Ownership, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T const& x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Ownership::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Ownership::swap(x); |
| this->Storage::swap(x); |
| } |
| |
| // implement input policy functions by forwarding to the Input type |
| template <typename MultiPass> |
| inline static void advance_input(MultiPass& mp) |
| { Input::advance_input(mp); } |
| |
| template <typename MultiPass> |
| inline static typename MultiPass::reference get_input(MultiPass& mp) |
| { return Input::get_input(mp); } |
| |
| template <typename MultiPass> |
| inline static bool input_at_eof(MultiPass const& mp) |
| { return Input::input_at_eof(mp); } |
| |
| template <typename MultiPass, typename TokenType> |
| inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) |
| { return Input::input_is_valid(mp, curtok); } |
| |
| // checking policy functions are forwarded to the Checking type |
| template <typename MultiPass> |
| inline static void docheck(MultiPass const& mp) |
| { Checking::docheck(mp); } |
| |
| template <typename MultiPass> |
| inline static void clear_queue(MultiPass& mp) |
| { Checking::clear_queue(mp); } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , true, false, false> |
| : Checking, Input, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T& x) : Input(x) {} |
| multi_pass_unique(T const& x) : Input(x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Checking::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Checking::swap(x); |
| this->Input::swap(x); |
| this->Storage::swap(x); |
| } |
| |
| // ownership policy functions are forwarded to the Ownership type |
| template <typename MultiPass> |
| inline static void clone(MultiPass& mp) |
| { Ownership::clone(mp); } |
| |
| template <typename MultiPass> |
| inline static bool release(MultiPass& mp) |
| { return Ownership::release(mp); } |
| |
| template <typename MultiPass> |
| inline static bool is_unique(MultiPass const& mp) |
| { return Ownership::is_unique(mp); } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , true, false, true> |
| : Checking, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T const& x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Checking::destroy(mp); |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Checking::swap(x); |
| this->Storage::swap(x); |
| } |
| |
| // implement input policy functions by forwarding to the Input type |
| template <typename MultiPass> |
| inline static void advance_input(MultiPass& mp) |
| { Input::advance_input(mp); } |
| |
| template <typename MultiPass> |
| inline static typename MultiPass::reference get_input(MultiPass& mp) |
| { return Input::get_input(mp); } |
| |
| template <typename MultiPass> |
| inline static bool input_at_eof(MultiPass const& mp) |
| { return Input::input_at_eof(mp); } |
| |
| template <typename MultiPass, typename TokenType> |
| inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) |
| { return Input::input_is_valid(mp, curtok); } |
| |
| // ownership policy functions are forwarded to the Ownership type |
| template <typename MultiPass> |
| inline static void clone(MultiPass& mp) |
| { Ownership::clone(mp); } |
| |
| template <typename MultiPass> |
| inline static bool release(MultiPass& mp) |
| { return Ownership::release(mp); } |
| |
| template <typename MultiPass> |
| inline static bool is_unique(MultiPass const& mp) |
| { return Ownership::is_unique(mp); } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , true, true, false> |
| : Input, Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T& x) : Input(x) {} |
| multi_pass_unique(T const& x) : Input(x) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Input::swap(x); |
| this->Storage::swap(x); |
| } |
| |
| // checking policy functions are forwarded to the Checking type |
| template <typename MultiPass> |
| inline static void docheck(MultiPass const& mp) |
| { Checking::docheck(mp); } |
| |
| template <typename MultiPass> |
| inline static void clear_queue(MultiPass& mp) |
| { Checking::clear_queue(mp); } |
| |
| // ownership policy functions are forwarded to the Ownership type |
| template <typename MultiPass> |
| inline static void clone(MultiPass& mp) |
| { Ownership::clone(mp); } |
| |
| template <typename MultiPass> |
| inline static bool release(MultiPass& mp) |
| { return Ownership::release(mp); } |
| |
| template <typename MultiPass> |
| inline static bool is_unique(MultiPass const& mp) |
| { return Ownership::is_unique(mp); } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename T, typename Ownership, typename Checking |
| , typename Input, typename Storage> |
| struct multi_pass_unique<T, Ownership, Checking, Input, Storage |
| , true, true, true> |
| : Storage |
| { |
| multi_pass_unique() {} |
| multi_pass_unique(T const&) {} |
| |
| template <typename MultiPass> |
| static void destroy(MultiPass& mp) |
| { |
| Input::destroy(mp); |
| Storage::destroy(mp); |
| } |
| void swap(multi_pass_unique& x) |
| { |
| this->Storage::swap(x); |
| } |
| |
| // implement input policy functions by forwarding to the Input type |
| template <typename MultiPass> |
| inline static void advance_input(MultiPass& mp) |
| { Input::advance_input(mp); } |
| |
| template <typename MultiPass> |
| inline static typename MultiPass::reference get_input(MultiPass& mp) |
| { return Input::get_input(mp); } |
| |
| template <typename MultiPass> |
| inline static bool input_at_eof(MultiPass const& mp) |
| { return Input::input_at_eof(mp); } |
| |
| template <typename MultiPass, typename TokenType> |
| inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) |
| { return Input::input_is_valid(mp, curtok); } |
| |
| // checking policy functions are forwarded to the Checking type |
| template <typename MultiPass> |
| inline static void docheck(MultiPass const& mp) |
| { Checking::docheck(mp); } |
| |
| template <typename MultiPass> |
| inline static void clear_queue(MultiPass& mp) |
| { Checking::clear_queue(mp); } |
| |
| // ownership policy functions are forwarded to the Ownership type |
| template <typename MultiPass> |
| inline static void clone(MultiPass& mp) |
| { Ownership::clone(mp); } |
| |
| template <typename MultiPass> |
| inline static bool release(MultiPass& mp) |
| { return Ownership::release(mp); } |
| |
| template <typename MultiPass> |
| inline static bool is_unique(MultiPass const& mp) |
| { return Ownership::is_unique(mp); } |
| }; |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // the multi_pass_shared structure is used to combine the shared data items |
| // of all policies into one single structure |
| /////////////////////////////////////////////////////////////////////////// |
| template<typename T, typename Ownership, typename Checking, typename Input |
| , typename Storage> |
| struct multi_pass_shared : Ownership, Checking, Input, Storage |
| { |
| explicit multi_pass_shared(T& input) : Input(input) {} |
| explicit multi_pass_shared(T const& input) : Input(input) {} |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // This is a default implementation of a policy class as required by the |
| // multi_pass template, combining 4 separate policies into one. Any other |
| // multi_pass policy class needs to follow the scheme as shown below. |
| template<typename Ownership, typename Checking, typename Input |
| , typename Storage> |
| struct default_policy |
| { |
| typedef Ownership ownership_policy; |
| typedef Checking checking_policy; |
| typedef Input input_policy; |
| typedef Storage storage_policy; |
| |
| /////////////////////////////////////////////////////////////////////// |
| template <typename T> |
| struct unique : multi_pass_unique<T |
| , typename Ownership::unique, typename Checking::unique |
| , typename Input::BOOST_NESTED_TEMPLATE unique<T> |
| , typename Storage::BOOST_NESTED_TEMPLATE unique< |
| typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> > |
| { |
| typedef typename Ownership::unique ownership_policy; |
| typedef typename Checking::unique checking_policy; |
| typedef typename Input::BOOST_NESTED_TEMPLATE unique<T> |
| input_policy; |
| typedef typename Storage::BOOST_NESTED_TEMPLATE unique< |
| typename input_policy::value_type> storage_policy; |
| |
| typedef multi_pass_unique<T, ownership_policy, checking_policy |
| , input_policy, storage_policy> unique_base_type; |
| |
| unique() {} |
| explicit unique(T& input) : unique_base_type(input) {} |
| explicit unique(T const& input) : unique_base_type(input) {} |
| }; |
| |
| /////////////////////////////////////////////////////////////////////// |
| template <typename T> |
| struct shared : multi_pass_shared<T |
| , typename Ownership::shared, typename Checking::shared |
| , typename Input::BOOST_NESTED_TEMPLATE shared<T> |
| , typename Storage::BOOST_NESTED_TEMPLATE shared< |
| typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> > |
| { |
| typedef typename Ownership::shared ownership_policy; |
| typedef typename Checking::shared checking_policy; |
| typedef typename Input::BOOST_NESTED_TEMPLATE shared<T> |
| input_policy; |
| typedef typename Storage::BOOST_NESTED_TEMPLATE shared< |
| typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> |
| storage_policy; |
| |
| typedef multi_pass_shared<T, ownership_policy, checking_policy |
| , input_policy, storage_policy> shared_base_type; |
| |
| explicit shared(T& input) |
| : shared_base_type(input), inhibit_clear_queue_(false) {} |
| explicit shared(T const& input) |
| : shared_base_type(input), inhibit_clear_queue_(false) {} |
| |
| // This is needed for the correct implementation of expectation |
| // points. Normally expectation points flush any multi_pass |
| // iterator they may act on, but if the corresponding error handler |
| // is of type 'retry' no flushing of the internal buffers should be |
| // executed (even if explicitly requested). |
| bool inhibit_clear_queue_; |
| }; |
| }; |
| |
| }}} |
| |
| #endif |