Boost logo

Boost :

Subject: Re: [boost] New libraries implementing C++11 features in C++03
From: Brent Spillner (spillner_at_[hidden])
Date: 2011-11-23 19:06:08


On 23 Nov 2011 10:21:50 Joel de Guzman wrote:
>a good approximation of lambda is already existing in Boost. Namely: bind,
>lambda and phoenix. I posted a Spirit example of lambda in action using
>Phoenix:
>
>http://tinyurl.com/7w2h2r9
>
>Try as hard as you can, but you cannot ever come close to the clarity of
>he syntax presented there. Proponents of locals have cited error-messages
>generated by the compiler as a justification for Locals. Locals is probably
>a good workaround. But hear me out...

First of all, this "trivial" example didn't even compile on the first
machine I tried it on, which had Boost 1.45 (which doesn't expose
qi:_val_type or qi:_1_type). This is a pretty good reminder of the
fact that Phoenix remains a fast moving target (1.45 is less than a
year old) and still appears unnecessarily baroque to new users (why
are typenames that need to be cited in even a basic tutorial prefixed
with an underscore?) Local/Closure, on the other hand, seems to have
a pretty stable interface at this point.

On a machine with 1.48, the example compiles just fine. If you were
to pass std::string::iterators instead of const_iterators to
phrase_parse(), though ( a pretty common class of mistake in the real
world), you get this error message (GCC 4.4.4):

/usr/include/boost/spirit/home/qi/reference.hpp: In member function
'bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const
Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator
= __gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, Context =
boost::spirit::context<boost::fusion::cons<int&, boost::fusion::nil>,
boost::spirit::locals<mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >, Skipper
= boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&,
const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with
Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, Expr =
client::calculator<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
> >, Skipper = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, Attr =
int]::skipper_type, Attribute = int, Subject = const
boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, int(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>]':
/usr/include/boost/spirit/home/qi/parse.hpp:164: instantiated from
'bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&)
[with Iterator = __gnu_cxx::__normal_iterator<char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, Expr = client::calculator<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
> >, Skipper = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, Attr = int]'
/usr/include/boost/spirit/home/qi/parse.hpp:197: instantiated from
'bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const
Expr&, const Skipper&, Attr&) [with Iterator =
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, Expr =
main()::calculator, Skipper = boost::spirit::ascii::space_type, Attr =
int]'
calc3.cpp:101: instantiated from here
/usr/include/boost/spirit/home/qi/reference.hpp:43: error: no matching
function for call to
'boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, int(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type,
boost::spirit::unused_type>::parse(__gnu_cxx::__normal_iterator<char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>&, const __gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >&,
boost::spirit::context<boost::fusion::cons<int&, boost::fusion::nil>,
boost::spirit::locals<mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >&, const
boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >&, int&) const'

But that's nothing; if you omit the '>>' from the expression or term
definition you get the 33 kilochar beauty copied at the bottom of this
email. There have been several postings to this list in the past
about trivial errors (substituting the wrong type or omitting a
forward declaration and so forth) that generate hundreds of kilobytes
of compiler barf with no apparent relation to what is actually wrong
with the source. Yes, the compiler is also largely to blame (although
GCC does not seem any worse here than the other mainstream options)
and perhaps someday this will finally get better, but I think you
grossly underestimate the deterrent effect this has on new users and
on wider adoption of Phoenix and similar libraries. Phoenix is great
when you really need it, but there's also quite a lot to be said for
alternatives (including Boost.Local) that don't build massive, fragile
scaffolds of parametric types and in some sense keep what the compiler
'sees' on a given line of source similar to what the programmer sees
in a text editor.

Don't get me wrong; I think Phoenix is an amazing piece of work, and
for someone who needs late binding and lazy evaluation in an
expression (or a small DSEL without depending on an external parser
generator) it's a godsend. I just happen to believe that you could
say the same things about Boost.Local--- if this is what you need,
it's *exactly* what you need. Many Boost users may never need local
functions, but you could again say the same thing about the vast
majority of the 113 official components of 1.48. If you want to keep
Boost limited to the bare essentials, it's already far too late. The
bar for entry should be that the library is well designed, well
documented, well implemented, serves a need that a nontrivial number
of users have, and isn't likely to interfere with the implementation
of other future language or Boost features, not that it will be used
just as frequently as enable_if<> or optional<>.

>Keep in mind that Boost has been at the forefront of C++ library development.
>It is because of these libraries that push the limits of C++ that we see the
>advancement in C++ that we enjoy now in C++11. Case in point is Boost Lambda

Hey, that's great. I just think that we all need to recognize that
very little C++ software is written with "push the limits of the
language" as one of the goals in mind. The participants on this
particular list have self-selected for interest in developing
state-of-the-art libraries, but most also have day jobs where they're
just trying to maintain an existing codebase with minimal hassle for
their colleagues and customers, as well as side projects where getting
something running quickly and correctly is more important (if not
always more interesting) than figuring out just how far we can push
overload resolution rules. And probably 99% of Boost users and 99.9%
of potential Boost users aren't the kind of programmers on this list
and have no interest at all in "pushing the envelope"--- they just
want tools with simple, stable syntax and easy debugging, both of
which Local offers. Furthermore, no matter how slick your personal
environment is, it's a simple fact that there are thousands and
thousands of important projects that will never have the benefit of a
C++11 compiler for a variety of reasons.

I *really* don't understand the criticism from several people about
using macros to implement the library. Part of the power of C++ is
that its syntax is extensible, and the preprocessor and operator
overloading are the two mechanisms that enable that. The preprocessor
is part of the language specification, arguably even more so than the
standard library since a (nonconforming) implementation that ships
with only 10% of the standard library implemented is far more useful
in practice than an implementation that ships with only 10% of the
preprocessor implemented. Yes, macros can be abused, as can operator
overloading (as many would criticize Phoenix), but often they're the
most appropriate choice.

There should be only two questions here: are there a nontrivial number
of users who desire or would benefit from local functions, and is
there a better way to provide them than what Lorenzo has chosen?

------------------- Horrific error messages follow ---------------------
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp: In static
member function 'static void boost::spirit::qi::rule<Iterator, T1, T2,
T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&,
const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>, Expr =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::plus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::minus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>, Iterator
= __gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, T1 = int(), T2 =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, T3 =
boost::spirit::unused_type, T4 = boost::spirit::unused_type]':
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:220:
instantiated from 'boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&
boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const
Expr&) [with Expr =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::plus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::minus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>, Iterator
= __gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, T1 = int(), T2 =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, T3 =
boost::spirit::unused_type, T4 = boost::spirit::unused_type]'
calc3.cpp:49: instantiated from
'client::calculator<Iterator>::calculator() [with Iterator =
__gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >]'
calc3.cpp:90: instantiated from here
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:176: error: no
matching function for call to
'assertion_failed(mpl_::failed************
(boost::spirit::qi::rule<Iterator, T1, T2, T3,
T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const
Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>, Expr =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::plus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::minus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>, Iterator
= __gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, T1 = int(), T2 =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, T3 =
boost::spirit::unused_type, T4 =
boost::spirit::unused_type]::error_invalid_expression::************)(boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::plus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::minus_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>))'
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp: In static
member function 'static void boost::spirit::qi::rule<Iterator, T1, T2,
T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&,
const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>, Expr =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::multiplies_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::divides_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>, Iterator
= __gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, T1 = int(), T2 =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, T3 =
boost::spirit::unused_type, T4 = boost::spirit::unused_type]':
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:220:
instantiated from 'boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&
boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const
Expr&) [with Expr =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::multiplies_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::divides_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>, Iterator
= __gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, T1 = int(), T2 =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, T3 =
boost::spirit::unused_type, T4 = boost::spirit::unused_type]'
calc3.cpp:56: instantiated from
'client::calculator<Iterator>::calculator() [with Iterator =
__gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >]'
calc3.cpp:90: instantiated from here
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:176: error: no
matching function for call to
'assertion_failed(mpl_::failed************
(boost::spirit::qi::rule<Iterator, T1, T2, T3,
T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const
Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>, Expr =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::multiplies_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::divides_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>, Iterator
= __gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, T1 = int(), T2 =
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>, T3 =
boost::spirit::unused_type, T4 =
boost::spirit::unused_type]::error_invalid_expression::************)(boost::proto::exprns_::expr<boost::proto::tagns_::tag::multiplies,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
boost::proto::argsns_::list2<const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::multiplies_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right,
boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const char&>, 0l>, const
boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const
char*, std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, int(),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0l>,
boost::spirit::unused_type, boost::spirit::unused_type>&,
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const
boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::divides_assign_eval,
boost::fusion::vector<boost::spirit::attribute<0>,
boost::spirit::argument<0>, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_> > >&>, 0l> >, 2l>&>, 2l>&>, 2l>&>, 2l>))'


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk