Если я поставлю 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);
}
Ничего подобного нет в 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
не имеет функций продолжения, так что вам придется писать их как функции, не являющиеся членами.