提问者:小点点

返回对std::variant的引用,该变量包含不可复制的替换项


让我们考虑以下代码:

#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();的“意外复制”(请注意,与原始代码相比,&丢失了)。

我找不到这段代码的正确语法。 也许没有。。。 我的目的是在函数第一次被调用时选择一个备选项,以后该变体不会被修改(它将始终持有相同的备选项)。

你有什么建议? 谢啦!


共1个答案

匿名用户

语句MyVariant variant{Foo{}};要求Foo具有可用的复制或移动构造函数,但实际上没有。 当您删除复制构造函数时,该复制构造函数也使移动构造函数成为非声明的,因此您需要显式声明该移动构造函数以进行编译。

auto foo=std::get(variant)需要复制构造函数。 请改用引用。

以下几个修复可以使其编译:

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();
}

相关问题