yuzu/externals/vcpkg/buildtrees/boost-utility/src/ost-1.79.0-8813e85352.clean/doc/result_of.qbk
2022-11-05 15:35:56 +01:00

422 lines
14 KiB
Plaintext
Executable File

[/
/ Copyright (c) 2012 Marshall Clow
/ Copyright (c) 2021, Alan Freitas
/
/ 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)
/]
[/===============]
[section Result of]
[/===============]
[section Introduction]
The class template __result_of__ helps determine the type of a
call expression. For example, given an lvalue `f` of type `F`
and lvalues `t1`,`t2`, ..., `tN` of types `T1`, `T2`, ..., `TN`,
respectively, the type __result_of__`<F(T1, T2, ..., TN)>::type` defines
the result type of the expression `f(t1, t2, ...,tN)`.
This implementation permits the type `F` to be a function pointer,
function reference, member function pointer, or class type. By default,
N may be any value between 0 and 16. To change the upper limit, define
the macro `BOOST_RESULT_OF_NUM_ARGS` to the maximum value for N. Class
template __result_of__ resides in the header
[@../../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
If your compiler's support for __decltype__ is adequate, __result_of__
automatically uses it to deduce the type of the call expression, in
which case __result_of__`<F(T1, T2, ..., TN)>::type` names the type
__decltype__`(boost::declval<F>()(boost::declval<T1>(),
boost::declval<T2>(), ..., boost::declval<TN>()))`, as in the
following example.
```
struct functor {
template<class T>
T operator()(T x)
{
return x;
}
};
typedef __boost_result_of__<functor(int)>::type type; // type is int
```
You can test whether __result_of__ is using __decltype__ by checking if
the macro `BOOST_RESULT_OF_USE_DECLTYPE` is defined after
including `result_of.hpp`. You can also force __result_of__ to use
__decltype__ by defining `BOOST_RESULT_OF_USE_DECLTYPE` prior
to including `result_of.hpp`.
If __decltype__ is not used, then automatic result type deduction of function
objects is not possible. Instead, __result_of__ uses the following protocol
to allow the programmer to specify a type. When `F` is a class type with a
member type `result_type`, `result_of<F(T1, T2, ..., TN)>::type` is
`F::result_type`. When `F` does not contain `result_type`,
`result_of<F(T1, T2, ..., TN)>::type` is
`F::result<F(T1, T2, ..., TN)>::type` when
`N > 0` or `void` when `N = 0`.
Note that it is the responsibility of the programmer to ensure that
function objects accurately advertise their result
type via this protocol, as in the following example.
```
struct functor {
template <class> struct result;
template<class F, class T>
struct result<F(T)> {
typedef T type;
};
template<class T>
T operator()(T x)
{
return x;
}
};
typedef __boost_result_of__<functor(int)>::type type; // type is int
```
Since __decltype__ is a language feature standardized in C++11, if you are
writing a function object to be used with __result_of__, for maximum
portability, you might consider following the above protocol
even if your compiler has proper __decltype__ support.
If you wish to continue to use the protocol on compilers that
support __decltype__, there are two options:
* You can use __boost_tr1_result_of__, which is also defined in
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
* Alternatively, you can define the macro `BOOST_RESULT_OF_USE_TR1`,
which causes __result_of__ to use the protocol described above instead
of __decltype__. If you choose to follow the protocol, take care to
ensure that the `result_type` and `result<>` members accurately
represent the return type of `operator()` given a call expression.
Additionally, __boost_result_of__ provides a third mode of operation,
which some users may find convenient. When
`BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` is defined,
__boost_result_of__ behaves as follows. If the function object has a member
type `result_type` or member template `result<>`, then __boost_result_of__
will use the TR1 protocol.
Otherwise, __boost_result_of__ will use __decltype__. Using TR1 with
a __decltype__ fallback may workaround certain problems at the cost of portability.
For example:
* Deficient compiler: If your code requires __boost_result_of__ to work
with incomplete return types but your compiler's __decltype__ implementation
does not support incomplete return types, then you can use the TR1 protocol
as a workaround. Support for incomplete return types was added late in the
C++11 standardization process
(see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf N3276])
and is not implemented by some compilers.
* Deficient legacy code: If your existing TR1 function object advertises a different type than
the actual result type deduced by __decltype__, then using TR1 with a __decltype__ fallback
will allow you to work with both your existing TR1 function objects and new C++11
function object. This situation could occur if your legacy function objects
misused the TR1 protocol. See the documentation on known [link sec:result_of_tr1_diff differences]
between __boost_result_of__ and TR1.
* [#BOOST_NO_RESULT_OF] This implementation of __result_of__ requires class template
partial specialization, the ability to parse function types properly, and support
for SFINAE. If __result_of__ is not supported by your compiler, including the header
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`] will define
the macro `BOOST_NO_RESULT_OF`.
For additional information about __result_of__, see the C++ Library
Technical Report, [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf N1836],
or, for motivation and design rationale, the __result_of__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html proposal].
[endsect]
[#sec:result_of_guidelines]
[section Usage guidelines for __boost_result_of__]
The following are general suggestions about when and how to use __boost_result_of__.
# If you are targeting C++11 and are not concerned about portability to
non-compliant compilers or previous versions of the standard, then use
`__std_result_of__`. If `__std_result_of__` meets your needs, then
there's no reason to stop using it.
# If you are targeting C++11 but may port your code to legacy compilers
at some time in the future, then use __boost_result_of__ with __decltype__.
When __decltype__ is used __boost_result_of__ and `__std_result_of__` are usually
interchangeable. See the documentation on known [link sec:result_of_cxx11_diff differences]
between __boost_result_of__ and C++11 __std_result_of__.
# If compiler portability is required, use __boost_result_of__ with the TR1 protocol
Regardless of how you configure __boost_result_of__, it is
important to bear in mind that the return type of a
function may change depending on its arguments, and
additionally, the return type of a member function may
change depending on the cv-qualification of the
object. __boost_result_of__ must be passed
the appropriately cv-qualified types in order to
deduce the corresponding return type.
For example:
```
struct functor {
int& operator()(int);
int const& operator()(int) const;
float& operator()(float&);
float const& operator()(float const&);
};
typedef __boost_result_of__<
functor(int)
>::type type1; // type1 is int &
typedef __boost_result_of__<
const functor(int)
>::type type2; // type2 is int const &
typedef __boost_result_of__<
functor(float&)
>::type type3; // type3 is float &
typedef __boost_result_of__<
functor(float const&)
>::type type4; // type4 is float const &
```
[endsect]
[#sec:result_of_tr1_protocol_guidelines]
[section Usage guidelines for the TR1 result_of protocol]
On compliant C++11 compilers, __boost_result_of__ can
use __decltype__ to deduce the type of any
call expression, including calls to function
objects. However, on pre-C++11 compilers or on
compilers without adequate decltype support,
additional scaffolding is needed from function
objects as described above. The following are
suggestions about how to use the TR1 protocol.
* When the return type does not depend on the
argument types or the cv-qualification of the
function object, simply
define `result_type`. There is no need
to use the `result` template unless the
return type varies.</li>
* Use the protocol specified type when defining
function prototypes. This can help ensure the
actual return type does not get out of sync with
the protocol specification. For example:
```
struct functor {
typedef int result_type;
result_type operator()(int);
};
```
* Always specify the `result` specialization near the corresponding
`operator()` overload. This can make it easier to keep the specializations
in sync with the overloads. For example:
```
struct functor {
template<class> struct result;
template<class F>
struct result<F(int)> {
typedef int& type;
};
result<functor(int)>::type operator()(int);
template<class F>
struct result<const F(int)> {
typedef int const& type;
};
result<const functor(int)>::type operator()(int) const;
};
```
* Use type transformations to simplify
the `result` template specialization. For
example, the following uses [@../type_traits/doc/html/index.html Boost.TypeTraits]
to specialize the `result` template for
a single `operator()` that can be called on
both a const and non-const function object with
either an lvalue or rvalue argument.
```
struct functor {
template<class> struct result;
template<class F, class T>
struct result<F(T)>
: boost::remove_cv<
typename boost::remove_reference<T>::type
>
{};
template<class T>
T operator()(T const&amp; x) const;
};
```
[endsect]
[#sec:result_of_tr1_diff]
[section Known differences between __boost_result_of__ and __boost_tr1_result_of__]
When using __decltype__, __boost_result_of__ ignores the TR1 protocol and instead deduces the
return type of function objects directly via __decltype__. In most situations, users
will not notice a difference, so long as they use the protocol correctly. The following are situations in
which the type deduced by __boost_result_of__ is known to differ depending on whether
__decltype__ or the TR1 protocol is used.
TR1 protocol misusage: When using the TR1 protocol, __boost_result_of__ cannot
detect whether the actual type of a call to a function object is the same as the
type specified by the protocol, which allows for the possibility of inadvertent
mismatches between the specified type and the actual type. When using __decltype__,
these subtle bugs may result in compilation errors. For example:
```
struct functor {
typedef short result_type;
int operator()(short);
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same<__boost_result_of__<functor(short)>::type, int>::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same<__boost_result_of__<functor(short)>::type, short>::value
));
#endif
```
Note that the user can force __boost_result_of__ to use the TR1
protocol even on platforms that support __decltype__ by
defining `BOOST_RESULT_OF_USE_TR1`.
Nullary function objects: When using the TR1 protocol, __boost_result_of__
cannot always deduce the type of calls to nullary function objects, in which case the
type defaults to void. When using __decltype__, __boost_result_of__ always gives the
actual type of the call expression. For example:
```
struct functor {
template<class> struct result {
typedef int type;
};
int operator()();
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same<__boost_result_of__<functor()>::type, int>::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same<__boost_result_of__<functor()>::type, void>::value
));
#endif
```
Note that there are some workarounds for the nullary function problem.
So long as the return type does not vary, `result_type` can always be used to
specify the return type regardless of arity. If the return type does vary,
then the user can specialize __boost_result_of__ itself for nullary calls.
Non-class prvalues and cv-qualification: When using the TR1 protocol, __boost_result_of__ will
report the cv-qualified type specified by `result_type` or the `result` template regardless of
the actual cv-qualification of the call expression. When using __decltype__, __boost_result_of__
will report the actual type of the call expression, which is not cv-qualified when the expression
is a non-class prvalue. For example:
```
struct functor {
template<class> struct result;
template<class F, class T> struct result<F(const T)> {
typedef const T type;
};
const short operator()(const short);
int const & operator()(int const &);
};
// Non-prvalue call expressions work the same with or without decltype.
BOOST_STATIC_ASSERT((
boost::is_same<
__boost_result_of__<functor(int const &)>::type,
int const &
::value
));
// Non-class prvalue call expressions are not actually cv-qualified,
// but only the decltype-based result_of reports this accurately.
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same<
__boost_result_of__<functor(const short)>::type,
short
::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same<
__boost_result_of__<functor(const short)>::type,
const short
::value
));
#endif
```
[endsect]
[#sec:result_of_cxx11_diff]
[section Known differences between __boost_result_of__ and C++11 result_of]
When using __decltype__, __boost_result_of__ implements most of the C++11 __std_result_of__
specification. One known exception is that __boost_result_of__ does not implement the
requirements regarding pointers to member data.
[endsect]
[/===============]
[xinclude tmp/result_of_reference.xml]
[/===============]
[section Acknowledgments]
Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others.
[endsect]
[endsect]