Reputation: 131636
If I put a T
into an std::any
, I can get it with any_cast<T>(my_any)
. But does the standard (= C++17, in the ballot phase at the moment) include a function like any_cast<T>(optional<any> oa)
which returns nullopt
if oa is nullopt
and std::any_cast<T>(oa.value())
otherwise? Or something along those lines?
Edit: Since people seem to be suggesting implementations, I'll also list what I use for now:
/* using magic here to select between boost/std::experimental/std versions */
template<typename T>
inline const optional<T> any_cast(const optional<any>& operand)
{
return operand ?
optional<T>(any_cast<T>(operand.value())) :
optional<T>(nullopt);
}
Upvotes: 3
Views: 1396
Reputation: 303107
If std::optional
had a bind
(or and_then
) member function (that is, a function on optional<T>
which takes a T -> optional<U>
and either invokes it or returns nullopt
), then that's what you'd be looking for:
std::optional<std::any>> oa;
optional<T> opt_t = oa.bind([](std::any& v) -> std::optional<T> {
if (T* t = std::any_cast<T>(&v)) {
return *t;
}
else {
return std::nullopt;
}
});
or, if you really want to directly invoke any_cast<T>
and deal with throwing, map
:
optional<T> opt_t = oa.map([](std::any& v) {
return std::any_cast<T>(v);
});
std::optional
has no continuation functions though, so you'd have to write those as non-member functions.
Upvotes: 0
Reputation: 93294
There is no mention of anything like that in the std::optional
proposal or in the std::any
proposal.
I suppose it would be trivial to implement using a continuation function, since the return type is different depending on the state of the optional object:
template <typename T, typename TOptional, typename TF>
void any_cast_or_nullopt(TOptional&& o, TF&& f)
{
if(!o) return;
f(std::any_cast<T>(*o));
}
Add static_assert
and/or SFINAE where appropriate to constrain the function. The value *o
should also be forwarded depending on o
's value category. Example usage:
int out = -1;
std::optional<std::any> x;
x = 10;
any_cast_or_nullopt<int>(x, [&out](int value)
{
out = value;
});
assert(out == 10);
Upvotes: 1