std::is_constructible 是编译期语法检查,仅验证构造函数签名匹配性,不检查访问控制、requires约束、static_assert或noexcept规格;true不保证T{args...}可安全构造。
std::is_constructible 是编译期判断,不是运行时调用
它不执行构造,只检查类型是否「语法上可构造」——哪怕构造函数是
或会触发
失败,只要签名匹配、未被
,
就可能返回
。真正构造时仍可能报错。
常见误用:以为
为
就能安全写
—— 实际可能因 SFINAE 外的约束(比如
、
、访问控制)失败。
只对「构造函数声明可见性」敏感,不对其实现内容做语义分析
若
的构造函数模板有
约束,
在 C++20 中仍可能返回
,但具体实例化时约束不满足就会编译失败
对
构造函数也成立,它不区分隐式/显式,只看能否构造
注意参数包展开与引用折叠陷阱
和
可能结果不同——前者检查「能否用左值引用构造」,后者检查「能否用右值(或可转换值)构造」。尤其当
的构造函数重载了
和
时,传参类型直接影响匹配结果。
避免直接传
或万能引用类型进
,先用
或明确值类别
测试移动构造可行性?用
,不是
传入
时,记得写
或直接写类型名,别写
(它是个指针字面量,类型非完全一致)
和 std::is_default_constructible / std::is_copy_constructible 不是互斥关系
检查默认构造,但它和
行为不同:后者要求默认构造函数是 public 且非 deleted;而前者只要存在某个默认构造函数签名(哪怕
)就可能为
。
C知道
CSDN推出的一款AI技术问答工具
下载
立即学习
“
C++免费学习笔记(深入)
”;
等价于
,但前者还额外要求该构造函数未被
且可访问(标准库实现中做了访问性检查)
所以不能用
完全替代
,尤其在涉及友元或私有继承时行为不一致
想确认「外部代码能否 copy-construct」?优先用
,而不是手写
模板中使用时,SFINAE 友好但需防硬错误
在
或
中用
是安全的,它是合法的 SFINAE 上下文。但若直接在模板参数列表里写
而没加默认模板参数,一旦条件为
就导致硬编译错误而非静默剔除。
推荐写法:
C++20 更简洁:
切忌在非 SFINAE 上下文中直接依赖其值做
,除非你确定所有实例化路径都应满足——否则会提前炸掉整个模板实例化过程
最易忽略的一点:它不检查
规格。就算
为
,那个构造函数也可能抛异常,而
才管这个。需要强异常保证时,必须单独查后者。
privatestatic_assertdeletestd::is_constructible_vtruestd::is_constructible_vtrueT{args...}requiresstatic_assertTrequiresstd::is_constructibletrueexplicitstd::is_constructible_vstd::is_constructible_vTT(int&&)T(const int&)auto&&is_constructiblestd::decay_tstd::is_constructible_vTstd::nullptr_tstd::nullptr_t{}nullptrstd::is_constructible_vstd::is_default_constructible_vprivatetruestd::is_copy_constructible_vstd::is_constructible_vdeletestd::is_constructible_vstd::is_copy_constructible_vstd::is_copy_constructibleis_constructibleenable_ifrequiresstd::is_constructible_vstd::enable_if_t<:is_constructible_v args...>>falsetemplate, int> = 0> template requires std::is_constructible_v static_assertnoexceptstd::is_constructible_vtruestd::is_nothrow_constructible_v