mirror of
https://github.com/boostorg/utility.git
synced 2025-08-03 14:54:31 +02:00
Doc tweaks
[SVN r1873]
This commit is contained in:
@@ -105,6 +105,8 @@ First we define the named parameter keywords. This is done by creating
|
|||||||
"tag" types for each keyword, and declaring ``keyword<``\ *tag*\
|
"tag" types for each keyword, and declaring ``keyword<``\ *tag*\
|
||||||
``>`` objects::
|
``>`` objects::
|
||||||
|
|
||||||
|
#include <boost/named_params.hpp>
|
||||||
|
|
||||||
struct name_t; // tag types
|
struct name_t; // tag types
|
||||||
struct value_t;
|
struct value_t;
|
||||||
|
|
||||||
@@ -209,107 +211,141 @@ Now compiles, and prints::
|
|||||||
bar = 0
|
bar = 0
|
||||||
unnamed = 3
|
unnamed = 3
|
||||||
|
|
||||||
``reference_wrapper<>``
|
Limitations of the Approach
|
||||||
=======================
|
===========================
|
||||||
|
|
||||||
Our forwarding functions need to take their parameters by const
|
Because the keywords' ``operator=`` returns a temporary, and
|
||||||
reference. This is because we need to be able to pass the temporaries
|
temporaries cannot be bound to non-``const`` reference parameters,
|
||||||
created from the operator= call. Because of this, passing non-const
|
our forwarding functions need to take their arguments by ``const``
|
||||||
references that aren't bound to a keyword isn't possible without some help.
|
reference [#forwarding]_. As a result, an argument which is bound
|
||||||
|
to a keyword with ``operator=`` can be transparently passed by
|
||||||
|
non-const reference, but positional arguments are always passed by
|
||||||
|
``const`` reference unless we use the `Boost.Ref`_ library to
|
||||||
|
indicate otherwise::
|
||||||
|
|
||||||
.. DWA What is "something something ?" supposed to mean?
|
#include <boost/ref.hpp>
|
||||||
.. It's was suppose to mean "more?"..
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
float x;
|
float x;
|
||||||
foo(value = x); // held type is float&
|
foo(value = x); // held type is float&
|
||||||
foo(x); // held type is float const&, need help!
|
foo(x); // held type is float const&, need help!
|
||||||
foo(ref(x)); // held type is float&
|
foo(boost::ref(x)); // held type is float&
|
||||||
|
|
||||||
Instances of boost::reference_wrapper<> will un unwrapped to it's held
|
.. _`Boost.Ref`: ../../bind/ref.hpp
|
||||||
reference type.
|
|
||||||
|
|
||||||
SFINAE restrictions
|
|
||||||
===================
|
|
||||||
|
|
||||||
Sometimes it is necessary to restrict the types on which the forwarding
|
Instances of ``boost::reference_wrapper<>`` generated by
|
||||||
functions can be instantiated. This can be accomplished in C++ by using
|
``boost::ref`` will be unwrapped automatically by the library.
|
||||||
SFINAE [#sfinae]_. If type substitution
|
|
||||||
during the instantiation of a function template results in an invalid
|
|
||||||
type, no compilation error is emitted; instead the overload is removed
|
|
||||||
from the overload set. By producing an invalid type in the function
|
|
||||||
signature depending on the result of some condition, whether or not an
|
|
||||||
overload is considered during overload resolution can be controlled.
|
|
||||||
This technique is formalized in the ``enable_if`` pattern [#enable_if]_.
|
|
||||||
|
|
||||||
.. [#sfinae] Substitution Failure Is Not An Error. Some discussion
|
Controlling Overload Resolution
|
||||||
of SFINAE goes here.
|
===============================
|
||||||
|
|
||||||
.. [#enable_if] Some discussion of ``enable_if`` goes here.
|
The parameters of our templated forwarding functions are completely
|
||||||
|
general; in fact, they're a perfect match for any argument type
|
||||||
|
whatsoever. The problems with exposing such general function
|
||||||
|
templates have been the subject of much discussion; especially in
|
||||||
|
the presence of `unqualified calls`__. Probably the safest thing
|
||||||
|
to do is to isolate the forwarding functions in a namespace
|
||||||
|
containing no types [#using]_, but often we'd *like* our functions
|
||||||
|
to play nicely with argument-dependent lookup and other function
|
||||||
|
overloads. In that case, it's neccessary to somehow remove the
|
||||||
|
functions from the overload set when the passed argument types
|
||||||
|
don't meet their needs.
|
||||||
|
|
||||||
.. more?
|
__ http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#225
|
||||||
|
|
||||||
.. DWA What about tutorial for your macro?
|
This overload control can be accomplished in C++ by taking
|
||||||
Daniel: Under BOOST_NAMED_PARAMS_FUN(), should it be moved?
|
advantage of SFINAE_ (Substitution Failure Is Not An Error). If
|
||||||
or do we need a more verbose tutorial?
|
type substitution during the instantiation of a function template
|
||||||
|
results in an invalid type, no compilation error is emitted;
|
||||||
|
instead the overload is removed from the overload set. By producing
|
||||||
|
an invalid type in the function signature depending on the result
|
||||||
|
of some condition, whether or not an overload is considered during
|
||||||
|
overload resolution can be controlled. This technique is
|
||||||
|
formalized in the |enable_if| utility.
|
||||||
|
|
||||||
Let's say we want to restrict our ``foo()`` so that the ``name``
|
The named parameters library provides built-in SFINAE support
|
||||||
parameter must be convertible to ``const char*``.
|
through the following class template::
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Keyword
|
class KeywordTag
|
||||||
, class HasDefaultValue
|
, class HasDefaultValue // mpl::true_ or mpl::false_
|
||||||
, class Predicate
|
, class Predicate
|
||||||
>
|
>
|
||||||
struct arg;
|
struct arg;
|
||||||
|
|
||||||
::
|
The key parameter, ``Predicate`` shall be a unary MPL lambda
|
||||||
|
expression or `Metafunction Class`_ that, when applied to the
|
||||||
|
actual type the argument, indicates whether that argument type
|
||||||
|
meets the function's requirements for that parameter position.
|
||||||
|
|
||||||
|
.. _`Metafunction Class`: ../../mpl/doc/ref/Metafunction_Class.html
|
||||||
|
|
||||||
|
.. _SFINAE: http://www.semantics.org/once_weakly/w02_SFINAE.pdf
|
||||||
|
|
||||||
|
.. |enable_if| replace:: ``enable_if``
|
||||||
|
.. _enable_if: ../enable_if.html
|
||||||
|
|
||||||
|
For example, let's say we want to restrict our ``foo()`` so that
|
||||||
|
the ``name`` parameter must be convertible to ``const char*``.
|
||||||
|
We'll replace our use of the ``name_t`` tag with a specialization
|
||||||
|
of ``boost::arg``:
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
struct foo_keywords
|
struct foo_keywords
|
||||||
: keywords<
|
: boost::keywords<
|
||||||
arg<
|
**boost::arg<
|
||||||
name_t
|
name_t
|
||||||
, mpl::false_
|
, mpl::false\_
|
||||||
, is_convertible<mpl::_
|
, is_convertible<mpl::\_, const char\*>
|
||||||
, const char*>
|
>**
|
||||||
>
|
|
||||||
, value_t
|
, value_t
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
::
|
Now we can add an additional optional argument to each of our
|
||||||
|
``foo`` overloads
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
template<class A0>
|
template<class A0>
|
||||||
void foo(const A0& a0
|
void foo(
|
||||||
, foo_keywords::restrict<A0>::type x = foo_keywords())
|
const A0& a0
|
||||||
|
, **foo_keywords::restrict<A0>::type x = foo_keywords()**
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foo_impl(x(a0));
|
foo_impl(x(a0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class A0, class A1>
|
template<class A0, class A1>
|
||||||
void foo(const A0& a0, const A1& a1
|
void foo(
|
||||||
, foo_keywords::restrict<A0,A1>::type x = foo_keywords())
|
const A0& a0, const A1& a1
|
||||||
|
, **foo_keywords::restrict<A0,A1>::type x = foo_keywords()**
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foo_impl(x(a0, a1));
|
foo_impl(x(a0, a1));
|
||||||
}
|
}
|
||||||
|
|
||||||
``BOOST_NAMED_PARAMS_FUN()``
|
These additional parameters are not intended to be used directly
|
||||||
============================
|
by callers; they merely trigger SFINAE by becoming illegal types
|
||||||
|
when the ``name`` argument is not convertible to ``const char*``.
|
||||||
|
|
||||||
To reduce the work needed to write functions which has named parameters,
|
Automatic Overload Generation
|
||||||
|
=============================
|
||||||
|
|
||||||
|
To reduce the work needed to write functions with named parameters,
|
||||||
we supply a macro that generates the boilerplate code.
|
we supply a macro that generates the boilerplate code.
|
||||||
|
|
||||||
Synopsis::
|
Synopsis::
|
||||||
|
|
||||||
BOOST_NAMED_PARAMS(
|
BOOST_NAMED_PARAMS_FUN(
|
||||||
return_type, function_name, keywords_type
|
return_type, function_name, keywords_type
|
||||||
, min_arity, max_arity
|
, min_arity, max_arity
|
||||||
);
|
);
|
||||||
|
|
||||||
Applying this to our original example, we get::
|
To generate all the forwarding functions and the implementation
|
||||||
|
function for our example, we need only apply
|
||||||
|
``BOOST_NAMED_PARAMS_FUN`` like this::
|
||||||
|
|
||||||
BOOST_NAMED_PARAMS_FUN(void, foo, foo_keywords, 0, 2)
|
BOOST_NAMED_PARAMS_FUN(void, foo, foo_keywords, 0, 2)
|
||||||
{
|
{
|
||||||
@@ -318,3 +354,27 @@ Applying this to our original example, we get::
|
|||||||
<< parms[value | 0] << "\n";
|
<< parms[value | 0] << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
.. [#forwarding] One could provide overloads for ``const`` and
|
||||||
|
non-``const`` reference versions of each parameter, but that
|
||||||
|
would quickly become unmanageable. It's known as "the
|
||||||
|
forwarding problem" and has been described in detail in this
|
||||||
|
paper__. The combinatorial explosion is avoided for the
|
||||||
|
parameter of keywords' ``operator=`` because they take only a
|
||||||
|
single argument.
|
||||||
|
|
||||||
|
__ http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm
|
||||||
|
|
||||||
|
|
||||||
|
.. [#using] You can always give the illusion that the function
|
||||||
|
lives in an outer namespace by applying a *using-declaration*::
|
||||||
|
|
||||||
|
namespace foo_overloads
|
||||||
|
{
|
||||||
|
// foo declarations here
|
||||||
|
void foo() { ... }
|
||||||
|
...
|
||||||
|
}
|
||||||
|
using foo_overloads::foo;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user