Copyright © 2007 -2008 Shunsuke Sogame
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)
Table of Contents
“An Egg to day is better than a Hen tomorrow.” -- Benjamin Franklin
This library is not part of Boost (yet).
Egg is a header-only library for building Polymorphic Function Object which can be used with Boost.Lambda. Such a function object is called a Major Function Object.
Egg mainly provides three components:
In short, a Polymorphic
Function Object is a Function
Object which can be used with Boost.ResultOf. (See also result_of
tutorial.) Boost.ResultOf is an MPL
Metafunction to extract function return types without the help of
C++0x decltype
, which enables
you to do the functional programming in C++03.
Fortunately, Polymorphic Function Object types are a superset of Adaptable Function Object types, so that you don't need extra efforts to play with Egg if you're already familiar with that concept. For example, the followings are trivially conforming Polymorphic Function Object types:
std::less<int>
boost::bind(...)
returns.
boost::function<...>
These function objects have a nested result_type
,
meaning that their return type doesn't depend on its argument types. Such
a function object is trivially conforming Polymorphic
Function Object. It is really easy to build one:
struct T_to_string { typedef std::string result_type; template<class T> result_type operator()(T const &t) const { return boost::lexical_cast<std::string>(t); } }; T_to_string const to_string = {};
Egg doesn't appreciate |
|
|
Note that to_string
can be
used also with boost::lambda::bind
. In other words, it is a model of
Major Function Object.
Unfortunately, if you need a Polymorphic Function Object whose return type depends on its argument types, it is not easy. There are many compiler bugs, pitfalls, and typings.
Egg is the framework for building such function objects.
struct little_plus { template<class Me, class X, class Y> struct apply : boost::remove_cv<X> { }; template<class Re, class X, class Y> Re call(X &x, Y &y) const { return x + y; } }; typedef function<little_plus> T_plus; T_plus const plus = {{}}; void egg_builder() { result_of_<T_plus(int, int)>::type r = plus(1, 2); BOOST_CHECK(r == 3); namespace bll = boost::lambda; using std::string; string one("1"); BOOST_CHECK("12" == bll::bind(plus, bll::_1, string("2"))(one)); } result_of_pipable<T_plus>::type const my_plus = BOOST_EGG_PIPABLE({{}}); void egg_adaptor() { int r = 1|my_plus(2)|my_plus(3); BOOST_CHECK(r == 1+2+3); result_of_<T_pipable(T_plus const &)>::type your_plus = pipable(plus); BOOST_CHECK((1|your_plus(2)) == 1+2); }
Determining return type. |
|
Building Little Function into Major Function Object type. |
|
This is Extension method emulation in C++. |
|
Using |
As shown above, Egg offers unfamiliar syntax using braces and macros. T_plus
is POD, and
plus
is initialized using
braced-initializer {{}}
. This
ensures plus
is statically
initialized. The static initialization advantages
are:
result_of
instantiation.
Also notice that my_plus
is initialized using "ugly" macro BOOST_EGG_PIPABLE
.
This macro can be regarded as "static-storage function call". In
fact, this macro is a tangled braced-initializer, so that we have no choice
but to use macro.
egg.zip
at Boost.Vault/FunctionObjects
Egg is known to work on the following platforms:
Special thanks to:
callable
.
Any feedbacks can be sent to pstade.mb@gmail.com, Boost developers list or Boost users list.
This document uses the following notation.
Valid expression |
Semantics |
---|---|
An imaginary operator which is the same as |
|
|
|
|
|
A Polymorphic Function Object type which is neither a reference type nor cv-qualified. |
|
A Little Function object |
|
A Little Function type which is neither a reference type nor cv-qualified. |
|
A type which is one of the Forwarding Strategies. |
|
A type which is one of |
|
|
|
|
|
|
An imaginary operator to construct a parameter list. |
|
An imaginary operator to concatenate parameter lists. |
|
An imaginary operator to concatenate tokens. |
|
Also, assume that every expression is placed after:
namespace egg = boost::egg; using namespace egg;
Every example source code can be found at libs/egg/example
.
Last revised: March 30, 2008 at 12:41:55 GMT |