A Forwarding Strategy is a type which has three associated imaginary operators
, __bytag_at
and __arg_list
.
Egg predefines the fundamental strategy quartet: __meta_arg_list
by_perfect
,
by_ref
, by_cref
,
and by_value
. Also note Egg
components use by_perfect
when
you omit or specify boost::use_default
for strategy parameter.
This section uses the following notation.
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
|
|
|
|
, where V
is boost::remove_cv<boost::decay<
.
__typeof
(a)>::type>::type
Caution | |
---|---|
Under msvc-7.1, |
Egg defines the following imaginary operators for its documentation.
K
is the length of a
.
fwd_arg(a, __Stg
,
K,
I)
is __rval
(aI)
if
__bytag_at
(__Stg
, K,
I)
is by_value
, __arg_list
(aI,
__Stg
)
otherwise.
Valid expression |
Semantics |
---|---|
|
See each section of |
|
See each section of |
|
|
|
See each section of |
|
|
|
Important | |
---|---|
|
Egg performs "perfect forwarding" by default.
<boost/egg/by_perfect.hpp>
remove_cr(x)
is
boost::remove_const<boost::remove_reference<__decltype
(x)>::type>::type
.
bI
is any object such that
remove_cr(bI)
is
the same as remove_cr(aI)
.
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
|
See |
0 <=
K &&
K <=
BOOST_EGG_MAX_ARITY
.
Expr(__arg_list
(a,
by_perfect))
is a precondition as valid expression, Expr(__arg_list
(b, by_perfect))
must be well-formed.
Expr(__meta_arg_list
(a,
by_perfect))
is a precondition as valid expression, Expr(__meta_arg_list
(b, by_perfect))
must be well-formed.
__meta_arg_list
(a, by_perfect)
is int,const int,int
const
if a
is i,3,ci
,
where i
is a non-const
lvalue and ci
is a const
lvalue.
by_ref
offers large arity,
but can't take non-const rvalues.
<boost/egg/by_ref.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
|
See |
0 <=
K &&
K <=
BOOST_EGG_MAX_LINEAR_ARITY
.
aI
is not a rvalue.
__meta_arg_list
(a, by_ref)
is int,const int,int
const
if a
is i,ci,ci
,
where i
is a non-const
lvalue and ci
is a const
lvalue.
by_cref
takes arguments by
const reference.
<boost/egg/by_cref.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
|
See |
0 <=
K &&
K <=
BOOST_EGG_MAX_LINEAR_ARITY
.
__meta_arg_list
(a, by_cref)
is int
const,const int,int const
if a
is i,ci,ci
, where i
is a non-const lvalue and ci
is a const lvalue.
by_value
takes arguments
by value so that arguments are "decayed". Also, it can forward
"movable" rvalues like std::auto_ptr<>
with keeping movability.
<boost/egg/by_value.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
|
See |
0 <=
K &&
K <=
BOOST_EGG_MAX_LINEAR_ARITY
.
__meta_arg_list
(a, by_value)
is int,int,int
if a
is i,3,ci
,
where i
is a non-const
lvalue and ci
is a const
lvalue.
by_value
copies arguments
and turns them into mutable lvalues so that generic Little
Functions can be written. But, if you know by_value
is used, Little Function
call
should take arguments
"by value" or const reference:
struct little_id; typedef function<little_id, by_value> T_id; struct little_id { template<class Me, class V> struct apply { typedef V type; }; template<class Re, class V> Re call(V v) const { return v; } };
The predefined strategies, by_perfect
etc, may be too simple to meet your requirements. Egg provides a uniform
way to define your own strategies.
<boost/egg/function_extension.hpp>
Valid expression |
Semantics |
---|---|
|
See below. |
|
|
|
|
|
These can be used as "meta" return type of strategy tag. |
|
See below. |
|
|
Bytags
is a Preprocessor
Sequence of __Bytag
.
Cv
is cv-qualifier
of call operator. In case of no cv-qualifiers,
Cv
must be mutable
.
Cv
must be const
(for now).
0 <=
K &&
K <=
BOOST_EGG_MAX_LINEAR_ARITY
.
A user-defined strategy tag is MPL
Metafunction Class which takes itself, arity and index, then returns
.
__Bytag
struct your_strategy { template<class _, class Arity, class Index> struct apply; typedef boost::mpl::vector<by_perfect, by_ref> arity2_bytags; template<class _, class Index> struct apply<_, boost::mpl::int_<2>, Index> : boost::mpl::at<arity2_bytags, Index> { }; template<class _, class Index> struct apply<_, boost::mpl::int_<3>, Index> { typedef by_value type; }; };
function<>
Using your strategy tag, function<>
template can be specialized. BOOST_EGG_FUNCTION_PREAMBLE()
must be placed in first, which automagically defines nested typedefs little_type
, strategy_type
,
and result<...>
etc.
namespace boost { namespace egg { template<class Lit> struct function<Lit, your_strategy> { BOOST_EGG_FUNCTION_PREAMBLE() Lit m_lit; Lit const & little() const { return m_lit; } // 0ary typename apply_little<Lit const>::type operator()() const { return call_little(m_lit); } // 2ary: by_perfect, by_ref BOOST_EGG_FUNCTION_CALL_OPERATOR((by_perfect)(by_ref), const) #if 0 // Macro above is expaneded to... template<class A0, class A1> typename apply_little<Lit const, A0, A1>::type operator()(A0 &a0, A1 &a1) const { return call_little(m_lit, a0, a1); } template<class A0, class A1> typename apply_little<Lit const, BOOST_EGG_DEDUCED_CONST(A0), A1>::type operator()(A0 const &a0, A1 &a1) const { return call_little(m_lit, a0, a1); } #endif // 3ary: by_value template<class A0, class A1, class A2> typename apply_little<Lit const, A0, A1, A2>::type operator()(A0 a0, A1 a1, A2 a2) const { return call_little(m_lit, a0, a1, a2); } }; } }
This must be placed first. |
|
|
|
|
For by_perfect
call operators,
it is easy and preferable to use BOOST_EGG_FUNCTION_CALL_OPERATOR
,
which will compile much faster in C++0x. Also note, in order to work around
some compiler bugs, you can use neither result
template nor
directly. You have to use __Lit
::callapply_little
and call_little
instead. Moreover, if you want to support buggy msvc-7.1, BOOST_EGG_DEDUCED_CONST
instead of const
must be used
in apply_little
.
Now function<>
with your strategy is a model of Major
Function Object. Let's look into the new valid expressions.
StgTag
is MPL
Metafunction Class which you have defined.
StgTag_
is (possibly cv-qualified)
StgTag
.
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
|
See |
C++ instantiates the declarations of non-dependent member function templates, so that some Function Builders and Function Adaptors require a special workaround. Here an imaginary operator is defined for the documentation.
__decltype_r0
(R0, expr)
is defined as follows:
R0
is __ud
,
it is a valid expression and returns an unspecified type .
R0
is use_nullary_result
,
__decltype
(expr)
is a valid expression, it is a valid expression and returns __decltype
(expr)
.
R0
.
Tip | |
---|---|
Boost.ResultOf too offers a special workaround:
A nullary callable |