带有 std::any 和 std::optional 的 any_cast
Posted
技术标签:
【中文标题】带有 std::any 和 std::optional 的 any_cast【英文标题】:any_cast with std::any's and std::optional 【发布时间】:2016-10-06 14:48:50 【问题描述】:如果我将T
放入std::any
,我可以使用any_cast<T>(my_any)
得到它。但是标准(= C++17,目前处于投票阶段)是否包含像 any_cast<T>(optional<any> oa)
这样的函数,如果 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);
【问题讨论】:
【参考方案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);
【讨论】:
我喜欢你的建议,但你真的需要 3 个模板参数吗? 如果你想要正确性和灵活性,是的:T
用于any_cast
; TOptional
用于完美转发可选值; TF
用于通用可调用对象。你可以在没有TOptional
的情况下实现它,但是当o
作为右值传递时,你需要重复代码才能正确移动*o
。
但我没有 f。你强迫我将演员阵容与其结果的使用结合起来 - 这不像任何演员。
@einpoklum:您要求一个函数,该函数给出optional<any>
和模板参数T
返回T
实例或nullopt
- 这是不可能的,因为T
和@ 987654342@ 是不相关的类型,因为 optional
的状态仅在运行时才知道。您可以让函数返回 optional<T>
(如 Barry 建议的那样),或使用延续函数以便按照我的建议直接使用 T
。
当然该函数应该返回一个可选的and_then
。如果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
虽然没有延续函数,所以你必须把它们写成非成员函数。
【讨论】:
以上是关于带有 std::any 和 std::optional 的 any_cast的主要内容,如果未能解决你的问题,请参考以下文章
使用带有decltype的std :: any_cast…为什么这段代码会抛出错误的any_cast?
`boost::any` 和 `std::any` 之间的区别
为啥在 dlopen'd 函数中传递的 std::any 的 std::any_cast 会引发错误