You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将不可复制不可移动对象放入std::variant中?

能否将不可复制、不可移动的对象放入std::variant中?

答案是:不能直接将完全不可复制、不可移动的对象放入std::variant中,以下通过代码示例说明原因:

编译失败的示例(对象不可复制、不可移动)

#include <iostream>
#include <variant>
#include <vector>

struct T {
    int _x;
    T(int x) : _x(x) { std::cout << "constructed" << std::endl; }
#if 0
    T(const T& t) : _x(t._x) { std::cout << "copied" << std::endl; }
    T( T&& t) : _x(t._x) { std::cout << "moved" << std::endl; }
#else
    T(const T& t) = delete;
    T(T&& t) = delete;
#endif

};

T make_t(){
    return T(1);
}

int main() {
    std::variant<std::monostate,T> v;
    v.emplace<T>(make_t());
}

这段代码里,结构体T的拷贝构造函数和移动构造函数被显式删除。调用v.emplace<T>(make_t())时,std::variant需要把make_t()返回的临时对象移动或拷贝到自身内部存储,但由于没有可用的移动/拷贝构造函数,编译会直接失败。

编译通过的示例(对象支持复制、移动)

#include <iostream>
#include <variant>
#include <vector>

struct T {
    int _x;
    T(int x) : _x(x) { std::cout << "constructed" << std::endl; }
#if 1
    T(const T& t) : _x(t._x) { std::cout << "copied" << std::endl; }
    T(T&& t) : _x(t._x) { std::cout << "moved" << std::endl; }
#else
    T(const T& t) = delete;
    T(T&& t) = delete;
#endif

};

T make_t(){
    return T(1);
}

int main() {
    std::variant<std::monostate,T> v;
    v.emplace<T>(make_t());
}

这里T提供了有效的拷贝构造函数和移动构造函数,std::variant可以通过移动操作将临时对象存入内部存储,因此编译正常通过。

补充说明

如果想在std::variant中使用不可复制、不可移动的对象,唯一可行的方式是直接在variant内部就地构造该对象——也就是通过emplace直接传递构造参数,而非传入已有的对象实例。比如把main中的代码改成:

v.emplace<T>(1);

此时std::variant会直接在内部存储中调用T(int)构造函数创建对象,不需要依赖拷贝或移动构造函数,这种情况下即使T的拷贝/移动构造函数被删除,代码也能正常编译运行。

内容的提问来源于stack exchange,提问作者bradgonesurfing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:40:31