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

为何含显式拷贝构造函数的类无法作为std::variant的类型?

std::variant 含显式拷贝构造函数类的编译问题分析

当使用类作为std::variant的备选类型时,若其中某个类拥有显式拷贝构造函数,编译器会直接报错;而使用默认生成或非显式的拷贝构造函数时,代码可正常编译。示例代码如下:

#include <iostream>
#include <cstdint>
#include <variant>

class A
{
    int m_a{0};
public:
    A() = default;
    A(int a) : m_a{a}
    {
        std::cout << "construct a" << std::endl;
    }
};

class B
{
    int m_b{0};
public:
    B() = default;
    B(int b) : m_b{b}
    {
        std::cout << "construct b" << std::endl;
    }

    //B(const B& other)             // <-- 可正常编译
    explicit B(const B& other)      // <-- 编译失败
    {
        m_b = other.m_b;
    }
};

class C
{
    int m_c{0};
public:
    C() = default;
    C(int c) : m_c{c}
    {
        std::cout << "construct c" << std::endl;
    }
};

int main()
{
    std::variant<A, B, C> v;

    B b{123};
    v = b;

    return 0;
}

原因分析

这是C++标准的刻意限制,核心逻辑如下:

  • std::variant的赋值操作(如v = b)需要将目标对象隐式拷贝构造为对应类型的临时实例,再完成变体内部的存储替换。
  • 被标记为explicit的拷贝构造函数会禁止所有隐式调用场景,这直接违反了std::variant对备选类型的要求——C++标准规定,std::variant的备选类型必须满足可复制构造(CopyConstructible)概念,而该概念明确要求拷贝构造函数支持隐式调用(即不能是显式的)。

MSVC、GCC和Clang均严格遵循标准规范,因此都会触发类似的编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:25:24