214 lines
7.7 KiB
C++
Executable File
214 lines
7.7 KiB
C++
Executable File
// 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 <boost/spirit/home/support/component.hpp>
|
|
#include <boost/spirit/home/support/unused.hpp>
|
|
#include <boost/spirit/home/support/auxiliary/functor_holder.hpp>
|
|
#include <boost/spirit/home/support/auxiliary/meta_function_holder.hpp>
|
|
#include <boost/spirit/home/support/detail/values.hpp>
|
|
#include <boost/spirit/home/karma/delimit.hpp>
|
|
#include <boost/mpl/if.hpp>
|
|
#include <boost/mpl/lambda.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
#include <boost/type_traits/remove_const.hpp>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace boost { namespace spirit
|
|
{
|
|
namespace karma
|
|
{
|
|
template <typename Functor, typename ParameterMF = Functor>
|
|
class functor_generator;
|
|
}
|
|
|
|
namespace result_of
|
|
{
|
|
template <typename Functor>
|
|
struct as_generator
|
|
{
|
|
typedef karma::functor_generator<Functor> type;
|
|
};
|
|
|
|
template <typename Functor, typename ParameterMF>
|
|
struct as_generator_mf
|
|
{
|
|
typedef karma::functor_generator<Functor, ParameterMF> 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 <typename Parameter, typename OutputIterator>
|
|
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 <typename Context>
|
|
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 <typename Functor, typename ParameterMF>
|
|
class functor_generator
|
|
: public proto::extends<
|
|
typename make_functor_holder<
|
|
functor_generator<Functor, ParameterMF> const*,
|
|
functor_generator<Functor, ParameterMF>
|
|
>::type,
|
|
functor_generator<Functor, ParameterMF>
|
|
>
|
|
{
|
|
private:
|
|
typedef functor_generator<Functor, ParameterMF> self_type;
|
|
typedef typename
|
|
make_functor_holder<self_type const*, self_type>::type
|
|
functor_tag;
|
|
typedef proto::extends<functor_tag, self_type> base_type;
|
|
|
|
public:
|
|
template <typename Context>
|
|
struct result
|
|
: mpl::apply<ParameterMF, Context>
|
|
{};
|
|
|
|
private:
|
|
// generate function just delegates to the functor supplied function
|
|
template <typename OutputIterator, typename Context, typename Parameter>
|
|
bool
|
|
generate (OutputIterator& sink, Context& ctx, Parameter const& p) const
|
|
{
|
|
// create an attribute if none is supplied
|
|
typedef typename result<Context>::type parameter_type;
|
|
typename mpl::if_<
|
|
is_same<typename remove_const<Parameter>::type, unused_type>,
|
|
parameter_type,
|
|
Parameter const&
|
|
>::type
|
|
param = spirit::detail::make_value<parameter_type>::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<Functor, ParameterMF> 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 <typename Parameter, typename OutputIterator>
|
|
// struct result
|
|
// {
|
|
// typedef bool type;
|
|
// };
|
|
//
|
|
// which declares 'bool' as the result type of the defined function
|
|
// operator and
|
|
//
|
|
// - an embedded apply meta function:
|
|
//
|
|
// template <typename Context>
|
|
// struct apply
|
|
// {
|
|
// typedef unspecified type;
|
|
// };
|
|
//
|
|
// which declares the given type as the expected parameter type for
|
|
// the generator to create.
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename Functor>
|
|
inline typename result_of::as_generator<Functor>::type
|
|
as_generator(Functor const& func)
|
|
{
|
|
return functor_generator<Functor>(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 <typename ParameterMF, typename Functor>
|
|
inline typename result_of::as_generator_mf<Functor, ParameterMF>::type
|
|
as_generator_mf(Functor const& func, ParameterMF const& mf)
|
|
{
|
|
return functor_generator<Functor, ParameterMF>(func, mf);
|
|
}
|
|
|
|
template <typename ParameterMF, typename Functor>
|
|
inline typename result_of::as_generator_mf<Functor, ParameterMF>::type
|
|
as_generator_mf(Functor const& func)
|
|
{
|
|
return functor_generator<Functor, ParameterMF>(func, ParameterMF());
|
|
}
|
|
|
|
}}}
|
|
|
|
#endif
|