/*============================================================================= Copyright (c) 2001-2014 Joel de Guzman http://spirit.sourceforge.net/ 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_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM) #define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { namespace x3 { namespace traits { /////////////////////////////////////////////////////////////////////////// // Find out if T can be a (strong) substitute for Attribute /////////////////////////////////////////////////////////////////////////// template struct is_substitute; template struct variant_has_substitute; namespace detail { template struct value_type_is_substitute : is_substitute< typename container_value::type , typename container_value::type> {}; template struct is_substitute_impl : is_same {}; template struct is_substitute_impl, fusion::traits::is_sequence, mpl::equal> > >::type> : mpl::true_ {}; template struct is_substitute_impl, is_container, value_type_is_substitute > >::type> : mpl::true_ {}; template struct is_substitute_impl >::type> : mpl::or_< is_same , variant_has_substitute > {}; } template struct is_substitute : detail::is_substitute_impl {}; // for reference T template struct is_substitute : is_substitute {}; // for reference Attribute template struct is_substitute : is_substitute {}; // 2 element mpl tuple is compatible with fusion::map if: // - it's first element type is existing key in map // - it second element type is compatible to type stored at the key in map template struct is_substitute , fusion::traits::is_sequence> , mpl::and_ , fusion::traits::is_associative> , mpl::false_>::type>::type> { // checking that "p_key >> p_value" parser can // store it's result in fusion::map attribute typedef typename mpl::at_c::type p_key; typedef typename mpl::at_c::type p_value; // for simple p_key type we just check that // such key can be found in attr and that value under that key // matches p_value template struct has_kv_in_map : mpl::eval_if< fusion::result_of::has_key , mpl::apply< is_substitute< fusion::result_of::value_at_key , Value> , Map> , mpl::false_> {}; // if p_key is variant over multiple types (as a result of // "(key1|key2|key3) >> p_value" parser) check that all // keys are found in fusion::map attribute and that values // under these keys match p_value template struct variant_kv : mpl::equal_to< mpl::size< typename Variant::types> , mpl::size< mpl::filter_view>> > {}; typedef typename mpl::eval_if< is_variant , variant_kv , has_kv_in_map >::type type; }; template struct is_substitute, optional> : is_substitute {}; }}}} #endif