From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- src/boost/libs/proto/example/calc3.cpp | 154 +++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/boost/libs/proto/example/calc3.cpp (limited to 'src/boost/libs/proto/example/calc3.cpp') diff --git a/src/boost/libs/proto/example/calc3.cpp b/src/boost/libs/proto/example/calc3.cpp new file mode 100644 index 00000000..9ca97d65 --- /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 +#include +#include +#include +#include +#include +#include +namespace mpl = boost::mpl; +namespace proto = boost::proto; +using proto::_; + +// Will be used to define the placeholders _1 and _2 +template 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() > > + + > +{}; + +// 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 +struct calculator_arity + : boost::result_of +{}; + +template +struct calculator_expression; + +// Tell proto how to generate expressions in the calculator_domain +struct calculator_domain + : proto::domain > +{}; + +// 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 + double operator ()(proto::tag::terminal, placeholder) const + { + return d[ I() - 1 ]; + } +}; + +// Wrap all calculator expressions in this type, which defines +// operator () to evaluate the expression. +template +struct calculator_expression + : proto::extends, calculator_domain> +{ + typedef + proto::extends, calculator_domain> + base_type; + + explicit calculator_expression(Expr const &expr = Expr()) + : base_type(expr) + {} + + BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression) + + // Override operator () to evaluate the expression + double operator ()() const + { + // Assert that the expression has arity 0 + BOOST_MPL_ASSERT_RELATION(0, ==, calculator_arity::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::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::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 > >::type> const _1; +calculator_expression > >::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; +} +//] -- cgit v1.2.3