calc3.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 156 行
CPP
156 行
//[ 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/xpressive/proto/proto.hpp>#include <boost/xpressive/proto/context.hpp>#include <boost/xpressive/proto/transform.hpp>using namespace boost;// Will be used to define the placeholders _1 and _2template<typename I> struct placeholder : I {};using proto::_;// 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::_arg > // 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 visitor, which// is not used, is mpl::void_.template<typename Expr>struct calculator_arity : boost::result_of<CalculatorGrammar(Expr, mpl::int_<0>, mpl::void_)>{};// For expressions in the calculator domain, operator ()// will be special; it will evaluate the expression.struct calculator_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<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) {} using base_type::operator =; // 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); }};// Tell proto how to generate expressions in the calculator_domainstruct calculator_domain : proto::domain<proto::generator<calculator_expression> >{};// 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;}//]
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?