...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::proto::pack — To turn an expression into a pseudo-parameter pack containing the expression's children, for the purpose of expanding the pack expression within a CallableTransform or ObjectTransform.
// In header: <boost/proto/transform/impl.hpp> struct pack { };
proto::pack
is useful within
CallableTransforms and
ObjectTransforms when one wishes to unpack an expression
into a function call or an object constructor. proto::pack
turns a Proto expression into a pseudo-parameter pack, which may appear in an unpacking
pattern to be expanded with the "...
" syntax.
Example:
// The following demonstrates how to use a pseudo-pack expansion // to unpack an expression into a function call. struct do_sum : proto::callable { typedef int result_type; int operator()(int i) const { return i; } int operator()(int i, int j) const { return i + j; } int operator()(int i, int j, int k) const { return i + j + k; } }; // Take any n-ary expression where the children are all int terminals and sum all the ints struct sum : proto::when< // Match any nary expression where the children are all int terminals proto::nary_expr<_, proto::vararg<proto::terminal<int> > > // Turn the current expression into a pseudo-parameter pack, then expand it, // extracting the value from each child in turn. , do_sum(proto::_value(proto::pack(_))...) > {}; int main() { proto::terminal<int>::type i = {42}; int result = sum()( i(3,5) ); // Creates a ternary functional-call expression std::cout << "Sum of 42, 3, and 5 : " << result << std::endl; }
The above program displays:
Sum of 42, 3, and 5 : 50
In the above example, the type
proto::_value(proto::pack(_))
is a so-called unpacking pattern, described below.
Unpacking Patterns:
Composite transforms (either CallableTransforms or
ObjectTransforms) usually have the form
X(A_{0},…A_{n})
.
However, when the argument list in a composite transform is terminated with a C-style
vararg ellipsis as in X(A_{0},…A_{n} ...)
,
the final argument A_{n}
is treated
as an unpacking pattern.
An unpacking pattern must itself be a composite transform; that is, it must be a
function type representing either a CallableTransform or
an ObjectTransform. The type proto::pack(_)
must appear exactly once in the unpacking pattern. This type will receive a substitution
when the unpacking pattern is expanded.
A composite transform like X(A_{0},…A_{n} ...)
,
when evaluated against a given expression E
, state and data, is evaluated as if it were
X(A_{0},…A_{n-1},
where S
)S
is a type sequence computed as follows:
Let
be a type function that replaces every occurence of
SUB
(A,B)proto::pack(_)
within A
with B
.
E
is a terminal (i.e. it has arity 0), S
is the one-element sequence containing SUB
(A_{n}, proto::_value)
.
E
is a non-terminal, S
is the sequence
SUB
(A_{n}, proto::_child_c<0>),…
SUB
(A_{n}, proto::_child_c<M
-1>)
, where
M
is the arity of the expression E
.