对于std::any
和std::variant
,我们有函数来请求对象有关当前包含的值,如果无法满足请求则返回nullptr
(就像dynamic_cast
那样) :
template<class ValueType>
const ValueType *any_cast(const any *operand);
template<class ValueType>
ValueType *any_cast(any *operand);
和
template <class T, class... Types>
std::add_pointer_t<T> get_if(variant<Types...> *pv);
template <class T, class... Types>
std::add_pointer_t<const T> get_if(const variant<Types...> *pv);
两者都将指针作为参数。为什么?效率不高。实现每次都检查参数是否不是nullptr
。 nullptr
论证是否有意义?
此函数可以是类成员,也可以将引用作为参数(可能名称略有不同)。这样的次优设计的原因是什么?只是模仿dynamic_cast
界面?
答案 0 :(得分:4)
为了使其功能保持其中一个,并使其像_cast
运算符中的buikt一样工作,any_cast
可以使用引用或指针。
指针版本采用指针,如果它包含您要求的内容,则返回指向该元素的指针。否则返回nullptr。
参考版本会引用,如果它不包含您要求的内容,则会抛出。
他们使用参数的指针来区分这两个选项,匹配dynamic_cast<T&>(x)
和dynamic_cast<T*>(&x)
的工作方式。
内联很容易。针对指针到自动存储对象的null的内联检查很容易被优化为&#34; not null&#34;,因为没有一致的方法使自动存储对象的地址为nullptr。
因此,在发行版的几乎所有情况下,我都希望check-if-nullptr的开销为零。一个例外是代码具有指向任何(或变体)的指针,它有一些证据证明这个指针指向任何不是null的编译器不太可能知道,然后它将它传递给{{1 }}。如果他们没有使用指向指针指针返回类型的技巧,那么可能会出现风险&#34; UB使用any_cast
并无条件地取消引用指针。
缺少真正的API是any_cast_to_ptr(any&)
,如果类型不匹配,它只会执行UB,因为关于dangerous_any_cast
状态的非经证实的知识似乎比非经证实的无效知识更有可能指向任何指针。
这种情况很少见。
对于any
vs get_if
,我不知道为什么没有get
重载。