123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- <?xml version="1.0" encoding="utf-8"?>
- <!--
- Copyright 2012 Eric Niebler
- Distributed under 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)
- -->
- <header name="boost/proto/transform/make.hpp">
- <para>
- Contains definition of the
- <computeroutput>
- <classname alt="boost::proto::make">proto::make<></classname>
- </computeroutput>
- and
- <computeroutput>
- <classname alt="boost::proto::protect">proto::protect<></classname>
- </computeroutput>
- transforms.
- </para>
- <namespace name="boost">
- <namespace name="proto">
- <struct name="noinvoke">
- <template>
- <template-type-parameter name="T"/>
- </template>
- <purpose>A type annotation in an <conceptname>ObjectTransform</conceptname> which instructs
- Proto not to look for a nested <computeroutput>::type</computeroutput> within
- <computeroutput>T</computeroutput> after type substitution.</purpose>
- <description>
- <para>
- <conceptname>ObjectTransform</conceptname>s are evaluated by
- <computeroutput><classname alt="proto::make">proto::make<></classname></computeroutput>,
- which finds all nested transforms and replaces them with the result of their applications.
- If any substitutions are performed, the result is first assumed to be a metafunction to be applied;
- that is, Proto checks to see if the result has a nested <computeroutput>::type</computeroutput>
- typedef. If it does, that becomes the result. The purpose of <computeroutput>proto::noinvoke<></computeroutput>
- is to prevent Proto from looking for a nested <computeroutput>::type</computeroutput> typedef
- in these situations.
- </para>
- <para>
- Example:
- <programlisting>struct Test
- : <classname>proto::when</classname><
- <classname>_</classname>
- , proto::noinvoke<
- // This remove_pointer invocation is bloked by noinvoke
- boost::remove_pointer<
- // This add_pointer invocation is *not* blocked by noinvoke
- boost::add_pointer<<classname>_</classname>>
- >
- >()
- >
- {};
- void test_noinvoke()
- {
- typedef <classname>proto::terminal</classname><int>::type Int;
-
- BOOST_MPL_ASSERT((
- boost::is_same<
- boost::result_of<Test(Int)>::type
- , boost::remove_pointer<Int *>
- >
- ));
-
- Int i = {42};
- boost::remove_pointer<Int *> t = Test()(i);
- }</programlisting>
- </para>
- </description>
- </struct>
- <struct name="protect">
- <template>
- <template-type-parameter name="PrimitiveTransform"/>
- </template>
- <inherit><classname>proto::transform</classname>< protect<PrimitiveTransform> ></inherit>
- <purpose>A <conceptname>PrimitiveTransform</conceptname> which prevents another
- <conceptname>PrimitiveTransform</conceptname> from being applied in an
- <conceptname>ObjectTransform</conceptname>.</purpose>
- <description>
- <para>
- When building higher order transforms with
- <computeroutput>
- <classname alt="proto::make">proto::make<></classname>
- </computeroutput> or
- <computeroutput>
- <classname alt="proto::lazy">proto::lazy<></classname>
- </computeroutput>,
- you sometimes would like to build types that are parameterized with Proto transforms. In such
- lambda-style transforms, Proto will unhelpfully find all nested transforms and apply them, even
- if you don't want them to be applied. Consider the following transform, which will replace the
- <computeroutput>proto::_</computeroutput> in
- <computeroutput>Bar<proto::_>()</computeroutput>
- with <computeroutput>proto::terminal<int>::type</computeroutput>:
- </para>
- <para>
- <programlisting>template<typename T>
- struct Bar
- {};
- struct Foo :
- <classname>proto::when</classname><<classname>proto::_</classname>, Bar<<classname>proto::_</classname>>() >
- {};
- <classname>proto::terminal</classname><int>::type i = {0};
- int main() {
- Foo()(i);
- std::cout << typeid(Foo()(i)).name() << std::endl;
- }</programlisting>
- </para>
- <para>
- If you actually wanted to default-construct an object of type
- <computeroutput>Bar<proto::_></computeroutput>, you would have to protect the
- <computeroutput>_</computeroutput> to prevent it from being applied. You can
- use <computeroutput>proto::protect<></computeroutput> as follows:
- </para>
- <para>
- <programlisting>// OK: replace anything with Bar<_>()
- struct Foo :
- <classname>proto::when</classname><<classname>proto::_</classname>, Bar<<classname>proto::protect</classname><<classname>proto::_</classname>> >() >
- {};</programlisting>
- </para>
- </description>
- <struct name="impl">
- <template>
- <template-type-parameter name=""/>
- <template-type-parameter name=""/>
- <template-type-parameter name=""/>
- </template>
- <typedef name="result_type">
- <type>PrimitiveTransform</type>
- </typedef>
- </struct>
- </struct>
- <struct name="make">
- <template>
- <template-type-parameter name="T"/>
- </template>
-
- <inherit><classname>proto::transform</classname>< make<T> ></inherit>
-
- <purpose>A <conceptname>PrimitiveTransform</conceptname> that computes a type by evaluating
- any nested transforms and then constructs an object of that type. </purpose>
-
- <description>
- <para>
- The purpose of <computeroutput>proto::make<></computeroutput> is to annotate a transform as
- an <conceptname>ObjectTransform</conceptname> so that
- <computeroutput><classname alt="proto::when">proto::when<></classname></computeroutput> knows
- how to apply it.
- </para>
- <para>
- For the full description of the behavior of the
- <computeroutput><classname alt="proto::make">proto::make<></classname></computeroutput>
- transform, see the documentation for the nested
- <computeroutput><classname alt="proto::make::impl">proto::make::impl<></classname></computeroutput>
- class template.
- </para>
- </description>
- <struct name="impl">
- <template>
- <template-type-parameter name="Expr"/>
- <template-type-parameter name="State"/>
- <template-type-parameter name="Data"/>
- </template>
- <inherit><classname>proto::transform_impl</classname>< Expr, State, Data ></inherit>
- <typedef name="result_type">
- <type><emphasis>see-below</emphasis></type>
- <description>
- <para>
- <computeroutput><classname>proto::make</classname><T>::impl<Expr, State, Data>::result_type</computeroutput> is
- computed as follows:
- </para>
- <para>
- If <computeroutput>T</computeroutput> is an <conceptname>ObjectTransform</conceptname> of the form
- <computeroutput>Object(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput> or
- <computeroutput>Object(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
- then let <computeroutput>O</computeroutput> be the return type
- <computeroutput>Object</computeroutput>. Otherwise, let <computeroutput>O</computeroutput>
- be <computeroutput>T</computeroutput>. The <computeroutput>result_type</computeroutput> typedef is
- then computed as follows:
- </para>
- <para>
- <itemizedlist>
- <listitem>
- <para>
- If <computeroutput><classname>proto::is_transform</classname><O>::value</computeroutput> is
- <computeroutput>true</computeroutput>, then let the result type be
- <computeroutput>
- boost::result_of<<classname>proto::when</classname><<classname>_</classname>, O>(Expr, State, Data)>::type
- </computeroutput>.
- Note that a substitution took place.
- </para>
- </listitem>
- <listitem>
- If <computeroutput>O</computeroutput> is a template like
- <computeroutput><classname>proto::noinvoke</classname><S<X<subscript>0</subscript>,…X<subscript>n</subscript>> ></computeroutput>,
- then the result type is calculated as follows:
- <itemizedlist>
- <listitem>
- <para>
- For each <computeroutput>i</computeroutput> in
- <computeroutput>[0,n]</computeroutput>, let <computeroutput>
- X<subscript>i</subscript>'
- </computeroutput> be
- <computeroutput>
- boost::result_of<<classname>proto::make</classname><X<subscript>i</subscript>>(Expr, State, Data)>::type
- </computeroutput>
- (which evaluates this procedure recursively). Note that a substitution took place. (In this case,
- Proto merely assumes that a substitution took place for the sake of compile-time efficiency. There
- would be no reason to use <computeroutput><classname>proto::noinvoke<></classname></computeroutput>
- otherwise.)
- </para>
- </listitem>
- <listitem>
- <para>
- The result type is
- <computeroutput>
- S<X<subscript>0</subscript>',…X<subscript>n</subscript>'>
- </computeroutput>.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- If <computeroutput>O</computeroutput> is a template like
- <computeroutput>S<X<subscript>0</subscript>,…X<subscript>n</subscript>></computeroutput>,
- then the result type is calculated as follows:
- <itemizedlist>
- <listitem>
- <para>
- For each <computeroutput>i</computeroutput> in
- <computeroutput>[0,n]</computeroutput>, let <computeroutput>
- X<subscript>i</subscript>'
- </computeroutput> be
- <computeroutput>
- boost::result_of<<classname>proto::make</classname><X<subscript>i</subscript>>(Expr, State, Data)>::type
- </computeroutput>
- (which evaluates this procedure recursively). Note whether any substitutions took place during
- this operation.
- </para>
- </listitem>
- <listitem>
- <para>
- If any substitutions took place in the above step and
- <computeroutput>
- S<X<subscript>0</subscript>',…X<subscript>n</subscript>'>
- </computeroutput> has a nested
- <computeroutput>type</computeroutput> typedef, the result type is
- <computeroutput>
- S<X<subscript>0</subscript>',…X<subscript>n</subscript>'>::type
- </computeroutput>.
- </para>
- </listitem>
- <listitem>
- <para>
- Otherwise, the result type is
- <computeroutput>
- S<X<subscript>0</subscript>',…X<subscript>n</subscript>'>
- </computeroutput>.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- Otherwise, the result type is <computeroutput>O</computeroutput>, and note that no
- substitution took place.
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Note that <computeroutput><classname alt="proto::when">proto::when<></classname></computeroutput> is implemented
- in terms of <computeroutput><classname alt="proto::call">proto::call<></classname></computeroutput>
- and <computeroutput><classname alt="proto::make">proto::make<></classname></computeroutput>, so the
- above procedure is evaluated recursively.
- </para>
- </description>
- </typedef>
- <method-group name="public member functions">
- <method name="operator()" cv="const">
- <type>result_type</type>
- <parameter name="expr">
- <paramtype>typename impl::expr_param</paramtype>
- </parameter>
- <parameter name="state">
- <paramtype>typename impl::state_param</paramtype>
- </parameter>
- <parameter name="data">
- <paramtype>typename impl::data_param</paramtype>
- </parameter>
- <description>
- <para>
- <computeroutput>
- <classname>proto::make</classname><T>::impl<Expr,State,Data>::operator()
- </computeroutput>
- behaves as follows:
- </para>
- <para>
- <itemizedlist>
- <listitem>
- <para>
- If <computeroutput>T</computeroutput> is of the form
- <computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- If <computeroutput>
- <classname>proto::is_aggregate</classname><result_type>::value
- </computeroutput> is <computeroutput>true</computeroutput>, then construct
- and return an object <computeroutput>that</computeroutput> as follows:
- <programlisting>result_type that = {
- <classname>proto::when</classname><<classname>_</classname>, A<subscript>0</subscript>>()(expr, state, data),
- …
- <classname>proto::when</classname><<classname>_</classname>, A<subscript>n</subscript>>()(expr, state, data)
- };</programlisting>
- </para>
- </listitem>
- <listitem>
- <para>
- Otherwise, construct
- and return an object <computeroutput>that</computeroutput> as follows:
- <programlisting>result_type that(
- <classname>proto::when</classname><<classname>_</classname>, A<subscript>0</subscript>>()(expr, state, data),
- …
- <classname>proto::when</classname><<classname>_</classname>, A<subscript>n</subscript>>()(expr, state, data)
- );</programlisting>
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>
- If <computeroutput>T</computeroutput> is of the form
- <computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
- then let <computeroutput>T'</computeroutput> be <computeroutput>O(A<subscript>0</subscript>,…A<subscript>n-1</subscript>, <replaceable>S</replaceable>)</computeroutput>,
- where <replaceable>S</replaceable> is a type sequence computed from the unpacking expression <computeroutput>A<subscript>n</subscript></computeroutput>
- as described in the reference for <computeroutput><classname>proto::pack</classname></computeroutput>. Then, return:
- <programlisting>proto::make<T'>()(expr, state, data)</programlisting>
- </para>
- </listitem>
- <listitem>
- <para>
- Otherwise, construct and return an object <computeroutput>that</computeroutput>
- as follows: <programlisting>result_type that = result_type();</programlisting>
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- </method>
- </method-group>
- </struct>
- </struct>
- </namespace>
- </namespace>
- </header>
|