is_constructible_v<std::string&&, std::string&&>含义及与同类表达式的区别
两个
is_constructible_v表达式的区别解析 先明确std::is_constructible_v<T, Args...>的核心作用:判断能否用Args类型的参数,完成T类型的初始化——注意这里的初始化不一定是构造对象,当T是引用类型时,本质是判断引用绑定是否合法。
第一个表达式:is_constructible_v<std::string, std::string&&>
这个判断的是:能不能用一个std::string右值(或右值引用)作为参数,构造出一个std::string对象。
结果为true,因为std::string自带移动构造函数,参数正好是std::string&&,专门用来把右值string的资源转移到新对象中,完全匹配这个场景。
第二个表达式:is_constructible_v<std::string&&, std::string&&>
这里的目标类型是std::string&&(右值引用类型),所以它根本不是在判断“构造右值对象”,而是:能不能把一个std::string&&类型的表达式,绑定到std::string&&类型的引用上。
根据C++规则,右值引用可以绑定到右值表达式,而declval<std::string&&>()属于右值表达式,所以这个绑定合法,结果也是true。但要明确:这里没有构造任何std::string对象,只是完成了引用的绑定。
你的疑问关键点解答
- “构造右值”是误解:右值是表达式的属性(值类别),不是可被构造的类型。
std::string&&是引用类型,不是对象类型,不存在“构造右值”的说法,第二个表达式本质是判断引用绑定的合法性。 - 构造函数和右值的关系:构造函数用来构造
T类型的对象,构造出的对象可以是左值(比如std::string s("a")里的s)或右值(比如std::string("a"))。但is_constructible_v<T&&, ...>和构造函数无关,它处理的是引用绑定,而非对象构造。 - 不是所有可构造的
T,is_constructible_v<T&&, Args...>都为true:比如is_constructible_v<std::string&&, const std::string&>的结果就是false——因为右值引用不能绑定到const左值引用对应的左值表达式。
内容的提问来源于stack exchange,提问作者myoldgrandpa
相关产品推荐
相关产品推荐

