2007-11-07 02:12:28 +00:00
[/==============================================================================
2011-10-10 10:37:53 +00:00
Copyright (C) 2001-2011 Joel de Guzman
Copyright (C) 2006 Dan Marsden
2010-10-04 20:50:31 +00:00
Copyright (C) 2010 Christopher Schmidt
2007-11-07 02:12:28 +00:00
Use, modification and distribution is subject to 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)
===============================================================================/]
2006-08-22 15:57:13 +00:00
[section Notes]
[heading Recursive Inlined Functions]
2007-11-07 02:12:28 +00:00
An interesting peculiarity of functions like __at__ when applied to a
__forward_sequence__ like __list__ is that what could have been linear
runtime complexity effectively becomes constant O(1) due to compiler
optimization of C++ inlined functions, however deeply recursive (up to a
2006-08-22 15:57:13 +00:00
certain compiler limit of course). Compile time complexity remains linear.
[heading Overloaded Functions]
2007-11-07 02:12:28 +00:00
Associative sequences use function overloading to implement membership
testing and type associated key lookup. This amounts to constant runtime
and amortized constant compile time complexities. There is an overloaded
function, `f(k)`, for each key /type/ `k`. The compiler chooses the
2006-08-22 15:57:13 +00:00
appropriate function given a key, `k`.
[heading Tag Dispatching]
Tag dispatching is a generic programming technique for selecting template
specializations. There are typically 3 components involved in the tag
dispatching mechanism:
# A type for which an appropriate template specialization is required
# A metafunction that associates the type with a tag type
# A template that is specialized for the tag type
For example, the fusion `result_of::begin` metafunction is implemented
as follows:
template <typename Sequence>
struct begin
{
typedef typename
result_of::begin_impl<typename traits::tag_of<Sequence>::type>::
template apply<Sequence>::type
type;
};
In the case:
2007-11-07 02:12:28 +00:00
# `Sequence` is the type for which a suitable implementation of
2006-08-22 15:57:13 +00:00
`result_of::begin_impl` is required
2007-11-07 02:12:28 +00:00
# `traits::tag_of` is the metafunction that associates `Sequence`
2006-08-22 15:57:13 +00:00
with an appropriate tag
2007-11-07 02:12:28 +00:00
# `result_of::begin_impl` is the template which is specialized to provide
2006-08-22 15:57:13 +00:00
an implementation for each tag type
[heading Extensibility]
2014-11-07 18:34:18 +01:00
Unlike __mpl__, there is no extensible sequence concept in fusion. This does
2007-11-07 02:12:28 +00:00
not mean that Fusion sequences are not extensible. In fact, all Fusion
sequences are inherently extensible. It is just that the manner of sequence
2014-11-07 18:34:18 +01:00
extension in Fusion is different from both __stl__ and __mpl__ on account of
2007-11-07 02:12:28 +00:00
the lazy nature of fusion __algorithms__. __stl__ containers extend
themselves in place though member functions such as __push_back__ and
__insert__. __mpl__ sequences, on the other hand, are extended through
"intrinsic" functions that actually return whole sequences. __mpl__ is
purely functional and can not have side effects. For example, __mpl__'s
`push_back` does not actually mutate an `mpl::vector`. It can't do that.
Instead, it returns an extended `mpl::vector`.
Like __mpl__, Fusion too is purely functional and can not have side
effects. With runtime efficiency in mind, Fusion sequences are extended
through generic functions that return __views__. __views__ are sequences
that do not actually contain data, but instead impart an alternative
presentation over the data from one or more underlying sequences. __views__
are proxies. They provide an efficient yet purely functional way to work on
potentially expensive sequence operations. For example, given a __vector__,
Fusion's __push_back__ returns a __joint_view__, instead of an actual
extended __vector__. A __joint_view__ holds a reference to the original
sequence plus the appended data --making it very cheap to pass around.
2006-08-22 15:57:13 +00:00
[heading Element Conversion]
2007-11-07 02:12:28 +00:00
Functions that take in elemental values to form sequences (e.g.
__make_list__) convert their arguments to something suitable to be stored
as a sequence element. In general, the element types are stored as plain
2006-08-22 15:57:13 +00:00
values. Example:
__make_list__(1, 'x')
2007-11-07 02:12:28 +00:00
returns a __list__`<int, char>`.
2006-08-22 15:57:13 +00:00
There are a few exceptions, however.
[*Arrays:]
2007-11-07 02:12:28 +00:00
Array arguments are deduced to reference to const types. For example
[footnote Note that the type of a string literal is an array of const
characters, not `const char*`. To get __make_list__ to create a __list__
with an element of a non-const array type one must use the `ref` wrapper
2015-02-21 19:15:49 +09:00
(see __note_ref_wrappers__).]:
2006-08-22 15:57:13 +00:00
__make_list__("Donald", "Daisy")
2007-11-07 02:12:28 +00:00
creates a __list__ of type
2006-08-22 15:57:13 +00:00
__list__<const char (&)[7], const char (&)[6]>
[*Function pointers:]
2007-11-07 02:12:28 +00:00
Function pointers are deduced to the plain non-reference type (i.e. to
2006-08-22 15:57:13 +00:00
plain function pointer). Example:
void f(int i);
...
__make_list__(&f);
2007-11-07 02:12:28 +00:00
creates a __list__ of type
2006-08-22 15:57:13 +00:00
__list__<void (*)(int)>
2015-01-15 18:58:33 +09:00
[heading Reference Wrappers]
2006-08-22 15:57:13 +00:00
2007-11-07 02:12:28 +00:00
Fusion's generation functions (e.g. __make_list__) by default stores the
2006-08-22 15:57:13 +00:00
element types as plain non-reference types. Example:
void foo(const A& a, B& b) {
...
__make_list__(a, b)
2007-11-07 02:12:28 +00:00
creates a __list__ of type
2006-08-22 15:57:13 +00:00
__list__<A, B>
2007-11-07 02:12:28 +00:00
Sometimes the plain non-reference type is not desired. You can use
`boost::ref` and `boost::cref` to store references or const references
(respectively) instead. The mechanism does not compromise const correctness
since a const object wrapped with ref results in a tuple element with const
2006-08-22 15:57:13 +00:00
reference type (see the fifth code line below). Examples:
For example:
A a; B b; const A ca = a;
__make_list__(cref(a), b); // creates list<const A&, B>
__make_list__(ref(a), b); // creates list<A&, B>
__make_list__(ref(a), cref(b)); // creates list<A&, const B&>
__make_list__(cref(ca)); // creates list<const A&>
__make_list__(ref(ca)); // creates list<const A&>
2007-11-07 02:12:28 +00:00
2006-08-22 15:57:13 +00:00
See __boost_ref__ for details.
2015-01-15 18:58:33 +09:00
Since C++11, the standard reference wrappers (`std::ref` and `std::cref`) work as well.
2010-10-04 20:50:31 +00:00
[heading adt_attribute_proxy]
To adapt arbitrary data types that do not allow direct access to their members,
but allow indirect access via expressions (such as invocations of get- and
set-methods), fusion's [^BOOST\_FUSION\_ADAPT\_['xxx]ADT['xxx]]-family (e.g.
__adapt_adt__) may be used.
To bypass the restriction of not having actual lvalues that
represent the elements of the fusion sequence, but rather a sequence of paired
expressions that access the elements, the actual return type of fusion's
intrinsic sequence access functions (__at__, __at_c__, __at_key__, __deref__,
and __deref_data__) is a proxy type, an instance of
`adt_attribute_proxy`, that encapsulates these expressions.
`adt_attribute_proxy` is defined in the namespace `boost::fusion::extension` and
has three template arguments:
namespace boost { namespace fusion { namespace extension
2011-10-10 10:37:53 +00:00
{
2010-10-04 20:50:31 +00:00
template<
typename Type
, int Index
, bool Const
>
struct adt_attribute_proxy;
}}}
2011-10-10 10:37:53 +00:00
2010-10-04 20:50:31 +00:00
When adapting a class type, `adt_attribute_proxy` is specialized for every
element of the adapted sequence, with `Type` being the class type that is
adapted, `Index` the 0-based indices of the elements, and `Const` both `true`
and `false`. The return type of fusion's intrinsic sequence access functions
for the ['N]th element of an adapted class type `type_name` is
[^adt_attribute_proxy<type_name, ['N], ['Const]>], with [^['Const]] being `true`
2011-10-10 10:37:53 +00:00
for constant instances of `type_name` and `false` for non-constant ones.
2010-10-04 20:50:31 +00:00
[variablelist Notation
[[`type_name`]
[The type to be adapted, with M attributes]]
[[`inst`]
[Object of type `type_name`]]
[[`const_inst`]
[Object of type `type_name const`]]
[[[^(attribute_type['N], attribute_const_type['N], get_expr['N], set_expr['N])]]
[Attribute descriptor of the ['N]th attribute of `type_name` as passed to the adaption macro, 0\u2264['N]<M]]
[[[^proxy_type['N]]]
[[^adt_attribute_proxy<type_name, ['N], `false`>] with ['N] being an integral constant, 0\u2264['N]<M]]
[[[^const_proxy_type['N]]]
[[^adt_attribute_proxy<type_name, ['N], `true`>] with ['N] being an integral constant, 0\u2264['N]<M]]
[[[^proxy['N]]]
[Object of type [^proxy_type['N]]]]
[[[^const_proxy['N]]]
[Object of type [^const_proxy_type['N]]]]
]
[*Expression Semantics]
2011-10-10 10:37:53 +00:00
2010-10-04 20:50:31 +00:00
[table
[[Expression] [Semantics]]
2010-10-04 21:16:42 +00:00
[[[^proxy_type['N](inst)]] [Creates an instance of [^proxy_type['N]] with underlying object `inst`]]
[[[^const_proxy_type['N](const_inst)]] [Creates an instance of [^const_proxy_type['N]] with underlying object `const_inst`]]
[[[^proxy_type['N]::type]] [Another name for [^attribute_type['N]]]]
[[[^const_proxy_type['N]::type]] [Another name for [^const_attribute_type['N]]]]
2010-10-04 20:50:31 +00:00
[[[^proxy['N]=t]] [Invokes [^set_expr['N]], with `t` being an arbitrary object. [^set_expr['N]] may access the variables named `obj` of type `type_name&`, which represent the corresponding instance of `type_name`, and `val` of an arbitrary const-qualified reference template type parameter `Val`, which represents `t`.]]
[[[^proxy['N].get()]] [Invokes [^get_expr['N]] and forwards its return value. [^get_expr['N]] may access the variable named `obj` of type `type_name&` which represents the underlying instance of `type_name`. [^attribute_type['N]] may specify the type that [^get_expr['N]] denotes to.]]
[[[^const_proxy['N].get()]] [Invokes [^get_expr['N]] and forwards its return value. [^get_expr['N]] may access the variable named `obj` of type `type_name const&` which represents the underlying instance of `type_name`. [^attribute_const_type['N]] may specify the type that [^get_expr['N]] denotes to.]]
]
2010-10-04 21:34:44 +00:00
Additionally, [^proxy_type['N]] and [^const_proxy_type['N]] are copy
constructible, copy assignable and implicitly convertible to
[^proxy_type['N]::type] or [^const_proxy_type['N]::type].
2010-10-04 20:50:31 +00:00
[tip To avoid the pitfalls of the proxy type, an arbitrary class type may also
be adapted directly using fusion's [link fusion.extension intrinsic extension
mechanism].]
2006-08-22 15:57:13 +00:00
[endsect]