Consider the following:
struct foo {
};
struct bar {
};
int main()
{
foo f;
bar b;
std::variant<foo*, bool> v;
v = &b; // compiles in Visual Studio 19 v16.7.3
}
As discussed in comments, I believe the above is legal C++17. There is a proposal, P0608R3, that was accepted into the standard addressing this kind of surprising behavior, but it was accepted in 2018 (at the San Diego meeting) and thus applies to C++20 not C++17. Further P0608R3 is not currently implemented in Visual Studio, even when compiling to the C++20 preview.
What is the best / least verbose way to make creation of this variant from a pointer that points to a non-foo a compile time error? I believe the following works but is a lot of boilerplate if the variant contains several items.
struct foo {
};
struct bar {
};
using variant_type = std::variant<foo*, bool>;
struct var_wrapper : public variant_type
{
var_wrapper(foo* v = nullptr) : variant_type(v)
{}
var_wrapper(bool v) : variant_type(v)
{}
template<typename T>
var_wrapper(T*) = delete;
};
int main()
{
foo f;
bar b;
var_wrapper vw;
vw = &f; // fine
vw = true; // fine
vw = &b; // compile time error
}
Am I missing some simpler way?
Another solution is to introduce another bool
wrapper that doesn't construct from anything except from bool
:
#include <variant>
struct foo {};
struct bar {};
struct StrongBool {
bool value = false;
StrongBool() noexcept = default;
StrongBool(bool b) noexcept : value(b) {}
template<class T>
StrongBool(T) = delete;
};
int main() {
foo f;
bar b;
std::variant<foo*, StrongBool> v;
v = true;
v = &f;
v = &b; // fails to compile
}
Regardless, limiting acceptable initializers requires introducing type wrappers with user-defined constructors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With