Provide access to result_type
or ResultType
nested type.
More...
Namespaces |
namespace | bslmf |
Detailed Description
- Outline
-
-
- Purpose:
- Provide access to
result_type
or ResultType
nested type.
-
- Classes:
-
- See also:
-
- Description:
- A number of functor classes provide a
typedef
alias for the returned type when invoking the functor. Unfortunately, standard types name this typedef
result_type
whereas BDE types name this typedef
ResultType
. This component facilitates writing code that depends on these typedef
s by providing a uniform interface, bslmf::ResultType
, for extracting the correct alias. bslmf::ResultType<t_FUNC>type
is identical to t_FUNC::result_type
if such a type exists; otherwise, it is identical to t_FUNC::ResultType
if that type exists; otherwise, it is undefined. A fallback type can be optionally specified such that bslmf::ResultType<t_FUNC, t_FALLBACK>type
is identical to t_FALLBACK
if neither t_FUNC::result_type
nor t_FUNC::ResultType
is defined.
- Note that
ResultType
checks only for a nested type within its t_FUNC
parameter; it does not attempt to deduce the return type of calling operator()
the way C++11 std::result_of
does.
-
- Usage:
- In this section we show intended use of this component.
-
- Usage Example 1:
- In this example, we write a C++03-compatible function template,
wrapInvoke<t_FUNC>(t_A1 a1, t_A2 a2)
, that constructs an instance of functor t_FUNC
, invokes it with arguments a1
and a2
, and translates any thrown exception to a generic exception type.
- First, we declare the generic exception type:
struct InvocationException { };
Now, we declare wrapInvoke
. The return type of wrapInvoke
should be the same as the return type of invoking an object of type t_FUNC
. There is no non-intrusive way to deduce the return type of t_FUNC
in C++03. We therefore require that t_FUNC
provide either a result_type
nested type (the idiom used in standard library functors) or a ResultType
nested type (the idiom used in BDE library functors). We use bslmf::ResultType
to automatically select the correct idiom: template <class t_FUNC, class t_A1, class t_A2>
typename bslmf::ResultType<t_FUNC>::type
wrapInvoke(t_A1 a1, t_A2 a2)
{
t_FUNC f;
try {
return f(a1, a2);
}
catch (...) {
throw InvocationException();
}
}
Next, we declare a functor class that compares its arguments, returns the string "less" if a1 < a2
, returns "greater" if a2 > a1
, and throws an exception if neither is true. The return type of this functor is declared using the BDE-style ResultType
nested type: struct LessGreater {
typedef const char *ResultType;
struct BadArgs { };
const char *operator()(long a1, long a2);
};
const char *LessGreater::operator()(long a1, long a2)
{
if (a1 < a2) {
return "less";
}
else if (a2 < a1) {
return "greater";
}
else {
throw BadArgs();
}
}
For comparison, let's also define a plus
functor that conforms to the C++11 standard definition of std::plus
: template <class TYPE>
struct plus {
typedef TYPE first_argument_type;
typedef TYPE second_argument_type;
typedef TYPE result_type;
TYPE operator()(const TYPE& x, const TYPE& y) const { return x + y; }
};
Now, we can use wrapInvoke
with our LessGreater
functor: int main()
{
const char *s = wrapInvoke<LessGreater>(5, -2);
assert(0 == std::strcmp(s, "greater"));
Finally, we confirm that we can also use wrapInvoke
with the functor plus<int>
: int sum = wrapInvoke<plus<int> >(5, -2);
assert(3 == sum);
return 0;
}
-
- Usage Example 2:
- This example extends the previous one by considering a functor that does not declare either
result_type
or ResultType
. The PostIncrement
functor performs the operation *a += b
and returns the old value of *a
: struct PostIncrement {
int operator()(int *a, int b)
{
unsigned tmp = *a;
*a += b;
return tmp;
}
};
Unfortunately, the following innocent-looking code is ill-formed; even though the return value is being discarded, the return type of wrapInvoke
is undefined because bslmf::ResultType<PostIncrement>type
is undefined: To make wrapInvoke
usable in these situations, we define a new version, wrapInvoke2
, that will fall back to a void
return type if neither t_FUNC::result_type
nor t_FUNC::ResultType
is defined: This use of the fallback parameter allows us to use bslmf::ResultType
in a context where the return type of a function might be ignored: int main()
{
int x = 10;
wrapInvoke2<PostIncrement>(&x, 2);
assert(12 == x);
return 0;
}