///////////////////////////////////////////////////////////////////////////////
/// \file make.hpp
/// Contains definition of the make<> transform.
//
// Copyright 2008 Eric Niebler. 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)
#ifndef BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007
#define BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
#endif
namespace boost { namespace proto
{
namespace detail
{
template
struct is_applyable
: mpl::and_, is_transform >
{};
template::value>
struct nested_type
{
typedef typename T::type type;
};
template
struct nested_type
{
typedef T type;
};
template
struct nested_type_if
{
typedef T type;
static bool const applied = false;
};
template
struct nested_type_if
: nested_type
{
static bool const applied = true;
};
template<
typename R
, typename Expr, typename State, typename Data
BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = detail::template_arity::value)
>
struct make_
{
typedef R type;
static bool const applied = false;
};
template<
typename R
, typename Expr, typename State, typename Data
, bool IsApplyable = is_applyable::value
>
struct make_if_
: make_
{};
template
struct make_if_
: uncvref::template impl::result_type>
{
static bool const applied = true;
};
#if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0)
// work around GCC bug
template
struct make_if_, Expr, State, Data, false>
{
typedef proto::expr type;
static bool const applied = false;
};
// work around GCC bug
template
struct make_if_, Expr, State, Data, false>
{
typedef proto::basic_expr type;
static bool const applied = false;
};
#endif
template::value>
struct construct_
{
typedef Type result_type;
BOOST_FORCEINLINE
Type operator ()() const
{
return Type();
}
// Other overloads generated by the preprocessor
#include
};
template
struct construct_
{
typedef Type result_type;
BOOST_FORCEINLINE
Type operator ()() const
{
return Type();
}
// Other overloads generated by the preprocessor
#include
};
}
/// \brief A PrimitiveTransform which prevents another PrimitiveTransform
/// from being applied in an \c ObjectTransform.
///
/// When building higher order transforms with make\<\> or
/// lazy\<\>, you sometimes would like to build types that
/// are parameterized with Proto transforms. In such lambda-style
/// transforms, Proto will unhelpfully find all nested transforms
/// and apply them, even if you don't want them to be applied. Consider
/// the following transform, which will replace the \c _ in
/// Bar<_>() with proto::terminal\::type:
///
/// \code
/// template
/// struct Bar
/// {};
///
/// struct Foo
/// : proto::when<_, Bar<_>() >
/// {};
///
/// proto::terminal::type i = {0};
///
/// int main()
/// {
/// Foo()(i);
/// std::cout << typeid(Foo()(i)).name() << std::endl;
/// }
/// \endcode
///
/// If you actually wanted to default-construct an object of type
/// Bar\<_\>, you would have to protect the \c _ to prevent
/// it from being applied. You can use proto::protect\<\>
/// as follows:
///
/// \code
/// // OK: replace anything with Bar<_>()
/// struct Foo
/// : proto::when<_, Bar >() >
/// {};
/// \endcode
template
struct protect : transform >
{
template
struct impl
{
typedef PrimitiveTransform result_type;
};
};
/// \brief A PrimitiveTransform which computes a type by evaluating any
/// nested transforms and then constructs an object of that type.
///
/// The make\<\> transform checks to see if \c Object is a template.
/// If it is, the template type is disassembled to find nested transforms.
/// Proto considers the following types to represent transforms:
///
/// \li Function types
/// \li Function pointer types
/// \li Types for which proto::is_callable\< type \>::value is \c true
///
/// boost::result_of\ \>(Expr, State, Data)\>::type
/// is evaluated as follows. For each \c X in X0,X1,..., do:
///
/// \li If \c X is a template like U\, then let X'
/// be boost::result_of\ \>(Expr, State, Data)\>::type
/// (which evaluates this procedure recursively). Note whether any
/// substitutions took place during this operation.
/// \li Otherwise, if \c X is a transform, then let X' be
/// boost::result_of\(Expr, State, Data)\>::type.
/// Note that a substitution took place.
/// \li Otherwise, let X' be \c X, and note that no substitution
/// took place.
/// \li If any substitutions took place in any of the above steps and
/// T\ has a nested ::type typedef,
/// the result type is T\::type.
/// \li Otherwise, the result type is T\.
///
/// Note that when\<\> is implemented in terms of call\<\>
/// and make\<\>, so the above procedure is evaluated recursively.
template
struct make : transform >
{
template
struct impl : transform_impl
{
typedef typename detail::make_if_