![]() |
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_listby_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 |