Reputation: 3632
I am trying to get a std::bad_variant_access
exception when the variant is not in the list .But the below code doesn't work it returns a implicit converted ASCII int value
what changes should I do that variant is strict on type selection
#include <iostream>
#include <variant>
using namespace std;
struct printer
{
void operator()(int x) {
cout << x << "i"<<endl;
}
void operator()(float x) {
cout << x << "f"<<endl;
}
void operator()(double x)
{
cout << x << "d" << endl;;
}
};
int main() {
using my_variant = std::variant<int, float, double>;
my_variant v0('c');
try {
std::visit(printer{}, v0);
}
catch(const std::bad_variant_access& e) {
std::cout << e.what() << '\n';
}
return 0;
}
Output:
99i
Whereas I was expecting to get std::bad_variant_access
exception
Upvotes: 2
Views: 3587
Reputation: 41110
std::visit
will only trigger a bad_variant_access
exception if the variant is valueless_by_exception (C++17, see N4659 23.7.3.5 [variant.status] )
What this means is that if you tried to set a variant value in a fashion that throws an exception, the variant is left in a "valueless" state, so visitation is not permitted.
To trigger it, we can change the code like so:
struct S{
operator int() const{throw 42;}
};
struct printer{//as before};
int main() {
using my_variant = std::variant<int, float, double>;
my_variant v0{'c'};
try{
v0.emplace<0>(S());
}catch(...){}
try {
std::visit(printer{}, v0);
}
catch(const std::bad_variant_access& e) {
std::cout << e.what() << '\n';
}
}
Frank already answered why you could construct your variant in the first place using a char
(construction chosen via overload).
You can not trigger a bad_variant_access
by attempting to first construct a variant in a fashion that will throw because [variant.ctor] dictates that the constructor will rethrow that exception (in this case int
).
Upvotes: 3
Reputation:
According to the documentation for std::variant
:
That constructor of variant does the following:
Constructs a variant holding the alternative type T_j that would be selected by overload resolution for the expression F(std::forward(t)) if there was an overload of imaginary function F(T_i) for every T_i from Types... in scope at the same time. [...]
I.e. std::variant will get the first type that is constructible from the passed argument. In this case, int
is constructible from a char
, so the variant gets assigned as such.
Upvotes: 2