简体   繁体   中英

any_cast with std::any's and std::optional

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);
}

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);

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM