std::is_copy_constructible 用于编译期检测类型是否具有可访问、非 explicit 的拷贝构造函数,不依赖显式定义而取决于实际可调用性,且与 std::is_trivially_copyable 语义不同。

用 std::is_copy_constructible 最直接
标准库提供了类型 trait std::is_copy_constructible,它在编译期就能告诉你某个类型是否拥有可访问、不被删除的拷贝构造函数。它不关心你是否“手动写了”,只看实际能否调用——比如即使类没显式定义拷贝构造,但所有成员都可拷贝且析构函数可访问,它就返回 true。
注意:它检测的是 非 explicit 的拷贝构造函数;如果只有 explicit T(const T&),std::is_copy_constructible<t>::value</t> 为 false。
示例:
struct A { A(const A&) = default; };
struct B { B(const B&) = delete; };
struct C { explicit C(const C&) {} };
static_assert(std::is_copy_constructible_v<A>); // ✅
static_assert(!std::is_copy_constructible_v<B>); // ✅
static_assert(!std::is_copy_constructible_v<C>); // ✅(explicit 拷贝构造不被认可)
为什么不能只看有没有 class(const class&) 声明
光检查类定义里是否存在拷贝构造函数声明是靠不住的。编译器可能隐式删除它(例如含不可拷贝成员、移动-only 成员、或用户定义了移动构造但没写拷贝),也可能隐式生成它(即使你什么都没写)。
立即学习“C++免费学习笔记(深入)”;
常见误判场景:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 类含
std::unique_ptr<int>成员 → 隐式拷贝构造被定义为= delete - 类有
const成员且无用户定义拷贝构造 → 若 const 成员无默认构造,隐式拷贝构造可能无法生成(或被禁用) - 类继承自不可拷贝基类 → 即使子类没动,拷贝构造也不可用
运行时无法判断,别试图 try/catch 拷贝
拷贝构造是否可用是编译期性质,不是运行时异常行为。写 try { A a = b; } catch(...) {} 不会捕获任何东西——编译直接失败,报错类似:use of deleted function ‘A::A(const A&)’ 或 ‘A::A(const A&)’ is private。
所以这类检查必须放在模板约束、static_assert 或 requires 表达式中,例如:
template<typename T>
void foo(const T& x) requires std::is_copy_constructible_v<T> {
T y = x; // 安全
}
和 std::is_trivially_copyable 不是一回事
新手常混淆这两个 trait:std::is_copy_constructible 关注“能否调用拷贝构造”,而 std::is_trivially_copyable 要求更严——它要求类型可 memcpy(即无用户定义拷贝/移动/析构,所有非静态成员和基类也都 trivially copyable)。一个类可以支持拷贝构造但不是 trivially copyable(比如带虚函数或自定义拷贝构造的类)。
如果你真正想问的是“能不能用 memcpy 安全复制”,那该用后者;如果只是想知道“能不能写 T a = b;”,那就只看前者。
容易被忽略的一点:即使 std::is_copy_constructible_v<T> 为 true,也不能保证拷贝构造函数是 noexcept ——若需强异常安全,还得额外查 std::is_nothrow_copy_constructible。

















