Reputation: 812
Let's consider this code:
#include <iostream>
#include <variant>
struct Foo {
#if 0
Foo() = default;
Foo(const Foo&) = delete;
#endif
void foo() { std::cout << "foo" << '\n'; }
};
using MyVariant = std::variant<Foo>;
MyVariant& getVariant() {
static MyVariant variant{Foo{}};
return variant;
}
int main() {
auto& variant = getVariant();
auto& foo = std::get<Foo>(variant);
foo.foo();
}
It compiles and prints "foo".
If you change the #if 0
by #if 1
, making Foo
a non copyable class, then the code no longer compiles.
Why do I want Foo to be non copyable? To avoid errors "unexpected copies" with something like auto variant = getVariant();
(note the that &
is missing compared to the original code).
I can't fin the correct syntax for this code. Maybe there is none... My purpose is to select an alternative the first time the function is called, and the variant will not be modified later (it will always hold the same alternative).
What do you suggest? Thanks!
Upvotes: 0
Views: 1457
Reputation: 136266
Statement MyVariant variant{Foo{}};
requires Foo
to have an available copy or move constructor, but there isn't one. When you delete
the copy constructor that also makes the move constructor non-declared, so that you need to declare that move constructor explicitly for to compile.
auto foo = std::get<Foo>(variant)
requires a copy constructor. Use a reference instead.
A couple of these fixes to make it compile:
struct Foo {
Foo() = default;
Foo(const Foo&) = delete;
Foo(Foo&&) = default; // <--- Declare move constructor.
void foo() { std::cout << "foo" << '\n'; }
};
using MyVariant = std::variant<Foo>;
MyVariant& getVariant() {
static MyVariant variant{Foo{}};
return variant;
}
int main() {
auto& variant = getVariant();
auto& foo = std::get<Foo>(variant); // <--- Use reference.
foo.foo();
}
Upvotes: 4