EVOLUTION-MANAGER
Edit File: attributes.hpp
/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2001-2012 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_ATTRIBUTES_JANUARY_29_2007_0954AM) #define BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM #if defined(_MSC_VER) #pragma once #endif #include <boost/spirit/home/support/unused.hpp> #include <boost/spirit/home/support/has_semantic_action.hpp> #include <boost/spirit/home/support/attributes_fwd.hpp> #include <boost/spirit/home/support/container.hpp> #include <boost/spirit/home/support/detail/hold_any.hpp> #include <boost/spirit/home/support/detail/as_variant.hpp> #include <boost/optional/optional.hpp> #include <boost/fusion/include/transform.hpp> #include <boost/fusion/include/filter_if.hpp> #include <boost/fusion/include/as_vector.hpp> #include <boost/fusion/include/push_front.hpp> #include <boost/fusion/include/pop_front.hpp> #include <boost/fusion/include/is_sequence.hpp> #include <boost/fusion/include/for_each.hpp> #include <boost/fusion/include/is_view.hpp> #include <boost/fusion/include/mpl.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_reference.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/end.hpp> #include <boost/mpl/find_if.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/deref.hpp> #include <boost/mpl/distance.hpp> #include <boost/mpl/or.hpp> #include <boost/mpl/has_xxx.hpp> #include <boost/mpl/equal.hpp> #include <boost/proto/proto_fwd.hpp> #include <boost/utility/enable_if.hpp> #include <boost/variant.hpp> #include <boost/range/iterator_range.hpp> #include <boost/config.hpp> #include <iterator> // for std::iterator_traits, std::distance #include <vector> #include <utility> #include <ios> /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace traits { /////////////////////////////////////////////////////////////////////////// // This file deals with attribute related functions and meta-functions // including generalized attribute transformation utilities for Spirit // components. /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Find out if T can be a (strong) substitute for Expected attribute namespace detail { template <typename T, typename Expected> struct value_type_is_substitute : is_substitute< typename container_value<T>::type , typename container_value<Expected>::type> {}; template <typename T, typename Expected, typename Enable = void> struct is_substitute_impl : is_same<T, Expected> {}; template <typename T, typename Expected> struct is_substitute_impl<T, Expected, typename enable_if< mpl::and_< fusion::traits::is_sequence<T>, fusion::traits::is_sequence<Expected>, mpl::equal<T, Expected, is_substitute<mpl::_1, mpl::_2> > > >::type> : mpl::true_ {}; template <typename T, typename Expected> struct is_substitute_impl<T, Expected, typename enable_if< mpl::and_< is_container<T>, is_container<Expected>, detail::value_type_is_substitute<T, Expected> > >::type> : mpl::true_ {}; } template <typename T, typename Expected, typename Enable /*= void*/> struct is_substitute : detail::is_substitute_impl<T, Expected> {}; template <typename T, typename Expected> struct is_substitute<optional<T>, optional<Expected> > : is_substitute<T, Expected> {}; template <typename T> struct is_substitute<T, T , typename enable_if<not_is_optional<T> >::type> : mpl::true_ {}; /////////////////////////////////////////////////////////////////////////// // Find out if T can be a weak substitute for Expected attribute namespace detail { // A type, which is convertible to the attribute is at the same time // usable as its weak substitute. template <typename T, typename Expected, typename Enable = void> struct is_weak_substitute_impl : is_convertible<T, Expected> {}; // // An exposed attribute is a weak substitute for a supplied container // // attribute if it is a weak substitute for its value_type. This is // // true as all character parsers are compatible with a container // // attribute having the corresponding character type as its value_type. // template <typename T, typename Expected> // struct is_weak_substitute_for_value_type // : is_weak_substitute<T, typename container_value<Expected>::type> // {}; // // template <typename T, typename Expected> // struct is_weak_substitute_impl<T, Expected, // typename enable_if< // mpl::and_< // mpl::not_<is_string<T> > // , is_string<Expected> // , is_weak_substitute_for_value_type<T, Expected> > // >::type> // : mpl::true_ // {}; // An exposed container attribute is a weak substitute for a supplied // container attribute if and only if their value_types are weak // substitutes. template <typename T, typename Expected> struct value_type_is_weak_substitute : is_weak_substitute< typename container_value<T>::type , typename container_value<Expected>::type> {}; template <typename T, typename Expected> struct is_weak_substitute_impl<T, Expected, typename enable_if< mpl::and_< is_container<T> , is_container<Expected> , value_type_is_weak_substitute<T, Expected> > >::type> : mpl::true_ {}; // Two fusion sequences are weak substitutes if and only if their // elements are pairwise weak substitutes. template <typename T, typename Expected> struct is_weak_substitute_impl<T, Expected, typename enable_if< mpl::and_< fusion::traits::is_sequence<T> , fusion::traits::is_sequence<Expected> , mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > > >::type> : mpl::true_ {}; // If this is not defined, the main template definition above will return // true if T is convertible to the first type in a fusion::vector. We // globally declare any non-Fusion sequence T as not compatible with any // Fusion sequence 'Expected'. template <typename T, typename Expected> struct is_weak_substitute_impl<T, Expected, typename enable_if< mpl::and_< mpl::not_<fusion::traits::is_sequence<T> > , fusion::traits::is_sequence<Expected> > >::type> : mpl::false_ {}; } // main template forwards to detail namespace, this helps older compilers // to disambiguate things template <typename T, typename Expected, typename Enable /*= void*/> struct is_weak_substitute : detail::is_weak_substitute_impl<T, Expected> {}; template <typename T, typename Expected> struct is_weak_substitute<optional<T>, optional<Expected> > : is_weak_substitute<T, Expected> {}; template <typename T, typename Expected> struct is_weak_substitute<optional<T>, Expected> : is_weak_substitute<T, Expected> {}; template <typename T, typename Expected> struct is_weak_substitute<T, optional<Expected> > : is_weak_substitute<T, Expected> {}; #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) template <typename T, typename Expected> struct is_weak_substitute<boost::variant<T>, Expected> : is_weak_substitute<T, Expected> {}; template <typename T0, typename T1, typename ...TN, typename Expected> struct is_weak_substitute<boost::variant<T0, T1, TN...>, Expected> : mpl::bool_<is_weak_substitute<T0, Expected>::type::value && is_weak_substitute<boost::variant<T1, TN...>, Expected>::type::value> {}; #else #define BOOST_SPIRIT_IS_WEAK_SUBSTITUTE(z, N, _) \ is_weak_substitute<BOOST_PP_CAT(T, N), Expected>::type::value && \ /***/ // make sure unused variant parameters do not affect the outcome template <typename Expected> struct is_weak_substitute<boost::detail::variant::void_, Expected> : mpl::true_ {}; template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Expected> struct is_weak_substitute< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Expected> : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES , BOOST_SPIRIT_IS_WEAK_SUBSTITUTE, _) true> {}; #undef BOOST_SPIRIT_IS_WEAK_SUBSTITUTE #endif template <typename T> struct is_weak_substitute<T, T , typename enable_if< mpl::and_<not_is_optional<T>, not_is_variant<T> > >::type> : mpl::true_ {}; /////////////////////////////////////////////////////////////////////////// template <typename T, typename Enable/* = void*/> struct is_proxy : mpl::false_ {}; template <typename T> struct is_proxy<T, typename enable_if< mpl::and_< fusion::traits::is_sequence<T>, fusion::traits::is_view<T> > >::type> : mpl::true_ {}; namespace detail { // By declaring a nested struct in your class/struct, you tell // spirit that it is regarded as a variant type. The minimum // required interface for such a variant is that it has constructors // for various types supported by your variant and a typedef 'types' // which is an mpl sequence of the contained types. // // This is an intrusive interface. For a non-intrusive interface, // use the not_is_variant trait. BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag) } template <typename T, typename Domain, typename Enable/* = void*/> struct not_is_variant : mpl::not_<detail::has_adapted_variant_tag<T> > {}; template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Domain> struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Domain> : mpl::false_ {}; // we treat every type as if it where the variant (as this meta function is // invoked for variant types only) template <typename T> struct variant_type : mpl::identity<T> {}; template <typename T> struct variant_type<boost::optional<T> > : variant_type<T> {}; template <typename T, typename Domain> struct not_is_variant_or_variant_in_optional : not_is_variant<typename variant_type<T>::type, Domain> {}; /////////////////////////////////////////////////////////////////////////// // The compute_compatible_component_variant /////////////////////////////////////////////////////////////////////////// namespace detail { // A component is compatible to a given Attribute type if the // Attribute is the same as the expected type of the component or if // it is convertible to the expected type. template <typename Expected, typename Attribute> struct attribute_is_compatible : is_convertible<Attribute, Expected> {}; template <typename Expected, typename Attribute> struct attribute_is_compatible<Expected, boost::optional<Attribute> > : is_convertible<Attribute, Expected> {}; template <typename Container> struct is_hold_any_container : traits::is_hold_any<typename traits::container_value<Container>::type> {}; } template <typename Attribute, typename Expected , typename IsNotVariant = mpl::false_, typename Enable = void> struct compute_compatible_component_variant : mpl::or_< traits::detail::attribute_is_compatible<Expected, Attribute> , traits::is_hold_any<Expected> , mpl::eval_if< is_container<Expected> , traits::detail::is_hold_any_container<Expected> , mpl::false_> > {}; namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(types) } template <typename Variant, typename Expected> struct compute_compatible_component_variant<Variant, Expected, mpl::false_ , typename enable_if<detail::has_types<typename variant_type<Variant>::type> >::type> { typedef typename traits::variant_type<Variant>::type variant_type; typedef typename variant_type::types types; typedef typename mpl::end<types>::type end; typedef typename mpl::find_if<types, is_same<Expected, mpl::_1> >::type iter; typedef typename mpl::distance< typename mpl::begin<types>::type, iter >::type distance; // true_ if the attribute matches one of the types in the variant typedef typename mpl::not_<is_same<iter, end> >::type type; enum { value = type::value }; // return the type in the variant the attribute is compatible with typedef typename mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type compatible_type; // return whether the given type is compatible with the Expected type static bool is_compatible(int which) { return which == distance::value; } }; template <typename Expected, typename Attribute, typename Domain> struct compute_compatible_component : compute_compatible_component_variant<Attribute, Expected , typename not_is_variant_or_variant_in_optional<Attribute, Domain>::type> {}; template <typename Expected, typename Domain> struct compute_compatible_component<Expected, unused_type, Domain> : mpl::false_ {}; template <typename Attribute, typename Domain> struct compute_compatible_component<unused_type, Attribute, Domain> : mpl::false_ {}; template <typename Domain> struct compute_compatible_component<unused_type, unused_type, Domain> : mpl::false_ {}; /////////////////////////////////////////////////////////////////////////// // return the type currently stored in the given variant template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v) { return v.which(); } }; template <typename T> int which(T const& v) { return variant_which<T>::call(v); } /////////////////////////////////////////////////////////////////////////// template <typename T, typename Domain, typename Enable/* = void*/> struct not_is_optional : mpl::true_ {}; template <typename T, typename Domain> struct not_is_optional<boost::optional<T>, Domain> : mpl::false_ {}; /////////////////////////////////////////////////////////////////////////// // attribute_of // // Get the component's attribute /////////////////////////////////////////////////////////////////////////// template <typename Component , typename Context = unused_type, typename Iterator = unused_type> struct attribute_of { typedef typename Component::template attribute<Context, Iterator>::type type; }; /////////////////////////////////////////////////////////////////////////// // attribute_not_unused // // An mpl meta-function class that determines whether a component's // attribute is not unused. /////////////////////////////////////////////////////////////////////////// template <typename Context, typename Iterator = unused_type> struct attribute_not_unused { template <typename Component> struct apply : not_is_unused<typename attribute_of<Component, Context, Iterator>::type> {}; }; /////////////////////////////////////////////////////////////////////////// // Retrieve the attribute type to use from the given type // // This is needed to extract the correct attribute type from proxy classes // as utilized in FUSION_ADAPT_ADT et. al. /////////////////////////////////////////////////////////////////////////// template <typename Attribute, typename Enable/* = void*/> struct attribute_type : mpl::identity<Attribute> {}; /////////////////////////////////////////////////////////////////////////// // Retrieve the size of a fusion sequence (compile time) /////////////////////////////////////////////////////////////////////////// template <typename T> struct sequence_size : fusion::result_of::size<T> {}; template <> struct sequence_size<unused_type> : mpl::int_<0> {}; /////////////////////////////////////////////////////////////////////////// // Retrieve the size of an attribute (runtime) /////////////////////////////////////////////////////////////////////////// namespace detail { template <typename Attribute, typename Enable = void> struct attribute_size_impl { typedef std::size_t type; static type call(Attribute const&) { return 1; } }; template <typename Attribute> struct attribute_size_impl<Attribute , typename enable_if< mpl::and_< fusion::traits::is_sequence<Attribute> , mpl::not_<traits::is_container<Attribute> > > >::type> { typedef typename fusion::result_of::size<Attribute>::value_type type; static type call(Attribute const& attr) { return fusion::size(attr); } }; template <typename Attribute> struct attribute_size_impl<Attribute , typename enable_if< mpl::and_< traits::is_container<Attribute> , mpl::not_<traits::is_iterator_range<Attribute> > > >::type> { typedef typename Attribute::size_type type; static type call(Attribute const& attr) { return attr.size(); } }; } template <typename Attribute, typename Enable/* = void*/> struct attribute_size : detail::attribute_size_impl<Attribute> {}; template <typename Attribute> struct attribute_size<optional<Attribute> > { typedef typename attribute_size<Attribute>::type type; static type call(optional<Attribute> const& val) { if (!val) return 0; return traits::size(val.get()); } }; namespace detail { struct attribute_size_visitor : static_visitor<std::size_t> { template <typename T> std::size_t operator()(T const& val) const { return spirit::traits::size(val); } }; } template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct attribute_size<variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { typedef std::size_t type; static type call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val) { return apply_visitor(detail::attribute_size_visitor(), val); } }; template <typename Iterator> struct attribute_size<iterator_range<Iterator> > { typedef typename std::iterator_traits<Iterator>:: difference_type type; static type call(iterator_range<Iterator> const& r) { return std::distance(r.begin(), r.end()); } }; template <> struct attribute_size<unused_type> { typedef std::size_t type; static type call(unused_type) { return 0; } }; template <typename Attribute> typename attribute_size<Attribute>::type size (Attribute const& attr) { return attribute_size<Attribute>::call(attr); } /////////////////////////////////////////////////////////////////////////// // pass_attribute // // Determines how we pass attributes to semantic actions. This // may be specialized. By default, all attributes are wrapped in // a fusion sequence, because the attribute has to be treated as being // a single value in any case (even if it actually already is a fusion // sequence in its own). /////////////////////////////////////////////////////////////////////////// template <typename Component, typename Attribute, typename Enable/* = void*/> struct pass_attribute { typedef fusion::vector1<Attribute&> type; }; /////////////////////////////////////////////////////////////////////////// // Subclass a pass_attribute specialization from this to wrap // the attribute in a tuple only IFF it is not already a fusion tuple. /////////////////////////////////////////////////////////////////////////// template <typename Attribute, typename Force = mpl::false_> struct wrap_if_not_tuple : mpl::if_< fusion::traits::is_sequence<Attribute> , Attribute&, fusion::vector1<Attribute&> > {}; template <typename Attribute> struct wrap_if_not_tuple<Attribute, mpl::true_> { typedef fusion::vector1<Attribute&> type; }; template <> struct wrap_if_not_tuple<unused_type, mpl::false_> { typedef unused_type type; }; template <> struct wrap_if_not_tuple<unused_type const, mpl::false_> { typedef unused_type type; }; /////////////////////////////////////////////////////////////////////////// // build_optional // // Build a boost::optional from T. Return unused_type if T is unused_type. /////////////////////////////////////////////////////////////////////////// template <typename T> struct build_optional { typedef boost::optional<T> type; }; template <typename T> struct build_optional<boost::optional<T> > { typedef boost::optional<T> type; }; template <> struct build_optional<unused_type> { typedef unused_type type; }; /////////////////////////////////////////////////////////////////////////// // build_std_vector // // Build a std::vector from T. Return unused_type if T is unused_type. /////////////////////////////////////////////////////////////////////////// template <typename T> struct build_std_vector { typedef std::vector<T> type; }; template <> struct build_std_vector<unused_type> { typedef unused_type type; }; /////////////////////////////////////////////////////////////////////////// // filter_unused_attributes // // Remove unused_types from a sequence /////////////////////////////////////////////////////////////////////////// // Compute the list of all *used* attributes of sub-components // (filter all unused attributes from the list) template <typename Sequence> struct filter_unused_attributes : fusion::result_of::filter_if<Sequence, not_is_unused<mpl::_> > {}; /////////////////////////////////////////////////////////////////////////// // sequence_attribute_transform // // This transform is invoked for every attribute in a sequence allowing // to modify the attribute type exposed by a component to the enclosing // sequence component. By default no transformation is performed. /////////////////////////////////////////////////////////////////////////// template <typename Attribute, typename Domain> struct sequence_attribute_transform : mpl::identity<Attribute> {}; /////////////////////////////////////////////////////////////////////////// // permutation_attribute_transform // // This transform is invoked for every attribute in a sequence allowing // to modify the attribute type exposed by a component to the enclosing // permutation component. By default a build_optional transformation is // performed. /////////////////////////////////////////////////////////////////////////// template <typename Attribute, typename Domain> struct permutation_attribute_transform : traits::build_optional<Attribute> {}; /////////////////////////////////////////////////////////////////////////// // sequential_or_attribute_transform // // This transform is invoked for every attribute in a sequential_or allowing // to modify the attribute type exposed by a component to the enclosing // sequential_or component. By default a build_optional transformation is // performed. /////////////////////////////////////////////////////////////////////////// template <typename Attribute, typename Domain> struct sequential_or_attribute_transform : traits::build_optional<Attribute> {}; /////////////////////////////////////////////////////////////////////////// // build_fusion_vector // // Build a fusion vector from a fusion sequence. All unused attributes // are filtered out. If the result is empty after the removal of unused // types, return unused_type. If the input sequence is an unused_type, // also return unused_type. /////////////////////////////////////////////////////////////////////////// template <typename Sequence> struct build_fusion_vector { // Remove all unused attributes typedef typename filter_unused_attributes<Sequence>::type filtered_attributes; // Build a fusion vector from a fusion sequence (Sequence), // But *only if* the sequence is not empty. i.e. if the // sequence is empty, our result will be unused_type. typedef typename mpl::eval_if< fusion::result_of::empty<filtered_attributes> , mpl::identity<unused_type> , fusion::result_of::as_vector<filtered_attributes> >::type type; }; template <> struct build_fusion_vector<unused_type> { typedef unused_type type; }; /////////////////////////////////////////////////////////////////////////// // build_attribute_sequence // // Build a fusion sequence attribute sequence from a sequence of // components. Transform<T>::type is called on each element. /////////////////////////////////////////////////////////////////////////// template <typename Sequence, typename Context , template <typename T, typename D> class Transform , typename Iterator = unused_type, typename Domain = unused_type> struct build_attribute_sequence { struct element_attribute { template <typename T> struct result; template <typename F, typename Element> struct result<F(Element)> { typedef typename Transform< typename attribute_of<Element, Context, Iterator>::type , Domain >::type type; }; // never called, but needed for decltype-based result_of (C++0x) #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template <typename Element> typename result<element_attribute(Element)>::type operator()(Element&&) const; #endif }; // Compute the list of attributes of all sub-components typedef typename fusion::result_of::transform<Sequence, element_attribute>::type type; }; /////////////////////////////////////////////////////////////////////////// // has_no_unused // // Test if there are no unused attributes in Sequence /////////////////////////////////////////////////////////////////////////// template <typename Sequence> struct has_no_unused : is_same< typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type , typename mpl::end<Sequence>::type> {}; namespace detail { template <typename Sequence, bool no_unused , int size = mpl::size<Sequence>::value> struct build_collapsed_variant; // N element case, no unused template <typename Sequence, int size> struct build_collapsed_variant<Sequence, true, size> : spirit::detail::as_variant<Sequence> {}; // N element case with unused template <typename Sequence, int size> struct build_collapsed_variant<Sequence, false, size> { typedef boost::optional< typename spirit::detail::as_variant< typename fusion::result_of::pop_front<Sequence>::type >::type > type; }; // 1 element case, no unused template <typename Sequence> struct build_collapsed_variant<Sequence, true, 1> : mpl::front<Sequence> {}; // 1 element case, with unused template <typename Sequence> struct build_collapsed_variant<Sequence, false, 1> : mpl::front<Sequence> {}; // 2 element case, no unused template <typename Sequence> struct build_collapsed_variant<Sequence, true, 2> : spirit::detail::as_variant<Sequence> {}; // 2 element case, with unused template <typename Sequence> struct build_collapsed_variant<Sequence, false, 2> { typedef boost::optional< typename mpl::deref< typename mpl::next< typename mpl::begin<Sequence>::type >::type >::type > type; }; } /////////////////////////////////////////////////////////////////////////// // alternative_attribute_transform // // This transform is invoked for every attribute in an alternative allowing // to modify the attribute type exposed by a component to the enclosing // alternative component. By default no transformation is performed. /////////////////////////////////////////////////////////////////////////// template <typename Attribute, typename Domain> struct alternative_attribute_transform : mpl::identity<Attribute> {}; /////////////////////////////////////////////////////////////////////////// // build_variant // // Build a boost::variant from a fusion sequence. build_variant makes sure // that 1) all attributes in the variant are unique 2) puts the unused // attribute, if there is any, to the front and 3) collapses single element // variants, variant<T> to T. /////////////////////////////////////////////////////////////////////////// template <typename Sequence> struct build_variant { // Remove all unused attributes. typedef typename filter_unused_attributes<Sequence>::type filtered_attributes; typedef has_no_unused<Sequence> no_unused; // If the original attribute list does not contain any unused // attributes, it is used, otherwise a single unused_type is // pushed to the front of the list. This is to make sure that if // there is an unused_type in the list, it is the first one. typedef typename mpl::eval_if< no_unused, mpl::identity<Sequence>, fusion::result_of::push_front<filtered_attributes, unused_type> >::type attribute_sequence; // Make sure each of the types occur only once in the type list typedef typename mpl::fold< attribute_sequence, mpl::vector<>, mpl::if_< mpl::contains<mpl::_1, mpl::_2>, mpl::_1, mpl::push_back<mpl::_1, mpl::_2> > >::type no_duplicates; // If there is only one type in the list of types we strip off the // variant. IOTW, collapse single element variants, variant<T> to T. // Take note that this also collapses variant<unused_type, T> to T. typedef typename traits::detail::build_collapsed_variant< no_duplicates, no_unused::value>::type type; }; namespace detail { // Domain-agnostic class template partial specializations and // type agnostic domain partial specializations are ambious. // To resolve the ambiguity type agnostic domain partial // specializations are dispatched via intermediate type. template <typename Exposed, typename Transformed, typename Domain> struct transform_attribute_base; template <typename Attribute> struct synthesize_attribute { typedef Attribute type; static Attribute pre(unused_type) { return Attribute(); } static void post(unused_type, Attribute const&) {} static void fail(unused_type) {} }; } /////////////////////////////////////////////////////////////////////////// // transform_attribute // // Sometimes the user needs to transform the attribute types for certain // attributes. This template can be used as a customization point, where // the user is able specify specific transformation rules for any attribute // type. // // Note: the transformations involving unused_type are internal details // and may be subject to change at any time. // /////////////////////////////////////////////////////////////////////////// template <typename Exposed, typename Transformed, typename Domain , typename Enable/* = void*/> struct transform_attribute : detail::transform_attribute_base<Exposed, Transformed, Domain> { BOOST_STATIC_ASSERT_MSG(!is_reference<Exposed>::value, "Exposed cannot be a reference type"); BOOST_STATIC_ASSERT_MSG(!is_reference<Transformed>::value, "Transformed cannot be a reference type"); }; template <typename Transformed, typename Domain> struct transform_attribute<unused_type, Transformed, Domain> : detail::synthesize_attribute<Transformed> {}; template <typename Transformed, typename Domain> struct transform_attribute<unused_type const, Transformed, Domain> : detail::synthesize_attribute<Transformed> {}; /////////////////////////////////////////////////////////////////////////// // swap_impl // // Swap (with proper handling of unused_types) /////////////////////////////////////////////////////////////////////////// template <typename A, typename B> void swap_impl(A& a, B& b) { A temp = a; a = b; b = temp; } template <typename T> void swap_impl(T& a, T& b) { boost::swap(a, b); } template <typename A> void swap_impl(A&, unused_type) { } template <typename A> void swap_impl(unused_type, A&) { } inline void swap_impl(unused_type, unused_type) { } /////////////////////////////////////////////////////////////////////////// // Strips single element fusion vectors into its 'naked' // form: vector<T> --> T /////////////////////////////////////////////////////////////////////////// template <typename T> struct strip_single_element_vector { typedef T type; }; #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) template <typename T> struct strip_single_element_vector<fusion::vector1<T> > { typedef T type; }; #endif template <typename T> struct strip_single_element_vector<fusion::vector<T> > { typedef T type; }; /////////////////////////////////////////////////////////////////////////// // meta function to return whether the argument is a one element fusion // sequence /////////////////////////////////////////////////////////////////////////// template <typename T , bool IsFusionSeq = fusion::traits::is_sequence<T>::value , bool IsProtoExpr = proto::is_expr<T>::value> struct one_element_sequence : mpl::false_ {}; template <typename T> struct one_element_sequence<T, true, false> : mpl::bool_<mpl::size<T>::value == 1> {}; /////////////////////////////////////////////////////////////////////////// // clear // // Clear data efficiently /////////////////////////////////////////////////////////////////////////// template <typename T> void clear(T& val); namespace detail { // this is used by the variant and fusion sequence dispatch struct clear_visitor : static_visitor<> { template <typename T> void operator()(T& val) const { spirit::traits::clear(val); } }; // default template <typename T> void clear_impl2(T& val, mpl::false_) { val = T(); } // for fusion sequences template <typename T> void clear_impl2(T& val, mpl::true_) { fusion::for_each(val, clear_visitor()); } // dispatch default or fusion sequence template <typename T> void clear_impl(T& val, mpl::false_) { clear_impl2(val, fusion::traits::is_sequence<T>()); } // STL containers template <typename T> void clear_impl(T& val, mpl::true_) { val.clear(); } } template <typename T, typename Enable/* = void*/> struct clear_value { static void call(T& val) { detail::clear_impl(val, typename is_container<T>::type()); } }; // optionals template <typename T> struct clear_value<boost::optional<T> > { static void call(boost::optional<T>& val) { if (val) val = none; // leave optional uninitialized } }; // variants template <BOOST_VARIANT_ENUM_PARAMS(typename T)> struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> > { static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val) { apply_visitor(detail::clear_visitor(), val); } }; // iterator range template <typename T> struct clear_value<iterator_range<T> > { static void call(iterator_range<T>& val) { val = iterator_range<T>(val.end(), val.end()); } }; // main dispatch template <typename T> void clear(T& val) { clear_value<T>::call(val); } // for unused inline void clear(unused_type) { } /////////////////////////////////////////////////////////////////////////// namespace detail { template <typename Out> struct print_fusion_sequence { print_fusion_sequence(Out& out_) : out(out_), is_first(true) {} typedef void result_type; template <typename T> void operator()(T const& val) const { if (is_first) is_first = false; else out << ", "; spirit::traits::print_attribute(out, val); } Out& out; mutable bool is_first; }; // print elements in a variant template <typename Out> struct print_visitor : static_visitor<> { print_visitor(Out& out_) : out(out_) {} template <typename T> void operator()(T const& val) const { spirit::traits::print_attribute(out, val); } Out& out; }; } template <typename Out, typename T, typename Enable> struct print_attribute_debug { // for plain data types template <typename T_> static void call_impl3(Out& out, T_ const& val, mpl::false_) { out << val; } // for fusion data types template <typename T_> static void call_impl3(Out& out, T_ const& val, mpl::true_) { out << '['; fusion::for_each(val, detail::print_fusion_sequence<Out>(out)); out << ']'; } // non-stl container template <typename T_> static void call_impl2(Out& out, T_ const& val, mpl::false_) { call_impl3(out, val, fusion::traits::is_sequence<T_>()); } // stl container template <typename T_> static void call_impl2(Out& out, T_ const& val, mpl::true_) { out << '['; if (!traits::is_empty(val)) { bool first = true; typename container_iterator<T_ const>::type iend = traits::end(val); for (typename container_iterator<T_ const>::type i = traits::begin(val); !traits::compare(i, iend); traits::next(i)) { if (!first) out << ", "; first = false; spirit::traits::print_attribute(out, traits::deref(i)); } } out << ']'; } // for variant types template <typename T_> static void call_impl(Out& out, T_ const& val, mpl::false_) { apply_visitor(detail::print_visitor<Out>(out), val); } // for non-variant types template <typename T_> static void call_impl(Out& out, T_ const& val, mpl::true_) { call_impl2(out, val, is_container<T_>()); } // main entry point static void call(Out& out, T const& val) { call_impl(out, val, not_is_variant<T>()); } }; template <typename Out, typename T> struct print_attribute_debug<Out, boost::optional<T> > { static void call(Out& out, boost::optional<T> const& val) { if (val) spirit::traits::print_attribute(out, *val); else out << "[empty]"; } }; /////////////////////////////////////////////////////////////////////////// template <typename Out, typename T> inline void print_attribute(Out& out, T const& val) { print_attribute_debug<Out, T>::call(out, val); } template <typename Out> inline void print_attribute(Out&, unused_type) { } /////////////////////////////////////////////////////////////////////////// // generate debug output for lookahead token (character) stream namespace detail { struct token_printer_debug_for_chars { template<typename Out, typename Char> static void print(Out& o, Char c) { using namespace std; // allow for ADL to find the proper iscntrl if (c == static_cast<Char>('\a')) o << "\\a"; else if (c == static_cast<Char>('\b')) o << "\\b"; else if (c == static_cast<Char>('\f')) o << "\\f"; else if (c == static_cast<Char>('\n')) o << "\\n"; else if (c == static_cast<Char>('\r')) o << "\\r"; else if (c == static_cast<Char>('\t')) o << "\\t"; else if (c == static_cast<Char>('\v')) o << "\\v"; else if (c >= 0 && c < 127 && iscntrl(c)) o << "\\" << std::oct << static_cast<int>(c); else o << static_cast<char>(c); } }; // for token types where the comparison with char constants wouldn't work struct token_printer_debug { template<typename Out, typename T> static void print(Out& o, T const& val) { o << val; } }; } template <typename T, typename Enable> struct token_printer_debug : mpl::if_< mpl::and_< is_convertible<T, char>, is_convertible<char, T> > , detail::token_printer_debug_for_chars , detail::token_printer_debug>::type {}; template <typename Out, typename T> inline void print_token(Out& out, T const& val) { // allow to customize the token printer routine token_printer_debug<T>::print(out, val); } }}} #endif