Boost C++ Libraries

PrevUpHomeNext

Concepts

Lexically Typed Object
Pipable Function Object
Ambi Function Object
Major Function Object
Static Function Object
Little Function
result_of tutorial
Description

A Lexically Typed Object is a named lvalue whose type is referable by using prefix T_.

Requirements

For any Lexically Typed Object a the following must be met:

  • a is a named lvalue.
  • If token a doesn't begin with a single underscore, T_%%a is __typeof(a); TT%%a otherwise.
Example

typedef int T_a;
T_a a;

typedef int TT_1;
TT_1 _1;

See also
Description

A Pipable Function Object is a Function Object which behaves as if it were a "pipe" using operator| and operator|=.

[Tip] Tip

According to Charles Brockman's research, "pipable" is not misspelling of "pipeable".

Refinement of
Requirements

In addition to the requirements defined in the refinements, for any Pipable Function Object p the following must be met:

  • x|p(x1,...,xN) is a valid expresion if and only if p(x1,...,xN)|=x is a valid expression.
  • x|p(x1,...,xN) and p(x1,...,xN)|=x have the same effects.
  • If N is 0, then x|p(), x|p, p|=x, and p()|=x are valid expressions which have the same effects.
  • operator| works with left-to-right associativity.
  • operator|= works with right-to-left associativity.
Example

struct pipable
{
    pipable operator()() const
    {
        return *this;
    }
};

int operator|(int ch, pipable)
{
    return std::toupper(ch);
}

int operator|=(pipable, int ch)
{
    return std::toupper(ch);
}

void test()
{
    pipable const to_upper = {};

    int maybeA = 'a'|to_upper();
    BOOST_CHECK(maybeA == 'A');

    int maybeB = to_upper|='b';
    BOOST_CHECK(maybeB == 'B');
}

See also
Description

An Ambi Function Object is a Pipable Function Object which can be used also as free function.

[Tip] Tip

"ambi" is short of "ambidextrous".

Refinement of
Requirements

In addition to the requirements defined in the refinements, for any Ambi Function Object i the following must be met:

  • x|i(x1,...,xN) is a valid expression if and only if i(x, x1,...,xN) is a valid expression.
  • x|i(x1,...,xN) and i(x, x1,...,xN) have the same effects.
[Note] Note

A Pipable Function Object can be overloaded with different arities, whereas Ambi Function Object cannot.

Example

struct ambi
{
    int operator()(int ch) const
    {
        return std::tolower(ch);
    }

    ambi operator()() const
    {
        return *this;
    }
};

int operator|(int ch, ambi)
{
    return std::tolower(ch);
}

int operator|=(ambi, int ch)
{
    return std::tolower(ch);
}

void test()
{
    ambi const to_lower = {};

    int maybei = 'I'|to_lower;
    BOOST_CHECK(maybei == 'i');

    int maybej = to_lower('J');
    BOOST_CHECK(maybej == 'j');
}

See also
Description

A Major Function Object is a Polymorphic Function Object which can be used with Boost.Lambda. Egg is a library which helps you define your own Major Function Object.

Refinement of
Requirements

In addition to the requirements defined in the refinements, for any Major Function Object f the following must be met:

  • f can be used as the first argument of boost::lambda::bind.
[Tip] Tip

This concept can be implemented without depending on Boost.Lambda library.

See also
Description

A Static Function Object is a Major Function Object which is intended to replace normal functions.

Refinement of
Requirements

In addition to the requirements defined in the refinements, for any Static Function Object f the following must be met:

[Note] Note

A Static Function Object can be singular, meaning that it may result in undefined behavior to call a default constructed one.

Example

typedef int (*T_is_alpha)(int ch);
T_is_alpha const is_alpha = &std::isalpha;

See also
Description

A Little Function type is a type which Function Builders require.

Requirements

For any Little Function type L the following must be met:

  • L has a nested class template named apply, where apply<...>::type means return type of function calls.
  • L has a const member function named call whose return type is explicitly specified by the first template parameter.
Example

struct little_identity
{
    template<class Self, class T>
    struct apply
    {
        typedef T &type;
    };

    template<class Auto, class T>
    Auto call(T &x) const
    {
        return x;
    }
};

See also
[Caution] Caution

Boost.ResultOf document in boost.org is outdated.

How to call

Lvalues are indicated by passing a reference type, rvalues are indicated by passing a non-reference type:

#include <boost/utility/result_of.hpp>
using boost::result_of;

struct T_plus
{
    typedef int result_type;

    result_type operator()(int i, int j) const
    {
        return i + j;
    }
};

void test_lvalue()
{
    int i = 2;
    result_of<T_plus(int &, int)>::type r = T_plus()(i, 3);
    BOOST_CHECK( r == 5 );
}

Thanks to this convention, you can easily write a "chain" of Boost.ResultOf:

void test_chain()
{
    int const i = 3;
    result_of<
        T_plus(result_of<T_plus(int, int)>::type, int const &)
    >::type r
        = T_plus()(T_plus()(1, 2), i);

    BOOST_CHECK( r == 6 );
}

A callable type can't be a reference type but must be "const-correct", meaning that you must add const to const-qualified Function Object type:

T_plus const plus = {};

void test_const()
{
    result_of<T_plus const(int, int)>::type r = plus(2, 3);
    BOOST_CHECK( r == 5 );
}

However, if a library guarantees the same behavior between const-qualified type and non-const-qualified type (as Static Function Object does so), you could omit const:

void test_nonconst()
{
    result_of<T_plus(int, int)>::type r = plus(2, 3);
    BOOST_CHECK( r == 5 );
}

Bugs
  • msvc-7.1 and msvc-8.0 doesn't work with POD templates.
  • A const-qualified function pointer doesn't work.

These bugs can be worked around by egg::result_of_ in <boost/egg/result_of.hpp>. The first bug is fixed with Boost1.35.

See also

PrevUpHomeNext