// Copyright (c) 2001-2008 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_KARMA_FUNCTOR_APR_01_2007_1038AM) #define BOOST_SPIRIT_KARMA_FUNCTOR_APR_01_2007_1038AM #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once // MS compatible compilers support #pragma once #endif #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace karma { template class functor_generator; } namespace result_of { template struct as_generator { typedef karma::functor_generator type; }; template struct as_generator_mf { typedef karma::functor_generator type; }; } }} // boost::spirit /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace karma { /////////////////////////////////////////////////////////////////////////// // This struct may be used as a base class for a user defined functor /////////////////////////////////////////////////////////////////////////// struct functor_base { /////////////////////////////////////////////////////////////////////// // The return value of a karma functor is always bool /////////////////////////////////////////////////////////////////////// template struct result { typedef bool type; }; // FIXME: It will be possible to specify the return value as a typedef, but for // that Phoenix will have to be fixed. // typedef bool result_type; /////////////////////////////////////////////////////////////////////// // The expected parameter type of a functor has to be defined using a // embedded apply metafunction. Normally this will be overloaded by // the derived class, but the default is unused type. /////////////////////////////////////////////////////////////////////// template struct apply { typedef spirit::unused_type type; }; }; /////////////////////////////////////////////////////////////////////////// // The functor generator template may be used to create new generators // without having to dig into the implementation details of Karma /////////////////////////////////////////////////////////////////////////// template class functor_generator : public proto::extends< typename make_functor_holder< functor_generator const*, functor_generator >::type, functor_generator > { private: typedef functor_generator self_type; typedef typename make_functor_holder::type functor_tag; typedef proto::extends base_type; public: template struct result : mpl::apply {}; private: // generate function just delegates to the functor supplied function template bool generate (OutputIterator& sink, Context& ctx, Parameter const& p) const { // create an attribute if none is supplied typedef typename result::type parameter_type; typename mpl::if_< is_same::type, unused_type>, parameter_type, Parameter const& >::type param = spirit::detail::make_value::call(p); return functor(param, ctx, sink); } friend struct functor_director; public: explicit functor_generator() : base_type(make_tag()) { } functor_generator(Functor const& functor_) : base_type(make_tag()), functor(functor_) { } functor_generator(Functor const& functor_, ParameterMF const& mf) : base_type(make_tag()), functor(functor_), mf_(mf) { } private: functor_tag make_tag() const { functor_tag xpr = {{ this }}; return xpr; } Functor functor; meta_function_holder mf_; }; /////////////////////////////////////////////////////////////////////////// // The as_generator generator function may be used to create a functor // generator from a function object (some callable item). // The supplied functor needs to expose // // - an embedded result meta function: // // template // struct result // { // typedef bool type; // }; // // which declares 'bool' as the result type of the defined function // operator and // // - an embedded apply meta function: // // template // struct apply // { // typedef unspecified type; // }; // // which declares the given type as the expected parameter type for // the generator to create. /////////////////////////////////////////////////////////////////////////// template inline typename result_of::as_generator::type as_generator(Functor const& func) { return functor_generator(func); } /////////////////////////////////////////////////////////////////////////// // The as_generator_mf generator function is equivalent to the function // as_generator above except that the user has explicitly to specify a // type exposing an embedded apply meta function declaring the expected // parameter type for the generator to create. /////////////////////////////////////////////////////////////////////////// template inline typename result_of::as_generator_mf::type as_generator_mf(Functor const& func, ParameterMF const& mf) { return functor_generator(func, mf); } template inline typename result_of::as_generator_mf::type as_generator_mf(Functor const& func) { return functor_generator(func, ParameterMF()); } }}} #endif