代码之家  ›  专栏  ›  技术社区  ›  msg

std::variant的奇怪结果

  •  0
  • msg  · 技术社区  · 6 月前

    我正在努力解决以下代码的一个奇怪行为。问题是,此代码段的输出为 "double" 但我们有一个 int 在里面 lhs .

    我挖了一会儿,发现编译器放了垃圾 double 价值进入 var 出于某种原因。然后,这将变量的类型转换为 双重的 。这会破坏我在外部作用域的所有代码,因为我根据变量的类型执行了一些操作。

    我错过了什么?它应该这样工作吗?

    std::variant<int, double> lhs = 4;
    
    auto var = std::holds_alternative<int>(lhs) ? std::get<int>(lhs) : std::get<double>(lhs);
    
    if (std::strcmp(typeid(var).name(), "i") == 0)
        std::cout << "int";
    else
        std::cout << "double";
    
    2 回复  |  直到 6 月前
        1
  •  5
  •   Yakk - Adam Nevraumont    6 月前
    std::variant<int, double> lhs = 4;
    

    所以 lhs 是包含以下任一项的变体 int 或a double .当您存储 int 其中,它包含一个 int .

    auto var = std::holds_alternative<int>(lhs) ? std::get<int>(lhs) : std::get<double>(lhs);
    

    这与

    auto var = true ? std::get<int>(lhs) : std::get<double>(lhs);
    

    这是

    auto var = true ? (int)4 : double(3.14);
    

    类型 var 计算结果为 双重的 ,但它的价值是 4 .

    double var = 4;
    

    auto 不是运行时动态类型;它是一种编译时计算类型。

    if (std::strcmp(typeid(var).name(), "i") == 0)
      std::cout << "int";
    else
      std::cout << "double";
    

    打印 "double" .

    我认为你想做的是:

    std::variant<int, double> lhs = 4;
    
    std::visit( [&](auto var){
      if (std::strcmp(typeid(var).name(), "i") == 0)
        std::cout << "int";
      else
        std::cout << "double";
    }, lhs);
    

    打印 "int" 正如预期的那样。

    在这里,我们创建了一个访问者函数。 std::visit 进行运行时切换以决定哪种类型 lhs 包含并调用与内类型匹配的对象 lhs .

    请小心,因为两个版本的lambda函数都被实例化了,但只调用了一个。

        2
  •  5
  •   Remy Lebeau    6 月前

    在本声明中:

    auto var = std::holds_alternative<int>(lhs) ? std::get<int>(lhs) : std::get<double>(lhs);
    

    使用条件运算符。编译器根据运算符的第二个和第三个操作数的类型确定结果的类型。由于通常的算术转换,常见的类型是 double 即(来自C++20标准):

    • 否则,如果其中一个操作数是double,则另一个应转换为double