any_cast с std::any's и std:: необязательный

Если я поставлю T в std::anyЯ могу получить это с any_cast<T>(my_any), Но включает ли стандарт (= C++17, на этапе голосования в данный момент) такую ​​функцию any_cast<T>(optional<any> oa) который возвращается nullopt если оа nullopt а также std::any_cast<T>(oa.value()) иначе? Или что-то вдоль этих линий?

Изменить: так как люди, кажется, предлагают реализации, я также перечислю то, что я использую сейчас:

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

2 ответа

Ничего подобного нет в std::optional предложение или в std::any предложение.

Я предполагаю, что было бы тривиально реализовать использование функции продолжения, поскольку тип возвращаемого значения различается в зависимости от состояния необязательного объекта:

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

добавлять static_assert и / или SFINAE, где необходимо, чтобы ограничить функцию. Значение *o также должны быть направлены в зависимости от oценностная категория. Пример использования:

int out = -1;

std::optional<std::any> x;
x = 10;

any_cast_or_nullopt<int>(x, [&out](int value)
    {
        out = value;
    });

assert(out == 10);

Если std::optional был bind (или же and_then) функция-член (то есть функция на optional<T> который занимает T -> optional<U> и либо вызывает его, либо возвращает nullopt), то вот что вы искали:

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

или, если вы действительно хотите напрямую вызвать any_cast<T> и заниматься броском, map:

optional<T> opt_t = oa.map([](std::any& v) {
    return std::any_cast<T>(v);
});

std::optional не имеет функций продолжения, так что вам придется писать их как функции, не являющиеся членами.

Другие вопросы по тегам