为何含显式拷贝构造函数的类无法作为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
相关产品推荐
相关产品推荐

