如何正确检查 any_cast 可用?

问题描述

我有一些输入,可以是简单的值或容器,封装在 std::any 中。我不想使用异常,所以我调用 noexcept 可变参数 any_cast 方法,该方法返回指向 any 值的指针或 nullptr

我可以使用 typeid() 验证任何可用的演员表,但我不想使用它并想找到一些替代方法。一些 typetraits 方法,例如 decltypedeclval 等。或者简单地使用 std::optional

但在这种情况下,可选似乎仍然潮湿和不稳定。 MSVC 编译器程序在运行时在 std::optional 源代码的深处中断。

#include <optional>
#include <any>
#include <utility>

int main() {

int input = 1; 

std::initializer_list<int> input2;
input2 = {1,2,3}; 

std::any any1 = input;
std::any any2 = input2;

std::optional o1 = *std::any_cast<int>(&any1);
std::optional p2 = *std::any_cast<int>(&any2);

// **std::forward<int & __ptr64>**(...) in  _Optional_destruct_base return nullptr.

}

实际上,typetraits 检查将是测试 any_cast 可能性的最佳方式。但我仍然对 C++ 元编程感到困惑。

解决方法

永远不要在不知道指针非空的情况下取消引用它。

这通常适用于所有可空类型;在 C++ 中,这些通常是支持一元 *-> 的类型。

std::optional o1 = std::any_cast<int>(&any1)?*std::any_cast<int>(&any1):std::optional<int>();

例如。

任何对可空类型的取消引用都是 UB,就 C++ 标准而言,它可以工作、崩溃或做任何其他事情。

但如果您的存储类型集是关闭的(不改变),也要考虑 std 变体。

,

如果您想坚持使用 std::optional 并且不想使用指针,我认为您可以编写自己的函数来为您执行指针检查并返回正确的 std::optional,例如:

template <typename T>
std::optional<T> get_v_opt(const std::any & a)
{
    if(const T * v = std::any_cast<T>(&a))
        return std::optional<T>(*v);
    else
        return std::nullopt;
}

这里是如何使用这样一个函数的用法示例:

int main()
{
    std::any a(42);

    std::optional opt_int = get_v_opt<int>(a);
    std::optional opt_str = get_v_opt<std::string>(a);

    if(opt_int.has_value())
        std::cout << "a is an int with value: " << opt_int.value() << '\n';
    else
        std::cout << "a is not an int\n";

    if(opt_str.has_value())
        std::cout << "a is a string with value: " << opt_str.value() << '\n';
    else
        std::cout << "a is not a string\n";

    return 0;
}

输出(对于这个例子):

a 是一个 int 值:42
a 不是字符串

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...