让我们考虑以下代码:
#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();
}
它编译并打印“foo”。
如果您将#If 0
改为#If 1
,使foo
成为不可复制的类,则代码将不再编译。
为什么我希望Foo是不可复制的? 为了避免错误,使用类似auto variant=getVariant();
的“意外复制”(请注意,与原始代码相比,&
丢失了)。
我找不到这段代码的正确语法。 也许没有。。。 我的目的是在函数第一次被调用时选择一个备选项,以后该变体不会被修改(它将始终持有相同的备选项)。
你有什么建议? 谢啦!
语句MyVariant variant{Foo{}};
要求Foo
具有可用的复制或移动构造函数,但实际上没有。 当您删除
复制构造函数时,该复制构造函数也使移动构造函数成为非声明的,因此您需要显式声明该移动构造函数以进行编译。
auto foo=std::get
需要复制构造函数。 请改用引用。
以下几个修复可以使其编译:
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();
}