forked from boostorg/utility
*** empty log message ***
[SVN r1870]
This commit is contained in:
@@ -36,9 +36,7 @@ parameters with default values, but as the number of parameters
|
|||||||
grows, so does the inconvenience of specifying parameters in the
|
grows, so does the inconvenience of specifying parameters in the
|
||||||
correct order, especially in the presence of default values:
|
correct order, especially in the presence of default values:
|
||||||
|
|
||||||
.. DWA please show examples of each of these as I've demonstrated below
|
* It can become difficult for readers to understand the meaning of
|
||||||
|
|
||||||
* It can become difficult readers to understand the meaning of
|
|
||||||
arguments at the call site::
|
arguments at the call site::
|
||||||
|
|
||||||
window* w = new_window("alert", true, true, false, 77, 65);
|
window* w = new_window("alert", true, true, false, 77, 65);
|
||||||
@@ -56,11 +54,19 @@ correct order, especially in the presence of default values:
|
|||||||
window* w = new_window("alert2", movability); // error!
|
window* w = new_window("alert2", movability); // error!
|
||||||
|
|
||||||
* Default values can not depend on the values of other function
|
* Default values can not depend on the values of other function
|
||||||
parameters.
|
parameters::
|
||||||
|
|
||||||
|
window* new_window(
|
||||||
|
char const* name, bool border, ...
|
||||||
|
, int width = 100, int heigh = width); // error!
|
||||||
|
|
||||||
* Template types can not be deduced from the default values,
|
* Template types can not be deduced from the default values,
|
||||||
meaning we have to resort to overloading to provide default
|
meaning we have to resort to overloading to provide default
|
||||||
values for parameters with template type.
|
values for parameters with template type::
|
||||||
|
|
||||||
|
template<class T> void f(T x = 0);
|
||||||
|
|
||||||
|
f(); // error!
|
||||||
|
|
||||||
This library is an attempt to address the problems outlined above
|
This library is an attempt to address the problems outlined above
|
||||||
by associating each parameter with a keyword identifier. Using
|
by associating each parameter with a keyword identifier. Using
|
||||||
@@ -80,122 +86,18 @@ argument position::
|
|||||||
The tutorial has to come before all the nasty details below.
|
The tutorial has to come before all the nasty details below.
|
||||||
I'm going to comment on that and leave the next stuff alone
|
I'm going to comment on that and leave the next stuff alone
|
||||||
|
|
||||||
``reference_wrapper<>``
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Our forwarding functions need to take their parameters by const
|
|
||||||
reference. This is because we need to be able to pass the temporaries
|
|
||||||
created from the operator= call. Because of this, passing non-const
|
|
||||||
references isn't possible without some help.
|
|
||||||
|
|
||||||
.. something something ?
|
|
||||||
|
|
||||||
.. DWA What is "something something ?" supposed to mean?
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
float x;
|
|
||||||
foo(value = boost::ref(x));
|
|
||||||
|
|
||||||
Will be unwrapped, so the type of ``value`` will actually be ``float&``.
|
|
||||||
|
|
||||||
|
|
||||||
SFINAE restrictions
|
|
||||||
===================
|
|
||||||
|
|
||||||
Sometimes it is necessary to restrict the types on which the forwarding
|
|
||||||
functions can be instantiated. This can be accomplished in C++ by using
|
|
||||||
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
|
|
||||||
of SFINAE goes here.
|
|
||||||
|
|
||||||
.. [#enable_if] Some discussion of ``enable_if`` goes here.
|
|
||||||
|
|
||||||
.. more?
|
|
||||||
|
|
||||||
.. DWA What about tutorial for your macro?
|
|
||||||
|
|
||||||
Let's say we want to restrict our ``foo()`` so that the ``name``
|
|
||||||
parameter must be convertible to ``const char*``.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Keyword
|
|
||||||
, class HasDefaultValue
|
|
||||||
, class Predicate
|
|
||||||
>
|
|
||||||
struct arg;
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
struct foo_keywords
|
|
||||||
: keywords<
|
|
||||||
arg<
|
|
||||||
name_t
|
|
||||||
, mpl::false_
|
|
||||||
, is_convertible<mpl::_
|
|
||||||
, const char*>
|
|
||||||
>
|
|
||||||
, value_t
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
template<class A0>
|
|
||||||
void foo(const A0& a0
|
|
||||||
, foo_keywords::restrict<A0>::type x = foo_keywords())
|
|
||||||
{
|
|
||||||
foo_impl(x(a0));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class A0, class A1>
|
|
||||||
void foo(const A0& a0, const A1& a1
|
|
||||||
, foo_keywords::restrict<A0,A1>::type x = foo_keywords())
|
|
||||||
{
|
|
||||||
foo_impl(x(a0, a1));
|
|
||||||
}
|
|
||||||
|
|
||||||
.. something more?
|
|
||||||
|
|
||||||
|
|
||||||
``BOOST_NAMED_PARAMS_FUN()``
|
|
||||||
============================
|
|
||||||
|
|
||||||
To reduce the work needed to write functions which has named parameters,
|
|
||||||
we supply a macro that generates the boilerplate code.
|
|
||||||
|
|
||||||
Synopsis::
|
|
||||||
|
|
||||||
BOOST_NAMED_PARAMS(
|
|
||||||
return_type, function_name, keywords_type
|
|
||||||
, min_arity, max_arity
|
|
||||||
);
|
|
||||||
|
|
||||||
Applying this to our original example, we get::
|
|
||||||
|
|
||||||
BOOST_NAMED_PARAMS_FUN(void, foo, foo_keywords, 0, 2)
|
|
||||||
{
|
|
||||||
std::cout
|
|
||||||
<< parms[name | "unnamed"] << " = "
|
|
||||||
<< parms[value | 0] << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Tutorial
|
Tutorial
|
||||||
========
|
========
|
||||||
|
|
||||||
.. DWA you need some set-up here describing the problem you're
|
.. DWA you need some set-up here describing the problem you're
|
||||||
going to solve.
|
going to solve.
|
||||||
|
|
||||||
|
This example shows how to wrap a function::
|
||||||
|
|
||||||
|
void foo(char const* name, float value);
|
||||||
|
|
||||||
|
to give both parameters names and default values.
|
||||||
|
|
||||||
Defining the keywords
|
Defining the keywords
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -303,3 +205,112 @@ Now compiles, and prints::
|
|||||||
bar = 0
|
bar = 0
|
||||||
unnamed = 3
|
unnamed = 3
|
||||||
|
|
||||||
|
``reference_wrapper<>``
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Our forwarding functions need to take their parameters by const
|
||||||
|
reference. This is because we need to be able to pass the temporaries
|
||||||
|
created from the operator= call. Because of this, passing non-const
|
||||||
|
references that aren't bound to a keyword isn't possible without some help.
|
||||||
|
|
||||||
|
.. DWA What is "something something ?" supposed to mean?
|
||||||
|
.. It's was suppose to mean "more?"..
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
float x;
|
||||||
|
foo(value = x); // float&
|
||||||
|
foo(x); // type is float const&, need help!
|
||||||
|
foo(ref(x)); // type is float&
|
||||||
|
|
||||||
|
Instances of boost::reference_wrapper<> will un unwrapped to it's held
|
||||||
|
reference type.
|
||||||
|
|
||||||
|
SFINAE restrictions
|
||||||
|
===================
|
||||||
|
|
||||||
|
Sometimes it is necessary to restrict the types on which the forwarding
|
||||||
|
functions can be instantiated. This can be accomplished in C++ by using
|
||||||
|
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
|
||||||
|
of SFINAE goes here.
|
||||||
|
|
||||||
|
.. [#enable_if] Some discussion of ``enable_if`` goes here.
|
||||||
|
|
||||||
|
.. more?
|
||||||
|
|
||||||
|
.. DWA What about tutorial for your macro?
|
||||||
|
Daniel: Under BOOST_NAMED_PARAMS_FUN(), should it be moved?
|
||||||
|
or do we need a more verbose tutorial?
|
||||||
|
|
||||||
|
Let's say we want to restrict our ``foo()`` so that the ``name``
|
||||||
|
parameter must be convertible to ``const char*``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
template<
|
||||||
|
class Keyword
|
||||||
|
, class HasDefaultValue
|
||||||
|
, class Predicate
|
||||||
|
>
|
||||||
|
struct arg;
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct foo_keywords
|
||||||
|
: keywords<
|
||||||
|
arg<
|
||||||
|
name_t
|
||||||
|
, mpl::false_
|
||||||
|
, is_convertible<mpl::_
|
||||||
|
, const char*>
|
||||||
|
>
|
||||||
|
, value_t
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
template<class A0>
|
||||||
|
void foo(const A0& a0
|
||||||
|
, foo_keywords::restrict<A0>::type x = foo_keywords())
|
||||||
|
{
|
||||||
|
foo_impl(x(a0));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class A0, class A1>
|
||||||
|
void foo(const A0& a0, const A1& a1
|
||||||
|
, foo_keywords::restrict<A0,A1>::type x = foo_keywords())
|
||||||
|
{
|
||||||
|
foo_impl(x(a0, a1));
|
||||||
|
}
|
||||||
|
|
||||||
|
``BOOST_NAMED_PARAMS_FUN()``
|
||||||
|
============================
|
||||||
|
|
||||||
|
To reduce the work needed to write functions which has named parameters,
|
||||||
|
we supply a macro that generates the boilerplate code.
|
||||||
|
|
||||||
|
Synopsis::
|
||||||
|
|
||||||
|
BOOST_NAMED_PARAMS(
|
||||||
|
return_type, function_name, keywords_type
|
||||||
|
, min_arity, max_arity
|
||||||
|
);
|
||||||
|
|
||||||
|
Applying this to our original example, we get::
|
||||||
|
|
||||||
|
BOOST_NAMED_PARAMS_FUN(void, foo, foo_keywords, 0, 2)
|
||||||
|
{
|
||||||
|
std::cout
|
||||||
|
<< parms[name | "unnamed"] << " = "
|
||||||
|
<< parms[value | 0] << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user