123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- [/==============================================================================
- Copyright (C) 2001-2011 Joel de Guzman
- Copyright (C) 2006 Dan Marsden
- Copyright (C) 2010 Christopher Schmidt
- 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)
- ===============================================================================/]
- [section Notes]
- [heading Recursive Inlined Functions]
- 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
- certain compiler limit of course). Compile time complexity remains linear.
- [heading Overloaded Functions]
- 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
- 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:
- # `Sequence` is the type for which a suitable implementation of
- `result_of::begin_impl` is required
- # `traits::tag_of` is the metafunction that associates `Sequence`
- with an appropriate tag
- # `result_of::begin_impl` is the template which is specialized to provide
- an implementation for each tag type
- [heading Extensibility]
- Unlike __mpl__, there is no extensible sequence concept in fusion. This does
- not mean that Fusion sequences are not extensible. In fact, all Fusion
- sequences are inherently extensible. It is just that the manner of sequence
- extension in Fusion is different from both __stl__ and __mpl__ on account of
- 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.
- [heading Element Conversion]
- 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
- values. Example:
- __make_list__(1, 'x')
- returns a __list__`<int, char>`.
- There are a few exceptions, however.
- [*Arrays:]
- 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
- (see __note_ref_wrappers__).]:
- __make_list__("Donald", "Daisy")
- creates a __list__ of type
- __list__<const char (&)[7], const char (&)[6]>
- [*Function pointers:]
- Function pointers are deduced to the plain non-reference type (i.e. to
- plain function pointer). Example:
- void f(int i);
- ...
- __make_list__(&f);
- creates a __list__ of type
- __list__<void (*)(int)>
- [heading Reference Wrappers]
- Fusion's generation functions (e.g. __make_list__) by default stores the
- element types as plain non-reference types. Example:
- void foo(const A& a, B& b) {
- ...
- __make_list__(a, b)
- creates a __list__ of type
- __list__<A, B>
- 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
- 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&>
- See __boost_ref__ for details.
- Since C++11, the standard reference wrappers (`std::ref` and `std::cref`) work as well.
- [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
- {
- template<
- typename Type
- , int Index
- , bool Const
- >
- struct adt_attribute_proxy;
- }}}
- 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`
- for constant instances of `type_name` and `false` for non-constant ones.
- [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]
- [table
- [[Expression] [Semantics]]
- [[[^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]]]]
- [[[^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.]]
- ]
- 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].
- [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].]
- [endsect]
|