Boost C++ Libraries

Next

Chapter 1. Boost.Egg 0.91.0

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

Overview
Preface
Disclaimer
Introduction
Requirements
Portability
Rationale
Acknowledgements
Contact
Notation
Quick Start
Installing Egg
Using Egg
Reading Doc
Concepts
Lexically Typed Object
Pipable Function Object
Ambi Function Object
Major Function Object
Static Function Object
Little Function
result_of tutorial
Forwarding Strategies
Argument list
by_perfect
by_ref
by_cref
by_value
Writing your own strategies
Determining nullary return types
Function Builders
function
function_facade
generator
implicit
poly
static_
variadic
Function Adaptors
ambiN
compose
curryN
uncurry
fix
fuse
unfuse
indirect
lazy
memoize
mono
nestN
perfect
pipable
regular
return_
tagged
Function Objects
adapted_to
always
identity
apply
bll_N
construct
construct_braced1
construct_braced2
construct_variadic1
get
pack
Utilities
expr
infix
bll/result_of.hpp
Configuration
MAX_ARITY
MAX_LINEAR_ARITY
Workarounds
result_of_
detect_result_type.hpp
CONST
OVERLOADED
Version History

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:

So what's Polymorphic Function Object?

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.

Polymorphic Function Object Models?

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:

  • function pointers
  • std::less<int>
  • function objects 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 1
{
    typedef std::string result_type; 2

    template<class T>
    result_type operator()(T const &t) const
    {
        return boost::lexical_cast<std::string>(t);
    }
};

T_to_string const to_string = {};

1

Egg doesn't appreciate std::unary_function<>, because inheriting it keeps types out of POD.

2

argument_type etc are not needed.

Note that to_string can be used also with boost::lambda::bind. In other words, it is a model of Major Function Object.

Egg what for?

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> 1
    { };

    template<class Re, class X, class Y>
    Re call(X &x, Y &y) const
    {
        return x + y;
    }
};

typedef function<little_plus> T_plus; 2
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); 3
    BOOST_CHECK(r == 1+2+3);

    result_of_<T_pipable(T_plus const &)>::type your_plus = pipable(plus); 4
    BOOST_CHECK((1|your_plus(2)) == 1+2);
}

1

Determining return type.

2

Building Little Function into Major Function Object type.

3

This is Extension method emulation in C++.

4

Using pipable as higher-order function.

POD-oriented programming

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:

  • No runtime overhead.
  • No compile-time overhead of result_of instantiation.
  • No "static initialization order fiasco".

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 is known to work on the following platforms:

  • Microsoft Visual C++ .NET Version 7.1 SP1
  • Microsoft Visual C++ 2005 Express Edition SP1
  • Microsoft Visual C++ 2008 Express Edition
  • MinGW with GCC 3.4.4
  • MinGW with GCC 4.1.2
  • Egg works around the Forwarding Problem.
  • Egg provides the way of static initialization.
  • Egg doesn't introduce any new "traits".

Special thanks to:

  • Dan Marsden, review manager of this library.
  • David Abrahams. The Forwarding Problem workaround is based on his callable.
  • Eric Niebler, who pointed out importance of static initialization.
  • Cryolite, Hitobashira, Kazuhiro Inaba, Takeshi Mouri, yotto-k, and Yusuke Kajimoto.

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

__decltype

An imaginary operator which is the same as decltype of C++0x.

__typeof(a)

boost::remove_cv<boost::remove_reference<__decltype(a)>::type>::type

__const(a)

static_cast<__typeof(a) const>(a)

__pfo

A Polymorphic Function Object

__PFo

A Polymorphic Function Object type which is neither a reference type nor cv-qualified.

__lit

A Little Function object

__Lit

A Little Function type which is neither a reference type nor cv-qualified.

__Stg

A type which is one of the Forwarding Strategies.

__Bytag

A type which is one of by_perfect, by_ref, by_cref, and by_value.

__ud

boost::use_default

__mpl

boost::mpl

[a1,...,aN]

An imaginary operator to construct a parameter list.

++

An imaginary operator to concatenate parameter lists.

%%

An imaginary operator to concatenate tokens.

__MAX_PACK_ARITY

10

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


Next