2016-10-06 3 views
2

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

Edit: Так как люди, кажется, предлагая реализации, я буду также список того, что я использую сейчас:

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

ответ

0

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

1

В std::optional proposal или в std::any proposal ничего не упоминается.

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

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

Мне нравится ваше предложение, но вам действительно нужны 3 аргумента шаблона? – einpoklum

+0

Если вы хотите правильности и гибкости, да: 'T' используется для' any_cast'; 'TOptional' используется для совершенства-пересылки значения опциона; 'TF' используется для общего вызываемого объекта. Вы можете реализовать его без 'TOptional', но вам потребуется повторение кода, чтобы правильно перемещать' * o', когда 'o' передается как r-значение. –

+0

Но у меня нет f. Вы заставляете меня комбинировать кастинг с использованием его результата, который не похож ни на какой бросок. – einpoklum