summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/proto/example
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/proto/example')
-rw-r--r--src/boost/libs/proto/example/Jamfile.v287
-rw-r--r--src/boost/libs/proto/example/calc1.cpp68
-rw-r--r--src/boost/libs/proto/example/calc2.cpp103
-rw-r--r--src/boost/libs/proto/example/calc3.cpp154
-rw-r--r--src/boost/libs/proto/example/external_transforms.cpp128
-rw-r--r--src/boost/libs/proto/example/futures.cpp134
-rw-r--r--src/boost/libs/proto/example/hello.cpp28
-rw-r--r--src/boost/libs/proto/example/lambda.cpp17
-rw-r--r--src/boost/libs/proto/example/lambda.hpp1730
-rw-r--r--src/boost/libs/proto/example/lazy_vector.cpp142
-rw-r--r--src/boost/libs/proto/example/map_assign.cpp136
-rw-r--r--src/boost/libs/proto/example/mini_lambda.cpp263
-rw-r--r--src/boost/libs/proto/example/mixed.cpp375
-rw-r--r--src/boost/libs/proto/example/rgb.cpp102
-rw-r--r--src/boost/libs/proto/example/tarray.cpp222
-rw-r--r--src/boost/libs/proto/example/vec3.cpp184
-rw-r--r--src/boost/libs/proto/example/vector.cpp241
-rw-r--r--src/boost/libs/proto/example/virtual_member.cpp306
18 files changed, 4420 insertions, 0 deletions
diff --git a/src/boost/libs/proto/example/Jamfile.v2 b/src/boost/libs/proto/example/Jamfile.v2
new file mode 100644
index 000000000..7528f9ee9
--- /dev/null
+++ b/src/boost/libs/proto/example/Jamfile.v2
@@ -0,0 +1,87 @@
+# (C) Copyright 2004: 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)
+
+exe hello
+ :
+ hello.cpp
+ ;
+
+
+exe calc1
+ :
+ calc1.cpp
+ ;
+
+exe calc2
+ :
+ calc2.cpp
+ ;
+
+exe calc3
+ :
+ calc3.cpp
+ ;
+
+exe lazy_vector
+ :
+ lazy_vector.cpp
+ ;
+
+exe tarray
+ :
+ tarray.cpp
+ ;
+
+exe rgb
+ :
+ rgb.cpp
+ ;
+
+exe vec3
+ :
+ vec3.cpp
+ ;
+
+exe vector
+ :
+ vector.cpp
+ ;
+
+exe mixed
+ :
+ mixed.cpp
+ ;
+
+exe futures
+ :
+ futures.cpp
+ ;
+
+exe map_assign
+ :
+ map_assign.cpp
+ ;
+
+exe mini_lambda
+ :
+ mini_lambda.cpp
+ ;
+
+exe virtual_member
+ :
+ virtual_member.cpp
+ ;
+
+exe external_transforms
+ :
+ external_transforms.cpp
+ ;
+
+exe lambda
+ :
+ lambda.cpp
+ :
+ <include>.
+ <toolset>clang:<cxxflags>-Wno-unused-local-typedef
+ ;
diff --git a/src/boost/libs/proto/example/calc1.cpp b/src/boost/libs/proto/example/calc1.cpp
new file mode 100644
index 000000000..d3fefa629
--- /dev/null
+++ b/src/boost/libs/proto/example/calc1.cpp
@@ -0,0 +1,68 @@
+//[ Calc1
+// 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)
+//
+// This is a simple example of how to build an arithmetic expression
+// evaluator with placeholders.
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace proto = boost::proto;
+using proto::_;
+
+template<int I> struct placeholder {};
+
+// Define some placeholders
+proto::terminal< placeholder< 1 > >::type const _1 = {{}};
+proto::terminal< placeholder< 2 > >::type const _2 = {{}};
+
+// Define a calculator context, for evaluating arithmetic expressions
+struct calculator_context
+ : proto::callable_context< calculator_context const >
+{
+ // The values bound to the placeholders
+ double d[2];
+
+ // The result of evaluating arithmetic expressions
+ typedef double result_type;
+
+ explicit calculator_context(double d1 = 0., double d2 = 0.)
+ {
+ d[0] = d1;
+ d[1] = d2;
+ }
+
+ // Handle the evaluation of the placeholder terminals
+ template<int I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
+ {
+ return d[ I - 1 ];
+ }
+};
+
+template<typename Expr>
+double evaluate( Expr const &expr, double d1 = 0., double d2 = 0. )
+{
+ // Create a calculator context with d1 and d2 substituted for _1 and _2
+ calculator_context const ctx(d1, d2);
+
+ // Evaluate the calculator expression with the calculator_context
+ return proto::eval(expr, ctx);
+}
+
+int main()
+{
+ // Displays "5"
+ std::cout << evaluate( _1 + 2.0, 3.0 ) << std::endl;
+
+ // Displays "6"
+ std::cout << evaluate( _1 * _2, 3.0, 2.0 ) << std::endl;
+
+ // Displays "0.5"
+ std::cout << evaluate( (_1 - _2) / _2, 3.0, 2.0 ) << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/calc2.cpp b/src/boost/libs/proto/example/calc2.cpp
new file mode 100644
index 000000000..6fc490bf7
--- /dev/null
+++ b/src/boost/libs/proto/example/calc2.cpp
@@ -0,0 +1,103 @@
+//[ Calc2
+// 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)
+//
+// This example enhances the simple arithmetic expression evaluator
+// in calc1.cpp by using proto::extends to make arithmetic
+// expressions immediately evaluable with operator (), a-la a
+// function object
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename Expr>
+struct calculator_expression;
+
+// Tell proto how to generate expressions in the calculator_domain
+struct calculator_domain
+ : proto::domain<proto::generator<calculator_expression> >
+{};
+
+// Will be used to define the placeholders _1 and _2
+template<int I> struct placeholder {};
+
+// Define a calculator context, for evaluating arithmetic expressions
+// (This is as before, in calc1.cpp)
+struct calculator_context
+ : proto::callable_context< calculator_context const >
+{
+ // The values bound to the placeholders
+ double d[2];
+
+ // The result of evaluating arithmetic expressions
+ typedef double result_type;
+
+ explicit calculator_context(double d1 = 0., double d2 = 0.)
+ {
+ d[0] = d1;
+ d[1] = d2;
+ }
+
+ // Handle the evaluation of the placeholder terminals
+ template<int I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
+ {
+ return d[ I - 1 ];
+ }
+};
+
+// Wrap all calculator expressions in this type, which defines
+// operator () to evaluate the expression.
+template<typename Expr>
+struct calculator_expression
+ : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
+{
+ explicit calculator_expression(Expr const &expr = Expr())
+ : calculator_expression::proto_extends(expr)
+ {}
+
+ BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
+
+ // Override operator () to evaluate the expression
+ double operator ()() const
+ {
+ calculator_context const ctx;
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1) const
+ {
+ calculator_context const ctx(d1);
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1, double d2) const
+ {
+ calculator_context const ctx(d1, d2);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define some placeholders (notice they're wrapped in calculator_expression<>)
+calculator_expression<proto::terminal< placeholder< 1 > >::type> const _1;
+calculator_expression<proto::terminal< placeholder< 2 > >::type> const _2;
+
+// Now, our arithmetic expressions are immediately executable function objects:
+int main()
+{
+ // Displays "5"
+ std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
+
+ // Displays "6"
+ std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
+
+ // Displays "0.5"
+ std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/calc3.cpp b/src/boost/libs/proto/example/calc3.cpp
new file mode 100644
index 000000000..9ca97d657
--- /dev/null
+++ b/src/boost/libs/proto/example/calc3.cpp
@@ -0,0 +1,154 @@
+//[ Calc3
+// 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)
+//
+// This example enhances the arithmetic expression evaluator
+// in calc2.cpp by using a proto transform to calculate the
+// number of arguments an expression requires and using a
+// compile-time assert to guarantee that the right number of
+// arguments are actually specified.
+
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+// Will be used to define the placeholders _1 and _2
+template<typename I> struct placeholder : I {};
+
+// This grammar basically says that a calculator expression is one of:
+// - A placeholder terminal
+// - Some other terminal
+// - Some non-terminal whose children are calculator expressions
+// In addition, it has transforms that say how to calculate the
+// expression arity for each of the three cases.
+struct CalculatorGrammar
+ : proto::or_<
+
+ // placeholders have a non-zero arity ...
+ proto::when< proto::terminal< placeholder<_> >, proto::_value >
+
+ // Any other terminals have arity 0 ...
+ , proto::when< proto::terminal<_>, mpl::int_<0>() >
+
+ // For any non-terminals, find the arity of the children and
+ // take the maximum. This is recursive.
+ , proto::when< proto::nary_expr<_, proto::vararg<_> >
+ , proto::fold<_, mpl::int_<0>(), mpl::max<CalculatorGrammar, proto::_state>() > >
+
+ >
+{};
+
+// Simple wrapper for calculating a calculator expression's arity.
+// It specifies mpl::int_<0> as the initial state. The data, which
+// is not used, is mpl::void_.
+template<typename Expr>
+struct calculator_arity
+ : boost::result_of<CalculatorGrammar(Expr)>
+{};
+
+template<typename Expr>
+struct calculator_expression;
+
+// Tell proto how to generate expressions in the calculator_domain
+struct calculator_domain
+ : proto::domain<proto::generator<calculator_expression> >
+{};
+
+// Define a calculator context, for evaluating arithmetic expressions
+// (This is as before, in calc1.cpp and calc2.cpp)
+struct calculator_context
+ : proto::callable_context< calculator_context const >
+{
+ // The values bound to the placeholders
+ double d[2];
+
+ // The result of evaluating arithmetic expressions
+ typedef double result_type;
+
+ explicit calculator_context(double d1 = 0., double d2 = 0.)
+ {
+ d[0] = d1;
+ d[1] = d2;
+ }
+
+ // Handle the evaluation of the placeholder terminals
+ template<typename I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
+ {
+ return d[ I() - 1 ];
+ }
+};
+
+// Wrap all calculator expressions in this type, which defines
+// operator () to evaluate the expression.
+template<typename Expr>
+struct calculator_expression
+ : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
+{
+ typedef
+ proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
+ base_type;
+
+ explicit calculator_expression(Expr const &expr = Expr())
+ : base_type(expr)
+ {}
+
+ BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
+
+ // Override operator () to evaluate the expression
+ double operator ()() const
+ {
+ // Assert that the expression has arity 0
+ BOOST_MPL_ASSERT_RELATION(0, ==, calculator_arity<Expr>::type::value);
+ calculator_context const ctx;
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1) const
+ {
+ // Assert that the expression has arity 1
+ BOOST_MPL_ASSERT_RELATION(1, ==, calculator_arity<Expr>::type::value);
+ calculator_context const ctx(d1);
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1, double d2) const
+ {
+ // Assert that the expression has arity 2
+ BOOST_MPL_ASSERT_RELATION(2, ==, calculator_arity<Expr>::type::value);
+ calculator_context const ctx(d1, d2);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define some placeholders (notice they're wrapped in calculator_expression<>)
+calculator_expression<proto::terminal< placeholder< mpl::int_<1> > >::type> const _1;
+calculator_expression<proto::terminal< placeholder< mpl::int_<2> > >::type> const _2;
+
+// Now, our arithmetic expressions are immediately executable function objects:
+int main()
+{
+ // Displays "5"
+ std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
+
+ // Displays "6"
+ std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
+
+ // Displays "0.5"
+ std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
+
+ // This won't compile because the arity of the
+ // expression doesn't match the number of arguments
+ // ( (_1 - _2) / _2 )( 3.0 );
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/external_transforms.cpp b/src/boost/libs/proto/example/external_transforms.cpp
new file mode 100644
index 000000000..3667ebbd6
--- /dev/null
+++ b/src/boost/libs/proto/example/external_transforms.cpp
@@ -0,0 +1,128 @@
+//[ CheckedCalc
+// Copyright 2011 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)
+//
+// This is an example of how to specify a transform externally so
+// that a single grammar can be used to drive multiple differnt
+// calculations. In particular, it defines a calculator grammar
+// that computes the result of an expression with either checked
+// or non-checked division.
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/fusion/container/vector.hpp>
+#include <boost/fusion/container/generation/make_vector.hpp>
+#include <boost/proto/proto.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+
+// The argument placeholder type
+template<typename I> struct placeholder : I {};
+
+// Give each rule in the grammar a "name". This is so that we
+// can easily dispatch on it later.
+struct calc_grammar;
+struct divides_rule : proto::divides<calc_grammar, calc_grammar> {};
+
+// Use external transforms in calc_gramar
+struct calc_grammar
+ : proto::or_<
+ proto::when<
+ proto::terminal<placeholder<proto::_> >
+ , proto::functional::at(proto::_state, proto::_value)
+ >
+ , proto::when<
+ proto::terminal<proto::convertible_to<double> >
+ , proto::_value
+ >
+ , proto::when<
+ proto::plus<calc_grammar, calc_grammar>
+ , proto::_default<calc_grammar>
+ >
+ , proto::when<
+ proto::minus<calc_grammar, calc_grammar>
+ , proto::_default<calc_grammar>
+ >
+ , proto::when<
+ proto::multiplies<calc_grammar, calc_grammar>
+ , proto::_default<calc_grammar>
+ >
+ // Note that we don't specify how division nodes are
+ // handled here. Proto::external_transform is a placeholder
+ // for an actual transform.
+ , proto::when<
+ divides_rule
+ , proto::external_transform
+ >
+ >
+{};
+
+template<typename E> struct calc_expr;
+struct calc_domain : proto::domain<proto::generator<calc_expr> > {};
+
+template<typename E>
+struct calc_expr
+ : proto::extends<E, calc_expr<E>, calc_domain>
+{
+ calc_expr(E const &e = E()) : calc_expr::proto_extends(e) {}
+};
+
+calc_expr<proto::terminal<placeholder<mpl::int_<0> > >::type> _1;
+calc_expr<proto::terminal<placeholder<mpl::int_<1> > >::type> _2;
+
+// Use proto::external_transforms to map from named grammar rules to
+// transforms.
+struct non_checked_division
+ : proto::external_transforms<
+ proto::when< divides_rule, proto::_default<calc_grammar> >
+ >
+{};
+
+struct division_by_zero : std::exception {};
+
+struct do_checked_divide
+ : proto::callable
+{
+ typedef int result_type;
+ int operator()(int left, int right) const
+ {
+ if (right == 0) throw division_by_zero();
+ return left / right;
+ }
+};
+
+// Use proto::external_transforms again, this time to map the divides_rule
+// to a transforms that performs checked division.
+struct checked_division
+ : proto::external_transforms<
+ proto::when<
+ divides_rule
+ , do_checked_divide(calc_grammar(proto::_left), calc_grammar(proto::_right))
+ >
+ >
+{};
+
+int main()
+{
+ non_checked_division non_checked;
+ int result2 = calc_grammar()(_1 / _2, fusion::make_vector(6, 2), non_checked);
+ BOOST_ASSERT(result2 == 3);
+
+ try
+ {
+ checked_division checked;
+ // This should throw
+ int result3 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), checked);
+ BOOST_ASSERT(false); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ std::cout << "caught division by zero!\n";
+ }
+}
+//]
diff --git a/src/boost/libs/proto/example/futures.cpp b/src/boost/libs/proto/example/futures.cpp
new file mode 100644
index 000000000..29e77d6ee
--- /dev/null
+++ b/src/boost/libs/proto/example/futures.cpp
@@ -0,0 +1,134 @@
+//[ FutureGroup
+// 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)
+//
+// This is an example of using Proto transforms to implement
+// Howard Hinnant's future group proposal.
+
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/as_vector.hpp>
+#include <boost/fusion/include/joint_view.hpp>
+#include <boost/fusion/include/single_view.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+template<class L,class R>
+struct pick_left
+{
+ BOOST_MPL_ASSERT((boost::is_same<L, R>));
+ typedef L type;
+};
+
+// Work-arounds for Microsoft Visual C++ 7.1
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define FutureGroup(x) proto::call<FutureGroup(x)>
+#endif
+
+// Define the grammar of future group expression, as well as a
+// transform to turn them into a Fusion sequence of the correct
+// type.
+struct FutureGroup
+ : proto::or_<
+ // terminals become a single-element Fusion sequence
+ proto::when<
+ proto::terminal<_>
+ , fusion::single_view<proto::_value>(proto::_value)
+ >
+ // (a && b) becomes a concatenation of the sequence
+ // from 'a' and the one from 'b':
+ , proto::when<
+ proto::logical_and<FutureGroup, FutureGroup>
+ , fusion::joint_view<
+ boost::add_const<FutureGroup(proto::_left) >
+ , boost::add_const<FutureGroup(proto::_right) >
+ >(FutureGroup(proto::_left), FutureGroup(proto::_right))
+ >
+ // (a || b) becomes the sequence for 'a', so long
+ // as it is the same as the sequence for 'b'.
+ , proto::when<
+ proto::logical_or<FutureGroup, FutureGroup>
+ , pick_left<
+ FutureGroup(proto::_left)
+ , FutureGroup(proto::_right)
+ >(FutureGroup(proto::_left))
+ >
+ >
+{};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#undef FutureGroup
+#endif
+
+template<class E>
+struct future_expr;
+
+struct future_dom
+ : proto::domain<proto::generator<future_expr>, FutureGroup>
+{};
+
+// Expressions in the future group domain have a .get()
+// member function that (ostensibly) blocks for the futures
+// to complete and returns the results in an appropriate
+// tuple.
+template<class E>
+struct future_expr
+ : proto::extends<E, future_expr<E>, future_dom>
+{
+ explicit future_expr(E const &e)
+ : future_expr::proto_extends(e)
+ {}
+
+ typename fusion::result_of::as_vector<
+ typename boost::result_of<FutureGroup(E)>::type
+ >::type
+ get() const
+ {
+ return fusion::as_vector(FutureGroup()(*this));
+ }
+};
+
+// The future<> type has an even simpler .get()
+// member function.
+template<class T>
+struct future
+ : future_expr<typename proto::terminal<T>::type>
+{
+ future(T const &t = T())
+ : future::proto_derived_expr(future::proto_base_expr::make(t))
+ {}
+
+ T get() const
+ {
+ return proto::value(*this);
+ }
+};
+
+// TEST CASES
+struct A {};
+struct B {};
+struct C {};
+
+int main()
+{
+ using fusion::vector;
+ future<A> a;
+ future<B> b;
+ future<C> c;
+ future<vector<A,B> > ab;
+
+ // Verify that various future groups have the
+ // correct return types.
+ A t0 = a.get();
+ vector<A, B, C> t1 = (a && b && c).get();
+ vector<A, C> t2 = ((a || a) && c).get();
+ vector<A, B, C> t3 = ((a && b || a && b) && c).get();
+ vector<vector<A, B>, C> t4 = ((ab || ab) && c).get();
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/hello.cpp b/src/boost/libs/proto/example/hello.cpp
new file mode 100644
index 000000000..4b9cd99b3
--- /dev/null
+++ b/src/boost/libs/proto/example/hello.cpp
@@ -0,0 +1,28 @@
+//[ HelloWorld
+////////////////////////////////////////////////////////////////////
+// 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)
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+// This #include is only needed for compilers that use typeof emulation:
+#include <boost/typeof/std/ostream.hpp>
+namespace proto = boost::proto;
+
+proto::terminal< std::ostream & >::type cout_ = {std::cout};
+
+template< typename Expr >
+void evaluate( Expr const & expr )
+{
+ proto::default_context ctx;
+ proto::eval(expr, ctx);
+}
+
+int main()
+{
+ evaluate( cout_ << "hello" << ',' << " world" );
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/lambda.cpp b/src/boost/libs/proto/example/lambda.cpp
new file mode 100644
index 000000000..bb5c1f03e
--- /dev/null
+++ b/src/boost/libs/proto/example/lambda.cpp
@@ -0,0 +1,17 @@
+//[ Lambda
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example builds a simple but functional lambda library using Proto.
+
+#include <iostream>
+#include "./lambda.hpp"
+
+int main()
+{
+ using namespace boost::lambda;
+ int i = (_1 + _1)(42);
+ std::cout << i << std::endl;
+}
diff --git a/src/boost/libs/proto/example/lambda.hpp b/src/boost/libs/proto/example/lambda.hpp
new file mode 100644
index 000000000..a08d9bf6d
--- /dev/null
+++ b/src/boost/libs/proto/example/lambda.hpp
@@ -0,0 +1,1730 @@
+#ifndef BOOST_PP_IS_ITERATING
+ ///////////////////////////////////////////////////////////////////////////////
+ // 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)
+ //
+ // This example contains a full-featured reimplementation of the old,
+ // now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It
+ // is necessarily complex to accomodate all the quirks and inconsistencies
+ // of that old library, but it is a good example of how to build a
+ // complete and full-featured EDLS using Proto.
+ #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008
+ #define BOOST_LAMBDA_HPP_EAN_04_19_2008
+
+ #include <iosfwd>
+ #include <typeinfo>
+ #include <algorithm>
+ #include <boost/ref.hpp>
+ #include <boost/assert.hpp>
+ #include <boost/mpl/or.hpp>
+ #include <boost/mpl/int.hpp>
+ #include <boost/mpl/void.hpp>
+ #include <boost/mpl/identity.hpp>
+ #include <boost/mpl/next_prior.hpp>
+ #include <boost/mpl/min_max.hpp>
+ #include <boost/mpl/assert.hpp>
+ #include <boost/preprocessor.hpp>
+ #include <boost/utility/enable_if.hpp>
+ #include <boost/utility/result_of.hpp>
+ #include <boost/fusion/include/vector.hpp>
+ #include <boost/type_traits/add_reference.hpp>
+ #include <boost/type_traits/remove_reference.hpp>
+ #include <boost/type_traits/remove_const.hpp>
+ #include <boost/type_traits/is_same.hpp>
+ #include <boost/proto/proto.hpp>
+
+ #ifndef BOOST_LAMBDA_MAX_ARITY
+ # define BOOST_LAMBDA_MAX_ARITY 3
+ #endif
+
+ #ifdef _MSC_VER
+ # pragma warning(push)
+ # pragma warning(disable: 4355) // 'this' : used in base member initializer list
+ # pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels
+ #endif
+
+ namespace boost { namespace lambda
+ {
+ namespace tag
+ {
+ struct if_ {};
+ struct if_else_ {};
+ struct for_ {};
+ struct while_ {};
+ struct do_while_ {};
+ struct protect {};
+ struct try_ {};
+ struct throw_ {};
+ struct rethrow_ {};
+ struct switch_ {};
+ struct default_ {};
+ template<int I> struct case_ { static const int value = I; };
+ template<typename E> struct catch_ { typedef E exception_type; };
+ struct catch_all_ { typedef catch_all_ exception_type; };
+ };
+
+ template<typename Int>
+ struct placeholder
+ {
+ typedef typename Int::tag tag;
+ typedef typename Int::value_type value_type;
+ typedef placeholder<Int> type;
+ typedef placeholder<typename Int::next> next;
+ typedef placeholder<typename Int::prior> prior;
+ static const value_type value = Int::value;
+
+ friend std::ostream &operator<<(std::ostream &sout, placeholder)
+ {
+ return sout << "boost::lambda::_" << (Int::value+1);
+ }
+ };
+
+ struct exception_placeholder
+ {};
+
+ struct no_exception_type {};
+ no_exception_type const no_exception = {};
+
+ // Calculate the arity of a lambda expression
+ struct Arity
+ : proto::or_<
+ proto::when<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()>
+ , proto::when<proto::terminal<proto::_>, mpl::int_<0>()>
+ , proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> >
+ >
+ {};
+
+ // True when a lambda expression can be applied with no arguments and
+ // without an active exception object
+ struct IsNullary
+ : proto::or_<
+ proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()>
+ , proto::when<proto::terminal<exception_placeholder>, mpl::false_()>
+ , proto::when<proto::terminal<proto::_>, mpl::true_()>
+ , proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> >
+ >
+ {};
+
+ struct Eval;
+
+ template<typename Expr, typename State, typename Data>
+ typename boost::result_of<Eval(Expr&, State&, Data&)>::type
+ eval_lambda(Expr& e, State& s, Data& d);
+
+ struct EvalWhile : proto::transform<EvalWhile>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ while(eval_lambda(proto::left(expr), state, data))
+ {
+ eval_lambda(proto::right(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalDoWhile : proto::transform<EvalDoWhile>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ do
+ {
+ eval_lambda(proto::child_c<0>(expr), state, data);
+ }
+ while(eval_lambda(proto::child_c<1>(expr), state, data));
+
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalFor : proto::transform<EvalFor>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ for(eval_lambda(proto::child_c<0>(expr), state, data)
+ ; eval_lambda(proto::child_c<1>(expr), state, data)
+ ; eval_lambda(proto::child_c<2>(expr), state, data))
+ {
+ eval_lambda(proto::child_c<3>(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalIf : proto::transform<EvalIf>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ if(eval_lambda(proto::left(expr), state, data))
+ {
+ eval_lambda(proto::right(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalIfElse : proto::transform<EvalIfElse>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ if(eval_lambda(proto::child_c<0>(expr), state, data))
+ {
+ eval_lambda(proto::child_c<1>(expr), state, data);
+ }
+ else
+ {
+ eval_lambda(proto::child_c<2>(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalException : proto::transform<EvalException>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename remove_const<typename impl::state>::type result_type;
+ BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>));
+ BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>));
+
+ typename impl::state_param operator()(
+ typename impl::expr_param
+ , typename impl::state_param state
+ , typename impl::data_param
+ ) const
+ {
+ return state;
+ }
+ };
+ };
+
+ struct EvalSwitch : proto::transform<EvalSwitch>
+ {
+ template<typename Expr, typename State, typename Data, long Arity, typename BackTag>
+ struct impl2;
+
+ #define M0(Z, N, DATA) \
+ case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \
+ eval_lambda(proto::child_c<N>(expr), state, data); \
+ break; \
+ /**/
+
+ #define M1(Z, N, DATA) \
+ template<typename Expr, typename State, typename Data, typename BackTag> \
+ struct impl2<Expr, State, Data, N, BackTag> \
+ : proto::transform_impl<Expr, State, Data> \
+ { \
+ typedef void result_type; \
+ \
+ void operator()( \
+ typename impl2::expr_param expr \
+ , typename impl2::state_param state \
+ , typename impl2::data_param data \
+ ) const \
+ { \
+ switch(eval_lambda(proto::child_c<0>(expr), state, data)) \
+ { \
+ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \
+ default: \
+ break; \
+ } \
+ } \
+ }; \
+ \
+ template<typename Expr, typename State, typename Data> \
+ struct impl2<Expr, State, Data, N, tag::default_> \
+ : proto::transform_impl<Expr, State, Data> \
+ { \
+ typedef void result_type; \
+ \
+ void operator()( \
+ typename impl2::expr_param expr \
+ , typename impl2::state_param state \
+ , typename impl2::data_param data \
+ ) const \
+ { \
+ switch(eval_lambda(proto::child_c<0>(expr), state, data)) \
+ { \
+ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \
+ default:; \
+ eval_lambda(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data); \
+ break; \
+ } \
+ } \
+ }; \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~)
+ #undef M0
+ #undef M1
+
+ template<typename Expr, typename State, typename Data>
+ struct impl
+ : impl2<
+ Expr
+ , State
+ , Data
+ , proto::arity_of<Expr>::value
+ , typename proto::tag_of<
+ typename proto::result_of::child_c<
+ Expr
+ , proto::arity_of<Expr>::value-1
+ >::type
+ >::type
+ >
+ {};
+ };
+
+ struct throw_fun
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+ template<typename Expr>
+ void operator()(Expr const &e) const
+ {
+ throw e;
+ }
+ };
+
+ struct unwrap_ref : proto::callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename T>
+ struct result<This(reference_wrapper<T>)>
+ {
+ typedef T &type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(T &)>
+ : result<This(T)>
+ {};
+
+ template<typename T>
+ T &operator()(reference_wrapper<T> const &ref) const
+ {
+ return ref;
+ }
+ };
+
+ struct anytype
+ {
+ template<typename T>
+ anytype(T &) { BOOST_ASSERT(false); }
+ template<typename T>
+ operator T &() const { BOOST_ASSERT(false); throw; }
+ private:
+ anytype();
+ };
+
+ struct rethrow_fun
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef anytype result_type;
+ template<typename State>
+ anytype operator()(State const &) const
+ {
+ BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>));
+ throw;
+ }
+ };
+
+ struct Cases
+ {
+ template<typename Tag>
+ struct case_
+ : proto::otherwise<proto::_default<Eval> >
+ {};
+
+ template<typename E>
+ struct case_<tag::catch_<E> >
+ : proto::otherwise<Eval(proto::_child)>
+ {};
+
+ template<int I>
+ struct case_<tag::case_<I> >
+ : proto::otherwise<Eval(proto::_child)>
+ {};
+ };
+
+ template<> struct Cases::case_<tag::while_> : proto::otherwise<EvalWhile> {};
+ template<> struct Cases::case_<tag::for_> : proto::otherwise<EvalFor> {};
+ template<> struct Cases::case_<tag::if_> : proto::otherwise<EvalIf> {};
+ template<> struct Cases::case_<tag::if_else_> : proto::otherwise<EvalIfElse> {};
+ template<> struct Cases::case_<tag::do_while_> : proto::otherwise<EvalDoWhile> {};
+ template<> struct Cases::case_<tag::switch_> : proto::otherwise<EvalSwitch> {};
+ template<> struct Cases::case_<tag::protect> : proto::otherwise<proto::_child> {};
+ template<> struct Cases::case_<tag::default_> : proto::otherwise<Eval(proto::_child)> {};
+ template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {};
+
+ template<>
+ struct Cases::case_<proto::tag::terminal>
+ : proto::or_<
+ proto::when<
+ proto::terminal<placeholder<proto::_> >
+ , proto::functional::at(proto::_data, proto::_value)
+ >
+ , proto::when<
+ proto::terminal<exception_placeholder>
+ , EvalException
+ >
+ , proto::when<
+ proto::terminal<reference_wrapper<proto::_> >
+ , unwrap_ref(proto::_value)
+ >
+ , proto::otherwise<proto::_default<Eval> >
+ >
+ {};
+
+ template<>
+ struct Cases::case_<proto::tag::function>
+ : proto::or_<
+ proto::when<
+ proto::function<proto::terminal<rethrow_fun> >
+ , rethrow_fun(proto::_state)
+ >
+ , proto::otherwise<proto::_default<Eval> >
+ >
+ {};
+
+ struct Eval
+ : proto::switch_<Cases>
+ {};
+
+ template<typename Expr, typename State, typename Data>
+ typename boost::result_of<Eval(Expr&, State&, Data&)>::type
+ eval_lambda(Expr& e, State& s, Data& d)
+ {
+ return Eval()(e, s, d);
+ }
+
+ // Use a grammar to disable Proto's assignment operator overloads.
+ // We'll define our own because we want (x+=_1) to store x by
+ // reference. (In all other cases, variables are stored by value
+ // within lambda expressions.)
+ struct Grammar
+ : proto::switch_<struct AssignOps>
+ {};
+
+ struct AssignOps
+ {
+ template<typename Tag> struct case_ : proto::_ {};
+ };
+
+ template<> struct AssignOps::case_<proto::tag::shift_left_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::shift_right_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::multiplies_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::divides_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::modulus_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::plus_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::minus_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::bitwise_and_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::bitwise_or_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign> : proto::not_<proto::_> {};
+
+ template<typename Expr>
+ struct llexpr;
+
+ // Wrap expressions in lambda::llexpr<>.
+ struct Generator
+ : proto::pod_generator<llexpr>
+ {};
+
+ // The domain for the lambda library.
+ struct lldomain
+ : proto::domain<Generator, Grammar, proto::default_domain>
+ {
+ // Make all terminals and children held by value instead of by reference.
+ // Proto::domain<>::as_expr<> holds everything it can by value; the only
+ // exceptions are function types, abstract types, and iostreams.
+ template<typename T>
+ struct as_child
+ : proto_base_domain::as_expr<T>
+ {};
+
+ // The exception is arrays, which should still be held by reference
+ template<typename T, std::size_t N>
+ struct as_child<T[N]>
+ : proto_base_domain::as_child<T[N]>
+ {};
+ };
+
+ template<typename Sig>
+ struct llresult;
+
+ template<typename This>
+ struct llresult<This()>
+ : mpl::if_c<
+ result_of<IsNullary(This &)>::type::value
+ , result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)>
+ , mpl::identity<void>
+ >::type
+ {};
+
+ #define M0(Z, N, DATA) \
+ template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \
+ struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \
+ : result_of< \
+ Eval( \
+ This & \
+ , no_exception_type const & \
+ , BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \
+ ) \
+ > \
+ {}; \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~)
+ #undef M0
+
+ template<typename Expr>
+ struct llexpr
+ {
+ BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ template<typename Sig>
+ struct result
+ : llresult<Sig>
+ {};
+
+ typename result<llexpr const()>::type
+ operator()() const
+ {
+ fusion::vector0<> args;
+ return eval_lambda(*this, no_exception, args);
+ }
+
+ #define M1(Z, N, _) ((0)(1))
+
+ #define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT)
+
+ #define M3(R, SIZE, PRODUCT) \
+ template<BOOST_PP_ENUM_PARAMS(SIZE, typename A)> \
+ typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type \
+ operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \
+ { \
+ BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE); \
+ BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args \
+ (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \
+ return eval_lambda(*this, no_exception, args); \
+ } \
+ /**/
+
+ #define M4(R, _, I, ELEM) \
+ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I) \
+ /**/
+
+ #define M5(R, _, I, ELEM) \
+ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)& \
+ /**/
+
+ #define M6(R, _, I, ELEM) \
+ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I) \
+ /**/
+
+ #define C0
+
+ #define C1 const
+
+ #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "lambda.hpp"))
+ #include BOOST_PP_ITERATE()
+
+ #undef C0
+ #undef C1
+ #undef M1
+ #undef M2
+ #undef M3
+ #undef M4
+ #undef M5
+ #undef M6
+ };
+
+ typedef llexpr<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type;
+ typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type;
+ typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::type> placeholder3_type;
+
+ placeholder1_type const _1 = {{{}}};
+ placeholder2_type const _2 = {{{}}};
+ placeholder3_type const _3 = {{{}}};
+
+ placeholder1_type const free1 = {{{}}};
+ placeholder2_type const free2 = {{{}}};
+ placeholder3_type const free3 = {{{}}};
+
+ typedef llexpr<proto::terminal<exception_placeholder>::type> placeholderE_type;
+ placeholderE_type const _e = {{{}}};
+
+ struct byref
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename T>
+ struct result<This(T &)>
+ {
+ typedef llexpr<typename proto::terminal<T &>::type> type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(llexpr<T> &)>
+ {
+ typedef boost::reference_wrapper<llexpr<T> > type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(llexpr<T> const &)>
+ {
+ typedef boost::reference_wrapper<llexpr<T> const> type;
+ };
+
+ template<typename T>
+ typename result<byref(T &)>::type operator()(T &t) const
+ {
+ typename result<byref(T &)>::type that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ typename result<byref(T const &)>::type operator()(T const &t) const
+ {
+ typename result<byref(T const &)>::type that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const
+ {
+ return boost::ref(t);
+ }
+
+ template<typename T>
+ boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> const &t) const
+ {
+ return boost::ref(t);
+ }
+ };
+
+ namespace exprns_
+ {
+ // Ugh, the assign operators (and only the assign operators) store
+ // their left terminals by reference. That requires this special handling.
+ #define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG) \
+ template<typename T, typename U> \
+ typename proto::result_of::make_expr< \
+ TAG \
+ , lldomain \
+ , typename boost::result_of<byref(T &)>::type \
+ , U & \
+ >::type const \
+ operator OP(T &t, U &u) \
+ { \
+ return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \
+ } \
+ template<typename T, typename U> \
+ typename proto::result_of::make_expr< \
+ TAG \
+ , lldomain \
+ , typename boost::result_of<byref(T &)>::type \
+ , U const & \
+ >::type const \
+ operator OP(T &t, U const &u) \
+ { \
+ return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \
+ } \
+ /**/
+
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign)
+ }
+
+ template<typename T>
+ struct var_type
+ {
+ typedef llexpr<typename proto::terminal<T &>::type> type;
+ };
+
+ template<typename T>
+ llexpr<typename proto::terminal<T &>::type> const
+ var(T &t)
+ {
+ llexpr<typename proto::terminal<T &>::type> that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ struct constant_type
+ : proto::result_of::make_expr<
+ proto::tag::terminal
+ , lldomain
+ , T const &
+ >
+ {};
+
+ template<typename T>
+ typename constant_type<T>::type const
+ constant(T const &t)
+ {
+ typename constant_type<T>::type that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ struct constant_ref_type
+ {
+ typedef llexpr<typename proto::terminal<T const &>::type> type;
+ };
+
+ template<typename T>
+ llexpr<typename proto::terminal<T const &>::type> const
+ constant_ref(T const &t)
+ {
+ llexpr<typename proto::terminal<T const &>::type> that = {{t}};
+ return that;
+ }
+
+ template<typename Cond>
+ struct while_generator
+ {
+ explicit while_generator(Cond const &c)
+ : cond(c)
+ {}
+
+ template<typename Body>
+ typename proto::result_of::make_expr<
+ tag::while_
+ , lldomain
+ , Cond const &
+ , Body const &
+ >::type const
+ operator[](Body const &body) const
+ {
+ return proto::make_expr<tag::while_, lldomain>(
+ boost::ref(this->cond)
+ , boost::ref(body)
+ );
+ }
+
+ private:
+ Cond const &cond;
+ };
+
+ template<typename Expr>
+ while_generator<Expr> while_(Expr const &expr)
+ {
+ return while_generator<Expr>(expr);
+ }
+
+ template<typename Expr>
+ struct else_generator
+ {
+ typedef typename proto::result_of::left<Expr const &>::type condition_type;
+ typedef typename proto::result_of::right<Expr const &>::type body1_type;
+
+ explicit else_generator(Expr const &expr)
+ : if_(expr)
+ {}
+
+ template<typename Body2>
+ typename proto::result_of::make_expr<
+ tag::if_else_
+ , lldomain
+ , condition_type
+ , body1_type
+ , Body2 const &
+ >::type const
+ operator[](Body2 const &body2) const
+ {
+ return proto::make_expr<tag::if_else_, lldomain>(
+ boost::ref(proto::left(this->if_))
+ , boost::ref(proto::right(this->if_))
+ , boost::ref(body2)
+ );
+ }
+
+ private:
+ Expr const &if_;
+ };
+
+ template<typename Expr>
+ struct with_else : Expr
+ {
+ template<typename T>
+ with_else(T const &expr)
+ : Expr(expr)
+ , else_(*this)
+ {}
+
+ else_generator<Expr> else_;
+ };
+
+ template<typename Cond>
+ struct if_generator
+ {
+ explicit if_generator(Cond const &c)
+ : cond(c)
+ {}
+
+ template<typename Body>
+ with_else<
+ typename proto::result_of::make_expr<
+ tag::if_
+ , lldomain
+ , Cond const &
+ , Body const &
+ >::type
+ > const
+ operator[](Body const &body) const
+ {
+ return proto::make_expr<tag::if_, lldomain>(
+ boost::ref(this->cond)
+ , boost::ref(body)
+ );
+ }
+
+ private:
+ Cond const &cond;
+ };
+
+ template<typename Expr>
+ if_generator<Expr> if_(Expr const &expr)
+ {
+ return if_generator<Expr>(expr);
+ }
+
+ template<typename Init, typename Cond, typename Oper>
+ struct for_generator
+ {
+ explicit for_generator(Init const &i, Cond const &c, Oper const &o)
+ : init(i)
+ , cond(c)
+ , oper(o)
+ {}
+
+ template<typename Body>
+ typename proto::result_of::make_expr<
+ tag::for_
+ , lldomain
+ , Init const &
+ , Cond const &
+ , Oper const &
+ , Body const &
+ >::type const
+ operator[](Body const &body) const
+ {
+ return proto::make_expr<tag::for_, lldomain>(
+ boost::ref(this->init)
+ , boost::ref(this->cond)
+ , boost::ref(this->oper)
+ , boost::ref(body)
+ );
+ }
+
+ private:
+ Init const &init;
+ Cond const &cond;
+ Oper const &oper;
+ };
+
+ template<typename Init, typename Cond, typename Oper>
+ for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o)
+ {
+ return for_generator<Init, Cond, Oper>(i, c, o);
+ }
+
+ template<typename Body>
+ struct do_while_generator
+ {
+ explicit do_while_generator(Body const &b)
+ : body(b)
+ {}
+
+ template<typename Cond>
+ typename proto::result_of::make_expr<
+ tag::do_while_
+ , lldomain
+ , Body const &
+ , Cond const &
+ >::type const
+ operator()(Cond const &cond) const
+ {
+ return proto::make_expr<tag::do_while_, lldomain>(
+ boost::ref(this->body)
+ , boost::ref(cond)
+ );
+ }
+
+ private:
+ Body const &body;
+ };
+
+ template<typename Body>
+ struct do_body
+ {
+ explicit do_body(Body const &body)
+ : while_(body)
+ {}
+
+ do_while_generator<Body> while_;
+ };
+
+ struct do_generator
+ {
+ template<typename Body>
+ do_body<Body> operator[](Body const &body) const
+ {
+ return do_body<Body>(body);
+ }
+ };
+
+ do_generator const do_ = {};
+
+ struct noop_fun
+ {
+ typedef void result_type;
+ void operator()() const {}
+ };
+
+ typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type;
+ noop_type const noop = {{{{{}}}}};
+
+ template<typename Init, typename Cond, typename Oper>
+ typename proto::result_of::make_expr<
+ tag::for_
+ , lldomain
+ , Init const &
+ , Cond const &
+ , Oper const &
+ , noop_type const &
+ >::type const
+ for_loop(Init const &init, Cond const &cond, Oper const &oper)
+ {
+ return proto::make_expr<tag::for_, lldomain>(
+ boost::ref(init)
+ , boost::ref(cond)
+ , boost::ref(oper)
+ , boost::ref(noop)
+ );
+ }
+
+ template<typename Init, typename Cond, typename Oper, typename Body>
+ typename proto::result_of::make_expr<
+ tag::for_
+ , lldomain
+ , Init const &
+ , Cond const &
+ , Oper const &
+ , Body const &
+ >::type const
+ for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body)
+ {
+ return proto::make_expr<tag::for_>(
+ boost::ref(init)
+ , boost::ref(cond)
+ , boost::ref(oper)
+ , boost::ref(body)
+ );
+ }
+
+ template<typename Cond, typename Body>
+ typename proto::result_of::make_expr<
+ tag::while_
+ , lldomain
+ , Cond const &
+ , Body const &
+ >::type const
+ while_loop(Cond const &cond, Body const &body)
+ {
+ return proto::make_expr<tag::while_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body)
+ );
+ }
+
+ template<typename Cond>
+ typename proto::result_of::make_expr<
+ tag::while_
+ , lldomain
+ , Cond const &
+ , noop_type const &
+ >::type const
+ while_loop(Cond const &cond)
+ {
+ return proto::make_expr<tag::while_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(noop)
+ );
+ }
+
+ template<typename Cond, typename Body>
+ typename proto::result_of::make_expr<
+ tag::do_while_
+ , lldomain
+ , Body const &
+ , Cond const &
+ >::type const
+ do_while_loop(Cond const &cond, Body const &body)
+ {
+ return proto::make_expr<tag::do_while_, lldomain>(
+ boost::ref(body)
+ , boost::ref(cond)
+ );
+ }
+
+ template<typename Cond>
+ typename proto::result_of::make_expr<
+ tag::do_while_
+ , lldomain
+ , noop_type const &
+ , Cond const &
+ >::type const
+ do_while_loop(Cond const &cond)
+ {
+ return proto::make_expr<tag::do_while_, lldomain>(
+ boost::ref(noop)
+ , boost::ref(cond)
+ );
+ }
+
+ template<typename Cond, typename Body1>
+ typename proto::result_of::make_expr<
+ tag::if_
+ , lldomain
+ , Cond const &
+ , Body1 const &
+ >::type const
+ if_then(Cond const &cond, Body1 const &body1)
+ {
+ return proto::make_expr<tag::if_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body1)
+ );
+ }
+
+ template<typename Cond, typename Body1, typename Body2>
+ typename proto::result_of::make_expr<
+ tag::if_else_
+ , lldomain
+ , Cond const &
+ , Body1 const &
+ , Body2 const &
+ >::type const
+ if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2)
+ {
+ return proto::make_expr<tag::if_else_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body1)
+ , boost::ref(body2)
+ );
+ }
+
+ template<typename Cond, typename Body1, typename Body2>
+ typename proto::result_of::make_expr<
+ proto::tag::if_else_
+ , lldomain
+ , Cond const &
+ , Body1 const &
+ , Body2 const &
+ >::type const
+ if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2)
+ {
+ return proto::make_expr<proto::tag::if_else_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body1)
+ , boost::ref(body2)
+ );
+ }
+
+ template<typename T>
+ T const &make_const(T const &t)
+ {
+ return t;
+ }
+
+ #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ proto::tag::function \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ bind(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \
+ } \
+ \
+ template<typename Ret, typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ proto::tag::function \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ bind(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
+ #undef M1
+
+ template<typename Ret, typename Expr>
+ Expr const &ret(Expr const &expr)
+ {
+ return expr;
+ }
+
+ template<typename Expr>
+ Expr const &const_parameters(Expr const &expr)
+ {
+ return expr;
+ }
+
+ template<typename Expr>
+ Expr const &break_const(Expr const &expr)
+ {
+ return expr;
+ }
+
+ template<typename Lambda>
+ proto::unexpr<Lambda> const
+ unlambda(Lambda const &lambda)
+ {
+ return proto::unexpr<Lambda>(lambda);
+ }
+
+ template<typename Lambda>
+ typename proto::result_of::make_expr<
+ tag::protect
+ , lldomain
+ , Lambda const &
+ >::type const
+ protect(Lambda const &lambda)
+ {
+ return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda));
+ }
+
+ template<typename T>
+ T const std_functor(T const &t)
+ {
+ return t;
+ }
+
+ template<typename T>
+ struct ll_static_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return static_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return static_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_static_cast_fun<T>
+ , U const &
+ >::type
+ ll_static_cast(U const &u)
+ {
+ ll_static_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct ll_const_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return const_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return const_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_const_cast_fun<T>
+ , U const &
+ >::type
+ ll_const_cast(U const &u)
+ {
+ ll_const_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct ll_dynamic_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return dynamic_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return dynamic_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_dynamic_cast_fun<T>
+ , U const &
+ >::type
+ ll_dynamic_cast(U const &u)
+ {
+ ll_dynamic_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct ll_reinterpret_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return reinterpret_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return reinterpret_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_reinterpret_cast_fun<T>
+ , U const &
+ >::type
+ ll_reinterpret_cast(U const &u)
+ {
+ ll_reinterpret_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ struct ll_sizeof_fun
+ {
+ typedef std::size_t result_type;
+
+ template<typename U>
+ std::size_t operator()(U const &) const
+ {
+ return sizeof(U);
+ }
+ };
+
+ template<typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_sizeof_fun
+ , U const &
+ >::type
+ ll_sizeof(U const &u)
+ {
+ ll_sizeof_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ struct ll_typeid_fun
+ {
+ typedef std::type_info const &result_type;
+
+ template<typename U>
+ std::type_info const &operator()(U const &) const
+ {
+ return typeid(U);
+ }
+ };
+
+ template<typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_typeid_fun
+ , U const &
+ >::type
+ ll_typeid(U const &u)
+ {
+ ll_typeid_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct constructor
+ {
+ typedef T result_type;
+
+ T operator()() const
+ {
+ return T();
+ }
+
+ #define M0(Z, N, DATA) \
+ template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
+ T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \
+ { \
+ return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
+ } \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
+ #undef M0
+ };
+
+ template<typename T>
+ struct new_ptr
+ {
+ typedef T *result_type;
+
+ T *operator()() const
+ {
+ return new T();
+ }
+
+ #define M0(Z, N, DATA) \
+ template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
+ T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \
+ { \
+ return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
+ } \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
+ #undef M0
+ };
+
+ struct destructor
+ {
+ typedef void result_type;
+
+ template<typename T>
+ void operator()(T const &t) const
+ {
+ t.~T();
+ }
+
+ template<typename T>
+ void operator()(T *const &t) const
+ {
+ (*t).~T();
+ }
+ };
+
+ struct delete_ptr
+ {
+ typedef void result_type;
+ template<typename T>
+ void operator()(T *t) const
+ {
+ delete t;
+ }
+ };
+
+ template<typename T>
+ struct new_array
+ {
+ typedef T *result_type;
+ T *operator()(std::size_t n) const
+ {
+ return new T[n];
+ }
+ };
+
+ struct delete_array
+ {
+ typedef void result_type;
+ template<typename T>
+ void operator()(T *t) const
+ {
+ delete[] t;
+ }
+ };
+
+ template<typename T>
+ struct type2type {};
+
+ struct try_catch_nil {};
+
+ template<typename Head, typename Tail>
+ struct try_catch_cons : Tail
+ {
+ typedef typename Head::proto_tag::exception_type exception_type;
+
+ try_catch_cons(Head const &head, Tail const &tail)
+ : Tail(tail)
+ , head(head)
+ {}
+
+ template<typename State, typename Data>
+ typename result_of<Tail const(State const &, Data &)>::type
+ operator()(State const &state, Data &data) const
+ {
+ return this->invoke(state, data, type2type<exception_type>());
+ }
+
+ private:
+ // catch(Exception const &)
+ template<typename State, typename Data, typename Exception>
+ typename result_of<Tail const(State const &, Data &)>::type
+ invoke(State const &state, Data &data, type2type<Exception>) const
+ {
+ typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
+ try
+ {
+ return static_cast<result_type>(this->Tail::operator()(state, data));
+ }
+ catch(Exception const &e)
+ {
+ return static_cast<result_type>(eval_lambda(this->head, e, data));
+ }
+ }
+
+ // catch(...)
+ template<typename State, typename Data>
+ typename result_of<Tail const(State const &, Data &)>::type
+ invoke(State const &state, Data &data, type2type<tag::catch_all_>) const
+ {
+ typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
+ try
+ {
+ return static_cast<result_type>(this->Tail::operator()(state, data));
+ }
+ catch(...)
+ {
+ return static_cast<result_type>(eval_lambda(this->head, tag::catch_all_(), data));
+ }
+ }
+
+ Head const &head;
+ };
+
+ template<typename Head>
+ struct try_catch_cons<Head, try_catch_nil> : proto::callable
+ {
+ try_catch_cons(Head const &head, try_catch_nil const &)
+ : head(head)
+ {}
+
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename State, typename Data>
+ struct result<This(State, Data)>
+ : result_of<Eval(Head const &, State, Data)>
+ {};
+
+ template<typename State, typename Data>
+ typename result_of<Eval(Head const &, State, Data)>::type
+ operator()(State const &state, Data &data) const
+ {
+ return eval_lambda(this->head, state, data);
+ }
+
+ private:
+ Head const &head;
+ };
+
+ struct try_catch_fun : proto::callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Fun, typename State, typename Data>
+ struct result<This(Fun, State, Data)>
+ : result_of<Fun(State, Data)>
+ {};
+
+ template<typename Fun, typename State, typename Data>
+ typename result_of<Fun(State const &, Data &)>::type
+ operator()(Fun const &fun, State const &state, Data &data) const
+ {
+ return fun(state, data);
+ }
+ };
+
+ template<>
+ struct Cases::case_<tag::try_>
+ : proto::otherwise<
+ try_catch_fun(
+ proto::fold<
+ proto::_
+ , try_catch_nil()
+ , try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state)
+ >
+ , proto::_state
+ , proto::_data
+ )
+ >
+ {};
+
+ template<typename E, typename Expr>
+ typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const
+ catch_exception(Expr const &expr)
+ {
+ return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr));
+ }
+
+ template<typename E>
+ typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const
+ catch_exception()
+ {
+ return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop));
+ }
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<
+ tag::catch_all_
+ , lldomain
+ , Expr const &
+ >::type const
+ catch_all(Expr const &expr)
+ {
+ return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr));
+ }
+
+ inline
+ proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const
+ catch_all()
+ {
+ return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop));
+ }
+
+ #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ tag::try_ \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ try_catch(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<tag::try_, lldomain>(ref_a(N)); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
+ #undef M1
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , throw_fun
+ , Expr const &
+ >::type const
+ throw_exception(Expr const &expr)
+ {
+ throw_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
+ }
+
+ inline
+ proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const
+ rethrow()
+ {
+ return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun());
+ }
+
+ struct make_void_fun
+ {
+ typedef void result_type;
+ template<typename T>
+ void operator()(T const &) const
+ {}
+ };
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , make_void_fun
+ , Expr const &
+ >::type const
+ make_void(Expr const &expr)
+ {
+ make_void_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
+ }
+
+ #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ tag::switch_ \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ switch_statement(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<tag::switch_, lldomain>(ref_a(N)); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
+ #undef M1
+
+ template<int I, typename Expr>
+ typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const
+ case_statement(Expr const &expr)
+ {
+ return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr));
+ }
+
+ template<int I>
+ typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const
+ case_statement()
+ {
+ return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop));
+ }
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const
+ default_statement(Expr const &expr)
+ {
+ return proto::make_expr<tag::default_, lldomain>(boost::ref(expr));
+ }
+
+ inline
+ proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const
+ default_statement()
+ {
+ return proto::make_expr<tag::default_, lldomain>(boost::ref(noop));
+ }
+
+ namespace ll
+ {
+ struct for_each
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Begin, typename End, typename Fun>
+ struct result<This(Begin, End, Fun)>
+ : remove_const<typename remove_reference<Fun>::type>
+ {};
+
+ template<typename InIter, typename Fun>
+ Fun operator()(InIter begin, InIter end, Fun fun) const
+ {
+ return std::for_each(begin, end, fun);
+ }
+ };
+ }
+
+ }}
+
+ namespace boost
+ {
+ template<typename Expr>
+ struct result_of<lambda::llexpr<Expr>()>
+ : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()>
+ {};
+
+ template<typename Expr>
+ struct result_of<lambda::llexpr<Expr> const()>
+ : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> const()>
+ {};
+ }
+
+ #ifdef _MSC_VER
+ # pragma warning(pop)
+ #endif
+
+ #endif
+
+#else
+
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(
+ M2,
+ BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~)
+ )
+
+#endif
diff --git a/src/boost/libs/proto/example/lazy_vector.cpp b/src/boost/libs/proto/example/lazy_vector.cpp
new file mode 100644
index 000000000..2fc7755c8
--- /dev/null
+++ b/src/boost/libs/proto/example/lazy_vector.cpp
@@ -0,0 +1,142 @@
+//[ LazyVector
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example constructs a mini-library for linear algebra, using
+// expression templates to eliminate the need for temporaries when
+// adding vectors of numbers.
+//
+// This example uses a domain with a grammar to prune the set
+// of overloaded operators. Only those operators that produce
+// valid lazy vector expressions are allowed.
+
+#include <vector>
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename Expr>
+struct lazy_vector_expr;
+
+// This grammar describes which lazy vector expressions
+// are allowed; namely, vector terminals and addition
+// and subtraction of lazy vector expressions.
+struct LazyVectorGrammar
+ : proto::or_<
+ proto::terminal< std::vector<_> >
+ , proto::plus< LazyVectorGrammar, LazyVectorGrammar >
+ , proto::minus< LazyVectorGrammar, LazyVectorGrammar >
+ >
+{};
+
+// Tell proto that in the lazy_vector_domain, all
+// expressions should be wrapped in laxy_vector_expr<>
+// and must conform to the lazy vector grammar.
+struct lazy_vector_domain
+ : proto::domain<proto::generator<lazy_vector_expr>, LazyVectorGrammar>
+{};
+
+// Here is an evaluation context that indexes into a lazy vector
+// expression, and combines the result.
+template<typename Size = std::size_t>
+struct lazy_subscript_context
+{
+ lazy_subscript_context(Size subscript)
+ : subscript_(subscript)
+ {}
+
+ // Use default_eval for all the operations ...
+ template<typename Expr, typename Tag = typename Expr::proto_tag>
+ struct eval
+ : proto::default_eval<Expr, lazy_subscript_context>
+ {};
+
+ // ... except for terminals, which we index with our subscript
+ template<typename Expr>
+ struct eval<Expr, proto::tag::terminal>
+ {
+ typedef typename proto::result_of::value<Expr>::type::value_type result_type;
+
+ result_type operator ()( Expr const & expr, lazy_subscript_context & ctx ) const
+ {
+ return proto::value( expr )[ ctx.subscript_ ];
+ }
+ };
+
+ Size subscript_;
+};
+
+// Here is the domain-specific expression wrapper, which overrides
+// operator [] to evaluate the expression using the lazy_subscript_context.
+template<typename Expr>
+struct lazy_vector_expr
+ : proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>
+{
+ lazy_vector_expr( Expr const & expr = Expr() )
+ : lazy_vector_expr::proto_extends( expr )
+ {}
+
+ // Use the lazy_subscript_context<> to implement subscripting
+ // of a lazy vector expression tree.
+ template< typename Size >
+ typename proto::result_of::eval< Expr, lazy_subscript_context<Size> >::type
+ operator []( Size subscript ) const
+ {
+ lazy_subscript_context<Size> ctx(subscript);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Here is our lazy_vector terminal, implemented in terms of lazy_vector_expr
+template< typename T >
+struct lazy_vector
+ : lazy_vector_expr< typename proto::terminal< std::vector<T> >::type >
+{
+ typedef typename proto::terminal< std::vector<T> >::type expr_type;
+
+ lazy_vector( std::size_t size = 0, T const & value = T() )
+ : lazy_vector_expr<expr_type>( expr_type::make( std::vector<T>( size, value ) ) )
+ {}
+
+ // Here we define a += operator for lazy vector terminals that
+ // takes a lazy vector expression and indexes it. expr[i] here
+ // uses lazy_subscript_context<> under the covers.
+ template< typename Expr >
+ lazy_vector &operator += (Expr const & expr)
+ {
+ std::size_t size = proto::value(*this).size();
+ for(std::size_t i = 0; i < size; ++i)
+ {
+ proto::value(*this)[i] += expr[i];
+ }
+ return *this;
+ }
+};
+
+int main()
+{
+ // lazy_vectors with 4 elements each.
+ lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );
+
+ // Add two vectors lazily and get the 2nd element.
+ double d1 = ( v2 + v3 )[ 2 ]; // Look ma, no temporaries!
+ std::cout << d1 << std::endl;
+
+ // Subtract two vectors and add the result to a third vector.
+ v1 += v2 - v3; // Still no temporaries!
+ std::cout << '{' << v1[0] << ',' << v1[1]
+ << ',' << v1[2] << ',' << v1[3] << '}' << std::endl;
+
+ // This expression is disallowed because it does not conform
+ // to the LazyVectorGrammar
+ //(v2 + v3) += v1;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/map_assign.cpp b/src/boost/libs/proto/example/map_assign.cpp
new file mode 100644
index 000000000..939110594
--- /dev/null
+++ b/src/boost/libs/proto/example/map_assign.cpp
@@ -0,0 +1,136 @@
+//[ MapAssign
+// 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)
+//
+// This is a port of map_list_of() from the Boost.Assign library.
+// It has the advantage of being more efficient at runtime by not
+// building any temporary container that requires dynamic allocation.
+
+#include <map>
+#include <string>
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/type_traits/add_reference.hpp>
+namespace proto = boost::proto;
+using proto::_;
+
+struct map_list_of_tag
+{};
+
+// A simple callable function object that inserts a
+// (key,value) pair into a map.
+struct insert
+ : proto::callable
+{
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Map, typename Key, typename Value>
+ struct result<This(Map, Key, Value)>
+ : boost::add_reference<Map>
+ {};
+
+ template<typename Map, typename Key, typename Value>
+ Map &operator()(Map &map, Key const &key, Value const &value) const
+ {
+ map.insert(typename Map::value_type(key, value));
+ return map;
+ }
+};
+
+// Work-arounds for Microsoft Visual C++ 7.1
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define MapListOf(x) proto::call<MapListOf(x)>
+#define _value(x) call<proto::_value(x)>
+#endif
+
+// The grammar for valid map-list expressions, and a
+// transform that populates the map.
+struct MapListOf
+ : proto::or_<
+ proto::when<
+ // map_list_of(a,b)
+ proto::function<
+ proto::terminal<map_list_of_tag>
+ , proto::terminal<_>
+ , proto::terminal<_>
+ >
+ , insert(
+ proto::_data
+ , proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ )
+ >
+ , proto::when<
+ // map_list_of(a,b)(c,d)...
+ proto::function<
+ MapListOf
+ , proto::terminal<_>
+ , proto::terminal<_>
+ >
+ , insert(
+ MapListOf(proto::_child0)
+ , proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ )
+ >
+ >
+{};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#undef MapListOf
+#undef _value
+#endif
+
+template<typename Expr>
+struct map_list_of_expr;
+
+struct map_list_of_dom
+ : proto::domain<proto::pod_generator<map_list_of_expr>, MapListOf>
+{};
+
+// An expression wrapper that provides a conversion to a
+// map that uses the MapListOf
+template<typename Expr>
+struct map_list_of_expr
+{
+ BOOST_PROTO_BASIC_EXTENDS(Expr, map_list_of_expr, map_list_of_dom)
+ BOOST_PROTO_EXTENDS_FUNCTION()
+
+ template<typename Key, typename Value, typename Cmp, typename Al>
+ operator std::map<Key, Value, Cmp, Al> () const
+ {
+ BOOST_MPL_ASSERT((proto::matches<Expr, MapListOf>));
+ std::map<Key, Value, Cmp, Al> map;
+ return MapListOf()(*this, 0, map);
+ }
+};
+
+map_list_of_expr<proto::terminal<map_list_of_tag>::type> const map_list_of = {{{}}};
+
+int main()
+{
+ // Initialize a map:
+ std::map<std::string, int> op =
+ map_list_of
+ ("<", 1)
+ ("<=",2)
+ (">", 3)
+ (">=",4)
+ ("=", 5)
+ ("<>",6)
+ ;
+
+ std::cout << "\"<\" --> " << op["<"] << std::endl;
+ std::cout << "\"<=\" --> " << op["<="] << std::endl;
+ std::cout << "\">\" --> " << op[">"] << std::endl;
+ std::cout << "\">=\" --> " << op[">="] << std::endl;
+ std::cout << "\"=\" --> " << op["="] << std::endl;
+ std::cout << "\"<>\" --> " << op["<>"] << std::endl;
+
+ return 0;
+}
+//]
+
diff --git a/src/boost/libs/proto/example/mini_lambda.cpp b/src/boost/libs/proto/example/mini_lambda.cpp
new file mode 100644
index 000000000..0f3d52c6d
--- /dev/null
+++ b/src/boost/libs/proto/example/mini_lambda.cpp
@@ -0,0 +1,263 @@
+//[ Lambda
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example builds a simple but functional lambda library using Proto.
+
+#include <iostream>
+#include <algorithm>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/fusion/tuple.hpp>
+#include <boost/typeof/typeof.hpp>
+#include <boost/typeof/std/ostream.hpp>
+#include <boost/typeof/std/iostream.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+// Forward declaration of the lambda expression wrapper
+template<typename T>
+struct lambda;
+
+struct lambda_domain
+ : proto::domain<proto::pod_generator<lambda> >
+{};
+
+template<typename I>
+struct placeholder
+{
+ typedef I arity;
+};
+
+template<typename T>
+struct placeholder_arity
+{
+ typedef typename T::arity type;
+};
+
+// The lambda grammar, with the transforms for calculating the max arity
+struct lambda_arity
+ : proto::or_<
+ proto::when<
+ proto::terminal< placeholder<_> >
+ , mpl::next<placeholder_arity<proto::_value> >()
+ >
+ , proto::when< proto::terminal<_>
+ , mpl::int_<0>()
+ >
+ , proto::when<
+ proto::nary_expr<_, proto::vararg<_> >
+ , proto::fold<_, mpl::int_<0>(), mpl::max<lambda_arity, proto::_state>()>
+ >
+ >
+{};
+
+// The lambda context is the same as the default context
+// with the addition of special handling for lambda placeholders
+template<typename Tuple>
+struct lambda_context
+ : proto::callable_context<lambda_context<Tuple> const>
+{
+ lambda_context(Tuple const &args)
+ : args_(args)
+ {}
+
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename I>
+ struct result<This(proto::tag::terminal, placeholder<I> const &)>
+ : fusion::result_of::at<Tuple, I>
+ {};
+
+ template<typename I>
+ typename fusion::result_of::at<Tuple, I>::type
+ operator ()(proto::tag::terminal, placeholder<I> const &) const
+ {
+ return fusion::at<I>(this->args_);
+ }
+
+ Tuple args_;
+};
+
+// The lambda<> expression wrapper makes expressions polymorphic
+// function objects
+template<typename T>
+struct lambda
+{
+ BOOST_PROTO_BASIC_EXTENDS(T, lambda<T>, lambda_domain)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ // Calculate the arity of this lambda expression
+ static int const arity = boost::result_of<lambda_arity(T)>::type::value;
+
+ template<typename Sig>
+ struct result;
+
+ // Define nested result<> specializations to calculate the return
+ // type of this lambda expression. But be careful not to evaluate
+ // the return type of the nullary function unless we have a nullary
+ // lambda!
+ template<typename This>
+ struct result<This()>
+ : mpl::eval_if_c<
+ 0 == arity
+ , proto::result_of::eval<T const, lambda_context<fusion::tuple<> > >
+ , mpl::identity<void>
+ >
+ {};
+
+ template<typename This, typename A0>
+ struct result<This(A0)>
+ : proto::result_of::eval<T const, lambda_context<fusion::tuple<A0> > >
+ {};
+
+ template<typename This, typename A0, typename A1>
+ struct result<This(A0, A1)>
+ : proto::result_of::eval<T const, lambda_context<fusion::tuple<A0, A1> > >
+ {};
+
+ // Define our operator () that evaluates the lambda expression.
+ typename result<lambda()>::type
+ operator ()() const
+ {
+ fusion::tuple<> args;
+ lambda_context<fusion::tuple<> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+
+ template<typename A0>
+ typename result<lambda(A0 const &)>::type
+ operator ()(A0 const &a0) const
+ {
+ fusion::tuple<A0 const &> args(a0);
+ lambda_context<fusion::tuple<A0 const &> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+
+ template<typename A0, typename A1>
+ typename result<lambda(A0 const &, A1 const &)>::type
+ operator ()(A0 const &a0, A1 const &a1) const
+ {
+ fusion::tuple<A0 const &, A1 const &> args(a0, a1);
+ lambda_context<fusion::tuple<A0 const &, A1 const &> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define some lambda placeholders
+lambda<proto::terminal<placeholder<mpl::int_<0> > >::type> const _1 = {{}};
+lambda<proto::terminal<placeholder<mpl::int_<1> > >::type> const _2 = {{}};
+
+template<typename T>
+lambda<typename proto::terminal<T>::type> const val(T const &t)
+{
+ lambda<typename proto::terminal<T>::type> that = {{t}};
+ return that;
+}
+
+template<typename T>
+lambda<typename proto::terminal<T &>::type> const var(T &t)
+{
+ lambda<typename proto::terminal<T &>::type> that = {{t}};
+ return that;
+}
+
+template<typename T>
+struct construct_helper
+{
+ typedef T result_type; // for TR1 result_of
+
+ T operator()() const
+ { return T(); }
+
+ // Generate BOOST_PROTO_MAX_ARITY overloads of the
+ // following function call operator.
+#define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, a)\
+ template<typename_A(N)> \
+ T operator()(A_const_ref_a(N)) const \
+ { return T(a(N)); }
+#define BOOST_PROTO_LOCAL_a BOOST_PROTO_a
+#include BOOST_PROTO_LOCAL_ITERATE()
+};
+
+// Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
+// following construct() function template.
+#define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+template<typename T, typename_A(N)> \
+typename proto::result_of::make_expr< \
+ proto::tag::function \
+ , lambda_domain \
+ , construct_helper<T> \
+ , A_const_ref(N) \
+>::type const \
+construct(A_const_ref_a(N)) \
+{ \
+ return proto::make_expr< \
+ proto::tag::function \
+ , lambda_domain \
+ >( \
+ construct_helper<T>() \
+ , ref_a(N) \
+ ); \
+}
+BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0)
+#undef M0
+
+struct S
+{
+ S() {}
+ S(int i, char c)
+ {
+ std::cout << "S(" << i << "," << c << ")\n";
+ }
+};
+
+int main()
+{
+ // Create some lambda objects and immediately
+ // invoke them by applying their operator():
+ int i = ( (_1 + 2) / 4 )(42);
+ std::cout << i << std::endl; // prints 11
+
+ int j = ( (-(_1 + 2)) / 4 )(42);
+ std::cout << j << std::endl; // prints -11
+
+ double d = ( (4 - _2) * 3 )(42, 3.14);
+ std::cout << d << std::endl; // prints 2.58
+
+ // check non-const ref terminals
+ (std::cout << _1 << " -- " << _2 << '\n')(42, "Life, the Universe and Everything!");
+ // prints "42 -- Life, the Universe and Everything!"
+
+ // "Nullary" lambdas work too
+ int k = (val(1) + val(2))();
+ std::cout << k << std::endl; // prints 3
+
+ // check array indexing for kicks
+ int integers[5] = {0};
+ (var(integers)[2] = 2)();
+ (var(integers)[_1] = _1)(3);
+ std::cout << integers[2] << std::endl; // prints 2
+ std::cout << integers[3] << std::endl; // prints 3
+
+ // Now use a lambda with an STL algorithm!
+ int rgi[4] = {1,2,3,4};
+ char rgc[4] = {'a','b','c','d'};
+ S rgs[4];
+
+ std::transform(rgi, rgi+4, rgc, rgs, construct<S>(_1, _2));
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/mixed.cpp b/src/boost/libs/proto/example/mixed.cpp
new file mode 100644
index 000000000..d48e21dcb
--- /dev/null
+++ b/src/boost/libs/proto/example/mixed.cpp
@@ -0,0 +1,375 @@
+//[ Mixed
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
+// expressions using std::vector<> and std::list, non-proto types. It is a port
+// of the Mixed example from PETE.
+// (http://www.codesourcery.com/pooma/download.html).
+
+#include <list>
+#include <cmath>
+#include <vector>
+#include <complex>
+#include <iostream>
+#include <stdexcept>
+#include <boost/proto/core.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/typeof/std/list.hpp>
+#include <boost/typeof/std/vector.hpp>
+#include <boost/typeof/std/complex.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+namespace proto = boost::proto;
+namespace mpl = boost::mpl;
+using proto::_;
+
+template<typename Expr>
+struct MixedExpr;
+
+template<typename Iter>
+struct iterator_wrapper
+{
+ typedef Iter iterator;
+
+ explicit iterator_wrapper(Iter iter)
+ : it(iter)
+ {}
+
+ mutable Iter it;
+};
+
+struct begin : proto::callable
+{
+ template<class Sig>
+ struct result;
+
+ template<class This, class Cont>
+ struct result<This(Cont)>
+ : proto::result_of::as_expr<
+ iterator_wrapper<typename boost::remove_reference<Cont>::type::const_iterator>
+ >
+ {};
+
+ template<typename Cont>
+ typename result<begin(Cont const &)>::type
+ operator ()(Cont const &cont) const
+ {
+ iterator_wrapper<typename Cont::const_iterator> it(cont.begin());
+ return proto::as_expr(it);
+ }
+};
+
+// Here is a grammar that replaces vector and list terminals with their
+// begin iterators
+struct Begin
+ : proto::or_<
+ proto::when< proto::terminal< std::vector<_, _> >, begin(proto::_value) >
+ , proto::when< proto::terminal< std::list<_, _> >, begin(proto::_value) >
+ , proto::when< proto::terminal<_> >
+ , proto::when< proto::nary_expr<_, proto::vararg<Begin> > >
+ >
+{};
+
+// Here is an evaluation context that dereferences iterator
+// terminals.
+struct DereferenceCtx
+{
+ // Unless this is an iterator terminal, use the
+ // default evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::default_eval<Expr, DereferenceCtx const>
+ {};
+
+ // Dereference iterator terminals.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<iterator_wrapper<_> > >
+ >::type
+ >
+ {
+ typedef typename proto::result_of::value<Expr>::type IteratorWrapper;
+ typedef typename IteratorWrapper::iterator iterator;
+ typedef typename std::iterator_traits<iterator>::reference result_type;
+
+ result_type operator ()(Expr &expr, DereferenceCtx const &) const
+ {
+ return *proto::value(expr).it;
+ }
+ };
+};
+
+// Here is an evaluation context that increments iterator
+// terminals.
+struct IncrementCtx
+{
+ // Unless this is an iterator terminal, use the
+ // default evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::null_eval<Expr, IncrementCtx const>
+ {};
+
+ // advance iterator terminals.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<iterator_wrapper<_> > >
+ >::type
+ >
+ {
+ typedef void result_type;
+
+ result_type operator ()(Expr &expr, IncrementCtx const &) const
+ {
+ ++proto::value(expr).it;
+ }
+ };
+};
+
+// A grammar which matches all the assignment operators,
+// so we can easily disable them.
+struct AssignOps
+ : proto::switch_<struct AssignOpsCases>
+{};
+
+// Here are the cases used by the switch_ above.
+struct AssignOpsCases
+{
+ template<typename Tag, int D = 0> struct case_ : proto::not_<_> {};
+
+ template<int D> struct case_< proto::tag::plus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::minus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::multiplies_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::divides_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::modulus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_left_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_right_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_and_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_or_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_xor_assign, D > : _ {};
+};
+
+// An expression conforms to the MixedGrammar if it is a terminal or some
+// op that is not an assignment op. (Assignment will be handled specially.)
+struct MixedGrammar
+ : proto::or_<
+ proto::terminal<_>
+ , proto::and_<
+ proto::nary_expr<_, proto::vararg<MixedGrammar> >
+ , proto::not_<AssignOps>
+ >
+ >
+{};
+
+// Expressions in the MixedDomain will be wrapped in MixedExpr<>
+// and must conform to the MixedGrammar
+struct MixedDomain
+ : proto::domain<proto::generator<MixedExpr>, MixedGrammar>
+{};
+
+// Here is MixedExpr, a wrapper for expression types in the MixedDomain.
+template<typename Expr>
+struct MixedExpr
+ : proto::extends<Expr, MixedExpr<Expr>, MixedDomain>
+{
+ explicit MixedExpr(Expr const &expr)
+ : MixedExpr::proto_extends(expr)
+ {}
+private:
+ // hide this:
+ using proto::extends<Expr, MixedExpr<Expr>, MixedDomain>::operator [];
+};
+
+// Define a trait type for detecting vector and list terminals, to
+// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
+template<typename T>
+struct IsMixed
+ : mpl::false_
+{};
+
+template<typename T, typename A>
+struct IsMixed<std::list<T, A> >
+ : mpl::true_
+{};
+
+template<typename T, typename A>
+struct IsMixed<std::vector<T, A> >
+ : mpl::true_
+{};
+
+namespace MixedOps
+{
+ // This defines all the overloads to make expressions involving
+ // std::vector to build expression templates.
+ BOOST_PROTO_DEFINE_OPERATORS(IsMixed, MixedDomain)
+
+ struct assign_op
+ {
+ template<typename T, typename U>
+ void operator ()(T &t, U const &u) const
+ {
+ t = u;
+ }
+ };
+
+ struct plus_assign_op
+ {
+ template<typename T, typename U>
+ void operator ()(T &t, U const &u) const
+ {
+ t += u;
+ }
+ };
+
+ struct minus_assign_op
+ {
+ template<typename T, typename U>
+ void operator ()(T &t, U const &u) const
+ {
+ t -= u;
+ }
+ };
+
+ struct sin_
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Arg>
+ struct result<This(Arg)>
+ : boost::remove_const<typename boost::remove_reference<Arg>::type>
+ {};
+
+ template<typename Arg>
+ Arg operator ()(Arg const &a) const
+ {
+ return std::sin(a);
+ }
+ };
+
+ template<typename A>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , MixedDomain
+ , sin_ const
+ , A const &
+ >::type sin(A const &a)
+ {
+ return proto::make_expr<proto::tag::function, MixedDomain>(sin_(), boost::ref(a));
+ }
+
+ template<typename FwdIter, typename Expr, typename Op>
+ void evaluate(FwdIter begin, FwdIter end, Expr const &expr, Op op)
+ {
+ IncrementCtx const inc = {};
+ DereferenceCtx const deref = {};
+ typename boost::result_of<Begin(Expr const &)>::type expr2 = Begin()(expr);
+ for(; begin != end; ++begin)
+ {
+ op(*begin, proto::eval(expr2, deref));
+ proto::eval(expr2, inc);
+ }
+ }
+
+ // Add-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &assign(std::vector<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op());
+ return arr;
+ }
+
+ // Add-assign to a list from some expression.
+ template<typename T, typename A, typename Expr>
+ std::list<T, A> &assign(std::list<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op());
+ return arr;
+ }
+
+ // Add-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &operator +=(std::vector<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op());
+ return arr;
+ }
+
+ // Add-assign to a list from some expression.
+ template<typename T, typename A, typename Expr>
+ std::list<T, A> &operator +=(std::list<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op());
+ return arr;
+ }
+
+ // Minus-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &operator -=(std::vector<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op());
+ return arr;
+ }
+
+ // Minus-assign to a list from some expression.
+ template<typename T, typename A, typename Expr>
+ std::list<T, A> &operator -=(std::list<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op());
+ return arr;
+ }
+}
+
+int main()
+{
+ using namespace MixedOps;
+
+ int n = 10;
+ std::vector<int> a,b,c,d;
+ std::list<double> e;
+ std::list<std::complex<double> > f;
+
+ int i;
+ for(i = 0;i < n; ++i)
+ {
+ a.push_back(i);
+ b.push_back(2*i);
+ c.push_back(3*i);
+ d.push_back(i);
+ e.push_back(0.0);
+ f.push_back(std::complex<double>(1.0, 1.0));
+ }
+
+ MixedOps::assign(b, 2);
+ MixedOps::assign(d, a + b * c);
+ a += if_else(d < 30, b, c);
+
+ MixedOps::assign(e, c);
+ e += e - 4 / (c + 1);
+
+ f -= sin(0.1 * e * std::complex<double>(0.2, 1.2));
+
+ std::list<double>::const_iterator ei = e.begin();
+ std::list<std::complex<double> >::const_iterator fi = f.begin();
+ for (i = 0; i < n; ++i)
+ {
+ std::cout
+ << "a(" << i << ") = " << a[i]
+ << " b(" << i << ") = " << b[i]
+ << " c(" << i << ") = " << c[i]
+ << " d(" << i << ") = " << d[i]
+ << " e(" << i << ") = " << *ei++
+ << " f(" << i << ") = " << *fi++
+ << std::endl;
+ }
+}
+//]
diff --git a/src/boost/libs/proto/example/rgb.cpp b/src/boost/libs/proto/example/rgb.cpp
new file mode 100644
index 000000000..51b0f459f
--- /dev/null
+++ b/src/boost/libs/proto/example/rgb.cpp
@@ -0,0 +1,102 @@
+//[ RGB
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is a simple example of doing arbitrary type manipulations with proto
+// transforms. It takes some expression involving primary colors and combines
+// the colors according to arbitrary rules. It is a port of the RGB example
+// from PETE (http://www.codesourcery.com/pooma/download.html).
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+namespace proto = boost::proto;
+
+struct RedTag
+{
+ friend std::ostream &operator <<(std::ostream &sout, RedTag)
+ {
+ return sout << "This expression is red.";
+ }
+};
+
+struct BlueTag
+{
+ friend std::ostream &operator <<(std::ostream &sout, BlueTag)
+ {
+ return sout << "This expression is blue.";
+ }
+};
+
+struct GreenTag
+{
+ friend std::ostream &operator <<(std::ostream &sout, GreenTag)
+ {
+ return sout << "This expression is green.";
+ }
+};
+
+typedef proto::terminal<RedTag>::type RedT;
+typedef proto::terminal<BlueTag>::type BlueT;
+typedef proto::terminal<GreenTag>::type GreenT;
+
+struct Red;
+struct Blue;
+struct Green;
+
+///////////////////////////////////////////////////////////////////////////////
+// A transform that produces new colors according to some arbitrary rules:
+// red & green give blue, red & blue give green, blue and green give red.
+struct Red
+ : proto::or_<
+ proto::plus<Green, Blue>
+ , proto::plus<Blue, Green>
+ , proto::plus<Red, Red>
+ , proto::terminal<RedTag>
+ >
+{};
+
+struct Green
+ : proto::or_<
+ proto::plus<Red, Blue>
+ , proto::plus<Blue, Red>
+ , proto::plus<Green, Green>
+ , proto::terminal<GreenTag>
+ >
+{};
+
+struct Blue
+ : proto::or_<
+ proto::plus<Red, Green>
+ , proto::plus<Green, Red>
+ , proto::plus<Blue, Blue>
+ , proto::terminal<BlueTag>
+ >
+{};
+
+struct RGB
+ : proto::or_<
+ proto::when< Red, RedTag() >
+ , proto::when< Blue, BlueTag() >
+ , proto::when< Green, GreenTag() >
+ >
+{};
+
+template<typename Expr>
+void printColor(Expr const & expr)
+{
+ int i = 0; // dummy state and data parameter, not used
+ std::cout << RGB()(expr, i, i) << std::endl;
+}
+
+int main()
+{
+ printColor(RedT() + GreenT());
+ printColor(RedT() + GreenT() + BlueT());
+ printColor(RedT() + (GreenT() + BlueT()));
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/tarray.cpp b/src/boost/libs/proto/example/tarray.cpp
new file mode 100644
index 000000000..338f69b1e
--- /dev/null
+++ b/src/boost/libs/proto/example/tarray.cpp
@@ -0,0 +1,222 @@
+//[ TArray
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example constructs a mini-library for linear algebra, using
+// expression templates to eliminate the need for temporaries when
+// adding arrays of numbers. It duplicates the TArray example from
+// PETE (http://www.codesourcery.com/pooma/download.html)
+
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+// This grammar describes which TArray expressions
+// are allowed; namely, int and array terminals
+// plus, minus, multiplies and divides of TArray expressions.
+struct TArrayGrammar
+ : proto::or_<
+ proto::terminal< int >
+ , proto::terminal< int[3] >
+ , proto::plus< TArrayGrammar, TArrayGrammar >
+ , proto::minus< TArrayGrammar, TArrayGrammar >
+ , proto::multiplies< TArrayGrammar, TArrayGrammar >
+ , proto::divides< TArrayGrammar, TArrayGrammar >
+ >
+{};
+
+template<typename Expr>
+struct TArrayExpr;
+
+// Tell proto that in the TArrayDomain, all
+// expressions should be wrapped in TArrayExpr<> and
+// must conform to the TArrayGrammar
+struct TArrayDomain
+ : proto::domain<proto::generator<TArrayExpr>, TArrayGrammar>
+{};
+
+// Here is an evaluation context that indexes into a TArray
+// expression, and combines the result.
+struct TArraySubscriptCtx
+ : proto::callable_context< TArraySubscriptCtx const >
+{
+ typedef int result_type;
+
+ TArraySubscriptCtx(std::ptrdiff_t i)
+ : i_(i)
+ {}
+
+ // Index array terminals with our subscript. Everything
+ // else will be handled by the default evaluation context.
+ int operator ()(proto::tag::terminal, int const (&data)[3]) const
+ {
+ return data[this->i_];
+ }
+
+ std::ptrdiff_t i_;
+};
+
+// Here is an evaluation context that prints a TArray expression.
+struct TArrayPrintCtx
+ : proto::callable_context< TArrayPrintCtx const >
+{
+ typedef std::ostream &result_type;
+
+ TArrayPrintCtx() {}
+
+ std::ostream &operator ()(proto::tag::terminal, int i) const
+ {
+ return std::cout << i;
+ }
+
+ std::ostream &operator ()(proto::tag::terminal, int const (&arr)[3]) const
+ {
+ return std::cout << '{' << arr[0] << ", " << arr[1] << ", " << arr[2] << '}';
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::plus, L const &l, R const &r) const
+ {
+ return std::cout << '(' << l << " + " << r << ')';
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::minus, L const &l, R const &r) const
+ {
+ return std::cout << '(' << l << " - " << r << ')';
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::multiplies, L const &l, R const &r) const
+ {
+ return std::cout << l << " * " << r;
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::divides, L const &l, R const &r) const
+ {
+ return std::cout << l << " / " << r;
+ }
+};
+
+// Here is the domain-specific expression wrapper, which overrides
+// operator [] to evaluate the expression using the TArraySubscriptCtx.
+template<typename Expr>
+struct TArrayExpr
+ : proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain>
+{
+ typedef proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain> base_type;
+
+ TArrayExpr( Expr const & expr = Expr() )
+ : base_type( expr )
+ {}
+
+ // Use the TArraySubscriptCtx to implement subscripting
+ // of a TArray expression tree.
+ int operator []( std::ptrdiff_t i ) const
+ {
+ TArraySubscriptCtx const ctx(i);
+ return proto::eval(*this, ctx);
+ }
+
+ // Use the TArrayPrintCtx to display a TArray expression tree.
+ friend std::ostream &operator <<(std::ostream &sout, TArrayExpr<Expr> const &expr)
+ {
+ TArrayPrintCtx const ctx;
+ return proto::eval(expr, ctx);
+ }
+};
+
+// Here is our TArray terminal, implemented in terms of TArrayExpr
+// It is basically just an array of 3 integers.
+struct TArray
+ : TArrayExpr< proto::terminal< int[3] >::type >
+{
+ explicit TArray( int i = 0, int j = 0, int k = 0 )
+ {
+ (*this)[0] = i;
+ (*this)[1] = j;
+ (*this)[2] = k;
+ }
+
+ // Here we override operator [] to give read/write access to
+ // the elements of the array. (We could use the TArrayExpr
+ // operator [] if we made the subscript context smarter about
+ // returning non-const reference when appropriate.)
+ int &operator [](std::ptrdiff_t i)
+ {
+ return proto::value(*this)[i];
+ }
+
+ int const &operator [](std::ptrdiff_t i) const
+ {
+ return proto::value(*this)[i];
+ }
+
+ // Here we define a operator = for TArray terminals that
+ // takes a TArray expression.
+ template< typename Expr >
+ TArray &operator =(Expr const & expr)
+ {
+ // proto::as_expr<TArrayDomain>(expr) is the same as
+ // expr unless expr is an integer, in which case it
+ // is made into a TArrayExpr terminal first.
+ return this->assign(proto::as_expr<TArrayDomain>(expr));
+ }
+
+ template< typename Expr >
+ TArray &printAssign(Expr const & expr)
+ {
+ *this = expr;
+ std::cout << *this << " = " << expr << std::endl;
+ return *this;
+ }
+
+private:
+ template< typename Expr >
+ TArray &assign(Expr const & expr)
+ {
+ // expr[i] here uses TArraySubscriptCtx under the covers.
+ (*this)[0] = expr[0];
+ (*this)[1] = expr[1];
+ (*this)[2] = expr[2];
+ return *this;
+ }
+};
+
+int main()
+{
+ TArray a(3,1,2);
+
+ TArray b;
+
+ std::cout << a << std::endl;
+ std::cout << b << std::endl;
+
+ b[0] = 7; b[1] = 33; b[2] = -99;
+
+ TArray c(a);
+
+ std::cout << c << std::endl;
+
+ a = 0;
+
+ std::cout << a << std::endl;
+ std::cout << b << std::endl;
+ std::cout << c << std::endl;
+
+ a = b + c;
+
+ std::cout << a << std::endl;
+
+ a.printAssign(b+c*(b + 3*c));
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/vec3.cpp b/src/boost/libs/proto/example/vec3.cpp
new file mode 100644
index 000000000..2da948725
--- /dev/null
+++ b/src/boost/libs/proto/example/vec3.cpp
@@ -0,0 +1,184 @@
+//[ Vec3
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is a simple example using proto::extends to extend a terminal type with
+// additional behaviors, and using custom contexts and proto::eval for
+// evaluating expressions. It is a port of the Vec3 example
+// from PETE (http://www.codesourcery.com/pooma/download.html).
+
+#include <iostream>
+#include <functional>
+#include <boost/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/proto_typeof.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+// Here is an evaluation context that indexes into a Vec3
+// expression, and combines the result.
+struct Vec3SubscriptCtx
+ : proto::callable_context< Vec3SubscriptCtx const >
+{
+ typedef int result_type;
+
+ Vec3SubscriptCtx(int i)
+ : i_(i)
+ {}
+
+ // Index array terminals with our subscript. Everything
+ // else will be handled by the default evaluation context.
+ int operator ()(proto::tag::terminal, int const (&arr)[3]) const
+ {
+ return arr[this->i_];
+ }
+
+ int i_;
+};
+
+// Here is an evaluation context that counts the number
+// of Vec3 terminals in an expression.
+struct CountLeavesCtx
+ : proto::callable_context< CountLeavesCtx, proto::null_context >
+{
+ CountLeavesCtx()
+ : count(0)
+ {}
+
+ typedef void result_type;
+
+ void operator ()(proto::tag::terminal, int const(&)[3])
+ {
+ ++this->count;
+ }
+
+ int count;
+};
+
+struct iplus : std::plus<int>, proto::callable {};
+
+// Here is a transform that does the same thing as the above context.
+// It demonstrates the use of the std::plus<> function object
+// with the fold transform. With minor modifications, this
+// transform could be used to calculate the leaf count at compile
+// time, rather than at runtime.
+struct CountLeaves
+ : proto::or_<
+ // match a Vec3 terminal, return 1
+ proto::when<proto::terminal<int[3]>, mpl::int_<1>() >
+ // match a terminal, return int() (which is 0)
+ , proto::when<proto::terminal<_>, int() >
+ // fold everything else, using std::plus<> to add
+ // the leaf count of each child to the accumulated state.
+ , proto::otherwise< proto::fold<_, int(), iplus(CountLeaves, proto::_state) > >
+ >
+{};
+
+// Here is the Vec3 struct, which is a vector of 3 integers.
+struct Vec3
+ : proto::extends<proto::terminal<int[3]>::type, Vec3>
+{
+ explicit Vec3(int i=0, int j=0, int k=0)
+ {
+ (*this)[0] = i;
+ (*this)[1] = j;
+ (*this)[2] = k;
+ }
+
+ int &operator [](int i)
+ {
+ return proto::value(*this)[i];
+ }
+
+ int const &operator [](int i) const
+ {
+ return proto::value(*this)[i];
+ }
+
+ // Here we define a operator = for Vec3 terminals that
+ // takes a Vec3 expression.
+ template< typename Expr >
+ Vec3 &operator =(Expr const & expr)
+ {
+ typedef Vec3SubscriptCtx const CVec3SubscriptCtx;
+ (*this)[0] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(0));
+ (*this)[1] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(1));
+ (*this)[2] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(2));
+ return *this;
+ }
+
+ // This copy-assign is needed because a template is never
+ // considered for copy assignment.
+ Vec3 &operator=(Vec3 const &that)
+ {
+ (*this)[0] = that[0];
+ (*this)[1] = that[1];
+ (*this)[2] = that[2];
+ return *this;
+ }
+
+ void print() const
+ {
+ std::cout << '{' << (*this)[0]
+ << ", " << (*this)[1]
+ << ", " << (*this)[2]
+ << '}' << std::endl;
+ }
+};
+
+// The count_leaves() function uses the CountLeaves transform and
+// to count the number of leaves in an expression.
+template<typename Expr>
+int count_leaves(Expr const &expr)
+{
+ // Count the number of Vec3 terminals using the
+ // CountLeavesCtx evaluation context.
+ CountLeavesCtx ctx;
+ proto::eval(expr, ctx);
+
+ // This is another way to count the leaves using a transform.
+ int i = 0;
+ BOOST_ASSERT( CountLeaves()(expr, i, i) == ctx.count );
+
+ return ctx.count;
+}
+
+int main()
+{
+ Vec3 a, b, c;
+
+ c = 4;
+
+ b[0] = -1;
+ b[1] = -2;
+ b[2] = -3;
+
+ a = b + c;
+
+ a.print();
+
+ Vec3 d;
+ BOOST_PROTO_AUTO(expr1, b + c);
+ d = expr1;
+ d.print();
+
+ int num = count_leaves(expr1);
+ std::cout << num << std::endl;
+
+ BOOST_PROTO_AUTO(expr2, b + 3 * c);
+ num = count_leaves(expr2);
+ std::cout << num << std::endl;
+
+ BOOST_PROTO_AUTO(expr3, b + c * d);
+ num = count_leaves(expr3);
+ std::cout << num << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/vector.cpp b/src/boost/libs/proto/example/vector.cpp
new file mode 100644
index 000000000..a2b80fe8b
--- /dev/null
+++ b/src/boost/libs/proto/example/vector.cpp
@@ -0,0 +1,241 @@
+//[ Vector
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
+// expressions using std::vector<>, a non-proto type. It is a port of the
+// Vector example from PETE (http://www.codesourcery.com/pooma/download.html).
+
+#include <vector>
+#include <iostream>
+#include <stdexcept>
+#include <boost/mpl/bool.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/utility/enable_if.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename Expr>
+struct VectorExpr;
+
+// Here is an evaluation context that indexes into a std::vector
+// expression and combines the result.
+struct VectorSubscriptCtx
+{
+ VectorSubscriptCtx(std::size_t i)
+ : i_(i)
+ {}
+
+ // Unless this is a vector terminal, use the
+ // default evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::default_eval<Expr, VectorSubscriptCtx const>
+ {};
+
+ // Index vector terminals with our subscript.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<std::vector<_, _> > >
+ >::type
+ >
+ {
+ typedef typename proto::result_of::value<Expr>::type::value_type result_type;
+
+ result_type operator ()(Expr &expr, VectorSubscriptCtx const &ctx) const
+ {
+ return proto::value(expr)[ctx.i_];
+ }
+ };
+
+ std::size_t i_;
+};
+
+// Here is an evaluation context that verifies that all the
+// vectors in an expression have the same size.
+struct VectorSizeCtx
+{
+ VectorSizeCtx(std::size_t size)
+ : size_(size)
+ {}
+
+ // Unless this is a vector terminal, use the
+ // null evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::null_eval<Expr, VectorSizeCtx const>
+ {};
+
+ // Index array terminals with our subscript. Everything
+ // else will be handled by the default evaluation context.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<std::vector<_, _> > >
+ >::type
+ >
+ {
+ typedef void result_type;
+
+ result_type operator ()(Expr &expr, VectorSizeCtx const &ctx) const
+ {
+ if(ctx.size_ != proto::value(expr).size())
+ {
+ throw std::runtime_error("LHS and RHS are not compatible");
+ }
+ }
+ };
+
+ std::size_t size_;
+};
+
+// A grammar which matches all the assignment operators,
+// so we can easily disable them.
+struct AssignOps
+ : proto::switch_<struct AssignOpsCases>
+{};
+
+// Here are the cases used by the switch_ above.
+struct AssignOpsCases
+{
+ template<typename Tag, int D = 0> struct case_ : proto::not_<_> {};
+
+ template<int D> struct case_< proto::tag::plus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::minus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::multiplies_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::divides_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::modulus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_left_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_right_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_and_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_or_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_xor_assign, D > : _ {};
+};
+
+// A vector grammar is a terminal or some op that is not an
+// assignment op. (Assignment will be handled specially.)
+struct VectorGrammar
+ : proto::or_<
+ proto::terminal<_>
+ , proto::and_<proto::nary_expr<_, proto::vararg<VectorGrammar> >, proto::not_<AssignOps> >
+ >
+{};
+
+// Expressions in the vector domain will be wrapped in VectorExpr<>
+// and must conform to the VectorGrammar
+struct VectorDomain
+ : proto::domain<proto::generator<VectorExpr>, VectorGrammar>
+{};
+
+// Here is VectorExpr, which extends a proto expr type by
+// giving it an operator [] which uses the VectorSubscriptCtx
+// to evaluate an expression with a given index.
+template<typename Expr>
+struct VectorExpr
+ : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>
+{
+ explicit VectorExpr(Expr const &expr)
+ : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>(expr)
+ {}
+
+ // Use the VectorSubscriptCtx to implement subscripting
+ // of a Vector expression tree.
+ typename proto::result_of::eval<Expr const, VectorSubscriptCtx const>::type
+ operator []( std::size_t i ) const
+ {
+ VectorSubscriptCtx const ctx(i);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define a trait type for detecting vector terminals, to
+// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
+template<typename T>
+struct IsVector
+ : mpl::false_
+{};
+
+template<typename T, typename A>
+struct IsVector<std::vector<T, A> >
+ : mpl::true_
+{};
+
+namespace VectorOps
+{
+ // This defines all the overloads to make expressions involving
+ // std::vector to build expression templates.
+ BOOST_PROTO_DEFINE_OPERATORS(IsVector, VectorDomain)
+
+ typedef VectorSubscriptCtx const CVectorSubscriptCtx;
+
+ // Assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &assign(std::vector<T, A> &arr, Expr const &expr)
+ {
+ VectorSizeCtx const size(arr.size());
+ proto::eval(proto::as_expr<VectorDomain>(expr), size); // will throw if the sizes don't match
+ for(std::size_t i = 0; i < arr.size(); ++i)
+ {
+ arr[i] = proto::as_expr<VectorDomain>(expr)[i];
+ }
+ return arr;
+ }
+
+ // Add-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &operator +=(std::vector<T, A> &arr, Expr const &expr)
+ {
+ VectorSizeCtx const size(arr.size());
+ proto::eval(proto::as_expr<VectorDomain>(expr), size); // will throw if the sizes don't match
+ for(std::size_t i = 0; i < arr.size(); ++i)
+ {
+ arr[i] += proto::as_expr<VectorDomain>(expr)[i];
+ }
+ return arr;
+ }
+}
+
+int main()
+{
+ using namespace VectorOps;
+
+ int i;
+ const int n = 10;
+ std::vector<int> a,b,c,d;
+ std::vector<double> e(n);
+
+ for (i = 0; i < n; ++i)
+ {
+ a.push_back(i);
+ b.push_back(2*i);
+ c.push_back(3*i);
+ d.push_back(i);
+ }
+
+ VectorOps::assign(b, 2);
+ VectorOps::assign(d, a + b * c);
+ a += if_else(d < 30, b, c);
+
+ VectorOps::assign(e, c);
+ e += e - 4 / (c + 1);
+
+ for (i = 0; i < n; ++i)
+ {
+ std::cout
+ << " a(" << i << ") = " << a[i]
+ << " b(" << i << ") = " << b[i]
+ << " c(" << i << ") = " << c[i]
+ << " d(" << i << ") = " << d[i]
+ << " e(" << i << ") = " << e[i]
+ << std::endl;
+ }
+}
+//]
diff --git a/src/boost/libs/proto/example/virtual_member.cpp b/src/boost/libs/proto/example/virtual_member.cpp
new file mode 100644
index 000000000..46183baeb
--- /dev/null
+++ b/src/boost/libs/proto/example/virtual_member.cpp
@@ -0,0 +1,306 @@
+//[ VirtualMember
+// 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)
+//
+// This example demonstrates how to use BOOST_PROTO_EXTENDS_MEMBERS()
+// to add "virtual" data members to expressions within a domain. For
+// instance, with Phoenix you can create a lambda expression such as
+//
+// if_(_1 > 0)[ std::cout << _2 ].else_[ std::cout << _3 ]
+//
+// In the above expression, "else_" is a so-called virtual data member
+// of the expression "if_(_1 > 0)[ std::cout << _2 ]". This example
+// shows how to implement the ".else_" syntax with Proto.
+//
+// ****WARNING****WARNING****WARNING****WARNING****WARNING****WARNING****
+// * The virtual data member feature is experimental and can change at *
+// * any time. Use it at your own risk. *
+// **********************************************************************
+
+#if defined(_MSC_VER) && _MSC_VER == 1310
+#error "Sorry, this example doesn\'t work with MSVC 7.1"
+#endif
+
+#include <iostream>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/typeof/std/ostream.hpp>
+#include <boost/proto/proto.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+namespace mini_lambda
+{
+ // A callable PolymorphicFunctionObject that wraps
+ // fusion::at()
+ struct at : proto::callable
+ {
+ template<class Sig>
+ struct result;
+
+ template<class This, class Vector, class N>
+ struct result<This(Vector, N)>
+ : fusion::result_of::at<
+ typename boost::remove_reference<Vector>::type
+ , typename boost::remove_reference<N>::type
+ >
+ {};
+
+ template<class Vector, class N>
+ typename fusion::result_of::at<Vector const, N>::type
+ operator()(Vector const &vector, N) const
+ {
+ return fusion::at<N>(vector);
+ }
+ };
+
+ // An MPL IntegralConstant
+ template<class N>
+ struct placeholder
+ {
+ typedef N type;
+ typedef typename N::tag tag;
+ typedef typename N::next next;
+ typedef typename N::prior prior;
+ typedef typename N::value_type value_type;
+ static const value_type value = N::value;
+ };
+
+ // Some keyword types for our lambda EDSL
+ namespace keyword
+ {
+ struct if_ {};
+ struct else_ {};
+ struct do_ {};
+ struct while_ {};
+ struct try_ {};
+ struct catch_ {};
+ }
+
+ // Forward declaration for the mini-lambda grammar
+ struct eval_if_else;
+
+ // Forward declaration for the mini-lambda expression wrapper
+ template<class E>
+ struct expression;
+
+ // The grammar for mini-lambda expressions with transforms for
+ // evaluating the lambda expression.
+ struct grammar
+ : proto::or_<
+ // When evaluating a placeholder, use the placeholder
+ // to index into the "data" parameter, which is a fusion
+ // vector containing the arguments to the lambda expression.
+ proto::when<
+ proto::terminal<placeholder<_> >
+ , at(proto::_data, proto::_value)
+ >
+ // When evaluating if/then/else expressions of the form
+ // "if_( E0 )[ E1 ].else_[ E2 ]", pass E0, E1 and E2 to
+ // eval_if_else along with the "data" parameter. Note the
+ // use of proto::member<> to match binary expressions like
+ // "X.Y" where "Y" is a virtual data member.
+ , proto::when<
+ proto::subscript<
+ proto::member<
+ proto::subscript<
+ proto::function<
+ proto::terminal<keyword::if_>
+ , grammar
+ >
+ , grammar
+ >
+ , proto::terminal<keyword::else_>
+ >
+ , grammar
+ >
+ , eval_if_else(
+ proto::_right(proto::_left(proto::_left(proto::_left)))
+ , proto::_right(proto::_left(proto::_left))
+ , proto::_right
+ , proto::_data
+ )
+ >
+ , proto::otherwise<
+ proto::_default<grammar>
+ >
+ >
+ {};
+
+ // A callable PolymorphicFunctionObject that evaluates
+ // if/then/else expressions.
+ struct eval_if_else : proto::callable
+ {
+ typedef void result_type;
+
+ template<typename If, typename Then, typename Else, typename Args>
+ void operator()(If const &if_, Then const &then_, Else const &else_, Args const &args) const
+ {
+ if(grammar()(if_, 0, args))
+ {
+ grammar()(then_, 0, args);
+ }
+ else
+ {
+ grammar()(else_, 0, args);
+ }
+ }
+ };
+
+ // Define the mini-lambda domain, in which all expressions are
+ // wrapped in mini_lambda::expression.
+ struct domain
+ : proto::domain<proto::pod_generator<expression> >
+ {};
+
+ // A simple transform for computing the arity of
+ // a lambda expression.
+ struct arity_of
+ : proto::or_<
+ proto::when<
+ proto::terminal< placeholder<_> >
+ , mpl::next<proto::_value>()
+ >
+ , proto::when<
+ proto::terminal<_>
+ , mpl::int_<0>()
+ >
+ , proto::otherwise<
+ proto::fold<
+ _
+ , mpl::int_<0>()
+ , mpl::max<arity_of, proto::_state>()
+ >
+ >
+ >
+ {};
+
+ // Here is the mini-lambda expression wrapper. It serves two purposes:
+ // 1) To define operator() overloads that evaluate the lambda expression, and
+ // 2) To define virtual data members like "else_" so that we can write
+ // expressions like "if_(X)[Y].else_[Z]".
+ template<class E>
+ struct expression
+ {
+ BOOST_PROTO_BASIC_EXTENDS(E, expression<E>, domain)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ // Use BOOST_PROTO_EXTENDS_MEMBERS() to define "virtual"
+ // data members that all expressions in the mini-lambda
+ // domain will have. They can be used to create expressions
+ // like "if_(x)[y].else_[z]" and "do_[y].while_(z)".
+ BOOST_PROTO_EXTENDS_MEMBERS(
+ ((keyword::else_, else_))
+ ((keyword::while_, while_))
+ ((keyword::catch_, catch_))
+ )
+
+ // Calculate the arity of this lambda expression
+ static int const arity = boost::result_of<arity_of(E)>::type::value;
+
+ // Define overloads of operator() that evaluate the lambda
+ // expression for up to 3 arguments.
+
+ // Don't try to compute the return type of the lambda if
+ // it isn't nullary.
+ typename mpl::eval_if_c<
+ 0 != arity
+ , mpl::identity<void>
+ , boost::result_of<grammar(
+ E const &
+ , int const &
+ , fusion::vector<> &
+ )>
+ >::type
+ operator()() const
+ {
+ BOOST_MPL_ASSERT_RELATION(arity, ==, 0);
+ fusion::vector<> args;
+ return grammar()(proto_base(), 0, args);
+ }
+
+ #define BOOST_PROTO_LOCAL_MACRO( \
+ N, typename_A, A_const_ref, A_const_ref_a, a \
+ ) \
+ template<typename_A(N)> \
+ typename boost::result_of<grammar( \
+ E const & \
+ , int const & \
+ , fusion::vector<A_const_ref(N)> & \
+ )>::type \
+ operator ()(A_const_ref_a(N)) const \
+ { \
+ BOOST_MPL_ASSERT_RELATION(arity, <=, N); \
+ fusion::vector<A_const_ref(N)> args(a(N)); \
+ return grammar()(proto_base(), 0, args); \
+ }
+ // Repeats BOOST_PROTO_LOCAL_MACRO macro for N=1 to 3
+ // inclusive (because there are only 3 placeholders)
+ #define BOOST_PROTO_LOCAL_a BOOST_PROTO_a
+ #define BOOST_PROTO_LOCAL_LIMITS (1, 3)
+ #include BOOST_PROTO_LOCAL_ITERATE()
+ };
+
+ namespace placeholders
+ {
+ typedef placeholder<mpl::int_<0> > _1_t;
+ typedef placeholder<mpl::int_<1> > _2_t;
+ typedef placeholder<mpl::int_<2> > _3_t;
+
+ // Define some placeholders
+ expression<proto::terminal<_1_t>::type> const _1 = {{{}}};
+ expression<proto::terminal<_2_t>::type> const _2 = {{{}}};
+ expression<proto::terminal<_3_t>::type> const _3 = {{{}}};
+
+ // Define the if_() statement
+ template<typename E>
+ typename proto::result_of::make_expr<proto::tag::function, domain
+ , keyword::if_
+ , E const &
+ >::type const
+ if_(E const &e)
+ {
+ return proto::make_expr<proto::tag::function, domain>(
+ keyword::if_()
+ , boost::ref(e)
+ );
+ }
+ }
+
+ using placeholders::if_;
+}
+
+int main()
+{
+ using namespace mini_lambda::placeholders;
+
+ // OK, we can create if/then/else lambda expressions
+ // and evaluate them.
+ if_(_1 > 0)
+ [
+ std::cout << _2 << '\n'
+ ]
+ .else_
+ [
+ std::cout << _3 << '\n'
+ ]
+ (-42, "positive", "non-positive");
+
+ // Even though all expressions in the mini-lambda
+ // domain have members named else_, while_, and catch_,
+ // they all occupy the same byte in the expression.
+ BOOST_MPL_ASSERT_RELATION(sizeof(_1), ==, 2);
+
+ return 0;
+}
+//]