对于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);
Run Code Online (Sandbox Code Playgroud)
和
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);
Run Code Online (Sandbox Code Playgroud)
两者都将指针作为参数。为什么?它效率不高。实现每次都检查参数是否不是nullptr。请问nullptr参数使得任何意义可言?
此函数可以是类成员或将引用作为参数(名称可能略有不同)。这种次优设计的原因是什么?只是模拟dynamic_cast界面?
为了将函数名称保留为其中之一,并使其像内置_cast运算符一样any_cast工作,可以使用引用或指针。
指针版本采用一个指针,如果它包含您所要求的内容,则返回一个指向该元素的指针。否则返回 nullptr。
参考版本接受一个参考,如果它不包含您要求的内容,则抛出。
他们使用参数的指针来区分这两个选项,匹配如何dynamic_cast<T&>(x)和dynamic_cast<T*>(&x)工作。
内联会很容易。针对指向自动存储对象的指针的空值的内联检查很容易优化为“非空”,因为没有符合自动存储对象地址为 nullptr 的方法。
因此,在几乎所有发布的情况下,我都希望 check-if-nullptr 的开销为零。一个例外是代码有一个指向任何(或变体)的指针,它有一些证据证明这个指向任何的指针不是编译器不太可能知道的空,然后它将它传递给any_cast. 如果他们没有使用指针到指示指针返回类型的技巧,人们可能会“冒险”使用 UBany_cast_to_ptr(any&)并无条件地取消引用指针。
真正缺少的 API 是dangerous_any_cast,如果类型不匹配,它只会执行 UB,因为关于 状态的any非本地证明的知识似乎比关于指向任何指针的无效性的非本地证明的知识更有可能。
这种情况很少见。
至于get_ifvs get,我不知道为什么没有get_if(variant<???>&)过载。