Reputation: 166
I'm struggling with an odd behavior of the below code. The problem is that output of this snippet is "double"
. But we have an int
in lhs
.
I dug for a while and figured out the compiler put a garbage double
value into var
for some reason. Then this turned the type of the variable into double
. This breaks all my code at the outer scope, because I do some operations according to the type of the variable.
What am I missing? Is it supposed to work like this?
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";
Upvotes: 1
Views: 113
Reputation: 311088
In this declaration:
auto var = std::holds_alternative<int>(lhs) ? std::get<int>(lhs) : std::get<double>(lhs);
The conditional operator is used. The compiler determines the type of the result based on the types of the 2nd and 3rd operands of the operator. Due to the usual arithmetic conversions, the common type is double
. That is (from the C++20 Standard):
- Otherwise, if either operand is double, the other shall be converted to double
Upvotes: 5
Reputation: 275800
std::variant<int, double> lhs = 4;
so lhs
is a variant holding either an int
or a double
. As you stored an int
in it, it holds an int
.
auto var = std::holds_alternative<int>(lhs) ? std::get<int>(lhs) : std::get<double>(lhs);
this is the same as
auto var = true ? std::get<int>(lhs) : std::get<double>(lhs);
which is
auto var = true ? (int)4 : double(3.14);
The type of var
is computed to be double
, but its value is 4
.
double var = 4;
auto
is not a runtime dynamic type; it is a compile time computed type.
if (std::strcmp(typeid(var).name(), "i") == 0)
std::cout << "int";
else
std::cout << "double";
which prints "double"
.
I think what you want to do is this:
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);
which prints "int"
as expected.
Here, we create a visitor function. std::visit
makes a runtime switch to decide which type lhs
contains, and calls the one that matches the type within lhs
.
Be careful, because both versions of the lambda function are instantiated, but only one is called.
Upvotes: 6