1
<?xml version=
"1.0" encoding=
"utf-8"?>
3 Copyright 2012 Eric Niebler
5 Distributed under the Boost
6 Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 <header name=
"boost/proto/extends.hpp">
10 <para>Macros and a base class for defining end-user expression types
</para>
11 <namespace name=
"boost">
12 <namespace name=
"proto">
14 <!-- proto::is_proto_expr -->
15 <struct name=
"is_proto_expr">
16 <purpose>Empty type to be used as a dummy template parameter of POD expression wrappers. It allows
17 argument-dependent lookup to find Proto's operator overloads.
</purpose>
20 <computeroutput>proto::is_proto_expr
</computeroutput> allows argument-dependent lookup to find Proto's operator overloads. For example:
23 <programlisting> template
<typename T, typename Dummy =
<classname>proto::is_proto_expr
</classname>>
26 <macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>(
27 typename
<classname>proto::terminal
</classname><T
>::type
28 , my_terminal
<T
>
29 ,
<classname>proto::default_domain
</classname>
34 my_terminal
<int
> _1, _2;
35 _1 + _2; // OK, uses proto::operator+
</programlisting>
38 Without the second
<computeroutput>Dummy
</computeroutput> template parameter, Proto's operator overloads
39 would not be considered by name lookup.
44 <!-- proto::extends -->
45 <struct name=
"extends">
47 <template-type-parameter name=
"Expr"/>
48 <template-type-parameter name=
"Derived"/>
49 <template-type-parameter name=
"Domain">
50 <default><classname>proto::default_domain
</classname></default>
51 </template-type-parameter>
53 <purpose>For adding behaviors to a Proto expression template.
</purpose>
56 Use
<computeroutput>proto::extends
<></computeroutput> to give expressions in your
57 domain custom data members and member functions.
60 Conceptually, using
<computeroutput>proto::extends
<></computeroutput> is akin
61 to inheriting from
<computeroutput><classname>proto::expr
</classname><></computeroutput>
62 and adding your own members. Using
<computeroutput>proto::extends
<></computeroutput> is
63 generally preferrable to straight inheritance because the members that would be inherited from
64 <computeroutput><classname>proto::expr
</classname><></computeroutput> would
65 be wrong; they would incorrectly slice off your additional members when building
66 larger expressions from smaller ones.
<computeroutput>proto::extends
<></computeroutput>
67 automatically gives your expression types the appropriate operator overloads that
68 preserve your domain-specific members when composing expression trees.
71 Expression extensions are typically defined as follows:
74 <programlisting>template
< typename Expr
>
77 Expr // The expression type we're extending
78 , my_expr
< Expr
> // The type we're defining
79 , my_domain // The domain associated with this expression extension
82 // An expression extension is constructed from the expression
84 my_expr( Expr const
& e = Expr() )
85 : my_expr::proto_extends( e )
88 // Unhide proto::extends::operator=
89 // (This is only necessary if a lazy assignment operator
90 // makes sense for your domain-specific language.)
91 BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expr)
94 ... domain-specific members go here ...
102 <computeroutput><macroname>BOOST_PROTO_EXTENDS
</macroname>()
</computeroutput>
105 <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN
</macroname>()
</computeroutput>
108 <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT
</macroname>()
</computeroutput>
113 <struct name=
"result">
115 <template-type-parameter name=
"Signature"/>
117 <typedef name=
"type">
118 <type><replaceable>unspecified
</replaceable></type>
121 <para>So that
<computeroutput>boost::result_of
<></computeroutput>
122 can compute the return type of
<computeroutput>proto::extends::operator()
</computeroutput>.
126 <typedef name=
"proto_base_expr">
127 <type>typename Expr::proto_base_expr
</type>
129 <typedef name=
"proto_domain">
132 <typedef name=
"proto_derived_expr">
135 <typedef name=
"proto_extends">
138 <typedef name=
"proto_tag">
139 <type>typename proto_base_expr::proto_tag
</type>
141 <typedef name=
"proto_args">
142 <type>typename proto_base_expr::proto_args
</type>
144 <typedef name=
"proto_arity">
145 <type>typename proto_base_expr::proto_arity
</type>
147 <typedef name=
"proto_grammar">
148 <type>typename proto_base_expr::proto_grammar
</type>
150 <typedef name=
"proto_childN">
151 <purpose>For each
<replaceable>N
</replaceable> in
<replaceable>[
0,max(
1,proto_arity_c))
</replaceable></purpose>
152 <type>typename proto_base_expr::proto_child
<replaceable>N
</replaceable></type>
155 <!-- constructors -->
158 <parameter name=
"that">
159 <paramtype><classname>extends
</classname> const
&</paramtype>
163 <parameter name=
"expr_">
164 <paramtype>Expr const
&</paramtype>
168 <method-group name=
"public static functions">
169 <method name=
"make" specifiers=
"static">
170 <type>Derived const
</type>
171 <parameter name=
"expr">
172 <paramtype>Expr const
&</paramtype>
175 <para>Construct an expression extension from the base expression.
</para>
177 <return>Derived(expr)
</return>
181 <method-group name=
"public member functions">
183 <!-- proto_base() -->
184 <method name=
"proto_base">
185 <type>proto_base_expr
&</type>
186 <returns><computeroutput>proto_expr_.proto_base()
</computeroutput></returns>
187 <throws><simpara>Will not throw.
</simpara></throws>
189 <method name=
"proto_base" cv=
"const">
190 <type>proto_base_expr const
&</type>
191 <returns><computeroutput>proto_expr_.proto_base()
</computeroutput></returns>
192 <throws><simpara>Will not throw.
</simpara></throws>
196 <method name=
"operator=">
197 <type><replaceable>unspecified
</replaceable></type>
199 <template-type-parameter name=
"A"/>
202 <paramtype>A
&</paramtype>
205 <para>Lazy assignment expression
</para>
208 <para>A new expression node representing the assignment operation.
</para>
212 <method name=
"operator=">
213 <type><replaceable>unspecified
</replaceable></type>
215 <template-type-parameter name=
"A"/>
218 <paramtype>A const
&</paramtype>
222 This is an overloaded member function, provided for convenience. It differs from
223 the above function only in what argument(s) it accepts.
228 <method name=
"operator=" cv=
"const">
229 <type><replaceable>unspecified
</replaceable></type>
231 <template-type-parameter name=
"A"/>
234 <paramtype>A
&</paramtype>
238 This is an overloaded member function, provided for convenience. It differs from
239 the above function only in what argument(s) it accepts.
244 <method name=
"operator=" cv=
"const">
245 <type><replaceable>unspecified
</replaceable></type>
247 <template-type-parameter name=
"A"/>
250 <paramtype>A const
&</paramtype>
254 This is an overloaded member function, provided for convenience. It differs from
255 the above function only in what argument(s) it accepts.
261 <method name=
"operator[]">
262 <type><replaceable>unspecified
</replaceable></type>
264 <template-type-parameter name=
"A"/>
267 <paramtype>A
&</paramtype>
270 <para>Lazy subscript expression
</para>
273 <para>A new expression node representing the subscript operation.
</para>
277 <method name=
"operator[]">
278 <type><replaceable>unspecified
</replaceable></type>
280 <template-type-parameter name=
"A"/>
283 <paramtype>A const
&</paramtype>
287 This is an overloaded member function, provided for convenience. It differs from
288 the above function only in what argument(s) it accepts.
293 <method name=
"operator[]" cv=
"const">
294 <type><replaceable>unspecified
</replaceable></type>
296 <template-type-parameter name=
"A"/>
299 <paramtype>A
&</paramtype>
303 This is an overloaded member function, provided for convenience. It differs from
304 the above function only in what argument(s) it accepts.
309 <method name=
"operator[]" cv=
"const">
310 <type><replaceable>unspecified
</replaceable></type>
312 <template-type-parameter name=
"A"/>
315 <paramtype>A const
&</paramtype>
319 This is an overloaded member function, provided for convenience. It differs from
320 the above function only in what argument(s) it accepts.
326 <method name=
"operator()">
327 <type><replaceable>unspecified
</replaceable></type>
329 <template-type-parameter name=
"A" pack=
"1"/>
331 <parameter name=
"a" pack=
"1">
332 <paramtype>A const
&</paramtype>
335 <para>Lazy function call
</para>
338 <para>A new expression node representing the function call operation.
</para>
342 <method name=
"operator()" cv=
"const">
343 <type><replaceable>unspecified
</replaceable></type>
345 <template-type-parameter name=
"A" pack=
"1"/>
347 <parameter name=
"a" pack=
"1">
348 <paramtype>A const
&</paramtype>
352 This is an overloaded member function, provided for convenience. It differs from
353 the above function only in what argument(s) it accepts.
359 <data-member name=
"proto_expr_">
361 <purpose>For exposition only.
</purpose>
364 <data-member name=
"proto_arity_c" specifiers=
"static">
365 <type>const long
</type>
366 <purpose><computeroutput>= proto_base_expr::proto_arity_c;
</computeroutput></purpose>
374 <macro name=
"BOOST_PROTO_EXTENDS" kind=
"functionlike">
375 <macro-parameter name=
"Expr"/>
376 <macro-parameter name=
"Derived"/>
377 <macro-parameter name=
"Domain"/>
378 <purpose>For creating expression wrappers that add behaviors to a Proto expression template, like
379 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>,
380 but while retaining POD-ness of the expression wrapper.
</purpose>
384 <programlisting><macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>(Expr, Derived, Domain)
385 <macroname>BOOST_PROTO_EXTENDS_ASSIGN
</macroname>()
386 <macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT
</macroname>()
387 <macroname>BOOST_PROTO_EXTENDS_FUNCTION
</macroname>()
</programlisting>
389 <para>If the
<computeroutput>Domain
</computeroutput> parameter is dependent, you can specify it as
390 <computeroutput>typename Domain
</computeroutput>, as in
391 <computeroutput>BOOST_PROTO_EXTENDS(Expr, Derived, typename Domain)
</computeroutput>
394 <emphasis role=
"bold">Example:
</emphasis><programlisting>template
< class Expr
>
398 :
<classname alt=
"boost::proto::domain">proto::domain
</classname>< <classname alt=
"boost::proto::pod_generator">proto::pod_generator
</classname>< my_expr
> >
401 template
< class Expr
>
404 // OK, this makes my_expr
<> a valid Proto expression extension.
405 // my_expr
<> has overloaded assignment, subscript,
406 // and function call operators that build expression templates.
407 <macroname>BOOST_PROTO_EXTENDS
</macroname>(Expr, my_expr, my_domain)
410 // OK, my_expr
<> is POD, so this is statically initialized:
411 my_expr
< <classname alt=
"boost::proto::terminal">proto::terminal
</classname><int
>::type
> const _1 = {{
1}};
</programlisting>
416 <macro name=
"BOOST_PROTO_BASIC_EXTENDS" kind=
"functionlike">
417 <macro-parameter name=
"Expr"/>
418 <macro-parameter name=
"Derived"/>
419 <macro-parameter name=
"Domain"/>
420 <purpose>For creating expression wrappers that add members to a Proto expression template, like
421 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>,
422 but while retaining POD-ness of the expression wrapper.
</purpose>
425 <computeroutput>BOOST_PROTO_BASIC_EXTENDS()
</computeroutput> adds the basic typedefs, member functions, and
426 data members necessary to make a struct a valid Proto expression extension. It does
<emphasis>not
</emphasis>
427 add any constructors, virtual functions or access control blocks that would render the containing
431 <computeroutput>Expr
</computeroutput> is the Proto expression that the enclosing struct extends.
432 <computeroutput>Derived
</computeroutput> is the type of the enclosing struct.
433 <computeroutput>Domain
</computeroutput> is the Proto domain to which this expression extension belongs.
434 (See
<computeroutput><classname alt=
"boost::proto::domain">proto::domain
<></classname></computeroutput>.)
435 Can be preceeded with
"<computeroutput>typename</computeroutput>" if the specified domain is a dependent type.
437 <para><computeroutput>BOOST_PROTO_BASIC_EXTENDS()
</computeroutput> adds to its enclosing struct
438 exactly one data member of type
<computeroutput>Expr
</computeroutput>.
440 <para>If the
<computeroutput>Domain
</computeroutput> parameter is dependent, you can specify it as
441 <computeroutput>typename Domain
</computeroutput>, as in
442 <computeroutput>BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, typename Domain)
</computeroutput>
445 <emphasis role=
"bold">Example:
</emphasis><programlisting>template
< class Expr
>
449 :
<classname alt=
"boost::proto::domain">proto::domain
</classname>< <classname alt=
"boost::proto::pod_generator">proto::pod_generator
</classname>< my_expr
> >
452 template
< class Expr
>
455 // OK, this makes my_expr
<> a valid Proto expression extension.
456 // my_expr
<> does /not/ have overloaded assignment, subscript,
457 // and function call operators that build expression templates, however.
458 <macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>(Expr, my_expr, my_domain)
461 // OK, my_expr
<> is POD, so this is statically initialized:
462 my_expr
< <classname alt=
"boost::proto::terminal">proto::terminal
</classname><int
>::type
> const _1 = {{
1}};
</programlisting>
468 <computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN
</macroname>()
</computeroutput>
471 <computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT
</macroname>()
</computeroutput>
474 <computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION
</macroname>()
</computeroutput>
477 <computeroutput><macroname>BOOST_PROTO_EXTENDS
</macroname>()
</computeroutput>
484 <macro name=
"BOOST_PROTO_EXTENDS_ASSIGN" kind=
"functionlike">
485 <purpose>For adding to an expression extension class an overloaded assignment operator that
486 builds an expression template.
</purpose>
489 Use
<computeroutput>BOOST_PROTO_EXTENDS_ASSIGN()
</computeroutput> after
<computeroutput>
490 <macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>()
</computeroutput> to give an expression
491 extension class an overloaded assignment operator that builds an expression template.
497 <computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>()
</computeroutput>
500 <computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT
</macroname>()
</computeroutput>
503 <computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION
</macroname>()
</computeroutput>
506 <computeroutput><macroname>BOOST_PROTO_EXTENDS
</macroname>()
</computeroutput>
513 <macro name=
"BOOST_PROTO_EXTENDS_FUNCTION" kind=
"functionlike">
514 <purpose>For adding to an expression extension class a set of overloaded function call operators
515 that build expression templates.
</purpose>
518 Use
<computeroutput>BOOST_PROTO_EXTENDS_FUNCTION()
</computeroutput> after
<computeroutput>
519 <macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>()
</computeroutput> to give an expression
520 extension class a set of overloaded function call operators that build expression templates.
521 In addition,
<computeroutput>BOOST_PROTO_EXTENDS_FUNCTION()
</computeroutput> adds a nested
522 <computeroutput>result
<></computeroutput> class template that is a metafunction for
523 calculating the return type of the overloaded function call operators.
529 <computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>()
</computeroutput>
532 <computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN
</macroname>()
</computeroutput>
535 <computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT
</macroname>()
</computeroutput>
538 <computeroutput><macroname>BOOST_PROTO_EXTENDS
</macroname>()
</computeroutput>
545 <macro name=
"BOOST_PROTO_EXTENDS_SUBSCRIPT" kind=
"functionlike">
546 <purpose>For adding to an expression extension class an overloaded subscript operator that
547 builds an expression template.
</purpose>
550 Use
<computeroutput>BOOST_PROTO_EXTENDS_SUBSCRIPT()
</computeroutput> after
<computeroutput>
551 <macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>()
</computeroutput> to give an expression
552 extension class an overloaded subscript operator that builds an expression template.
558 <computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS
</macroname>()
</computeroutput>
561 <computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN
</macroname>()
</computeroutput>
564 <computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION
</macroname>()
</computeroutput>
567 <computeroutput><macroname>BOOST_PROTO_EXTENDS
</macroname>()
</computeroutput>
574 <macro name=
"BOOST_PROTO_EXTENDS_USING_ASSIGN" kind=
"functionlike">
575 <macro-parameter name=
"Derived"/>
576 <purpose>For exposing in classes that inherit from
577 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>
578 the overloaded assignment operators defined therein.
</purpose>
581 The standard usage of
582 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>
583 is to inherit from it. However, the derived class automatically gets a compiler-generated assignment
584 operator that will hide the ones defined in
585 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>.
586 Use
<code>BOOST_PROTO_EXTENDS_USING_ASSIGN()
</code> in the derived class to unhide the assignment
588 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>.
591 See
<computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>
592 for an example that demonstrates usage of
<code>BOOST_PROTO_EXTENDS_USING_ASSIGN()
</code>.
597 <macro name=
"BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT" kind=
"functionlike">
598 <macro-parameter name=
"Derived"/>
599 <purpose>For exposing in classes that inherit from
600 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>
601 the overloaded assignment operators defined therein. Unlike the
602 <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN
</macroname>()
</computeroutput> macro,
603 <code>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT()
</code> is for use in non-dependent
608 The standard usage of
609 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>
610 is to define a class template that inherits from it. The derived class template automatically gets a
611 compiler-generated assignment operator that hides the ones defined in
612 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>.
613 Using
<code>BOOST_PROTO_EXTENDS_USING_ASSIGN()
</code> in the derived class solves this problem.
616 However, if the expression extension is an ordinary class and not a class template, the usage of
617 <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()
</code> is in a so-called non-dependent context. In plain English,
618 it means it is illegal to use
<code>typename
</code> in some places where it is required in a class template.
619 In those cases, you should use
<code>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT()
</code> instead.
625 <computeroutput><classname alt=
"boost::proto::extends">proto::extends
<></classname></computeroutput>
628 <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN
</macroname>()
</computeroutput>