为何is_assignable_v<int, int>与is_assignable_v<int&, int>结果不同?
关于
std::is_assignable_v的结果差异解释 核心判定逻辑
std::is_assignable_v<T, U>的本质是检查表达式std::declval<T>() = std::declval<U>()是否能通过编译,而非直觉里“类型T能不能接受类型U的值”,这是理解结果差异的关键。
为什么is_assignable_v<int, int>返回false
std::declval<int>()返回的是int&&类型的右值(纯右值)。- C++中,赋值运算符的左操作数必须是可修改的左值——右值是临时值,无法被赋值(就像你不能写
5 = 3一样)。 - 因此
std::declval<int>() = std::declval<int>()等价于int&& = int&&,这是非法语句,所以is_assignable_v<int, int>返回false。
为什么is_assignable_v<int&, int>返回true
std::declval<int&>返回的是int&类型的左值引用,而非“int右值的引用”。std::declval<T>的规则是:如果T是引用类型,直接返回T类型的引用(左值引用就返回左值引用,右值引用返回右值引用)。- 此时表达式
std::declval<int&>() = std::declval<int>()等价于调用int的赋值运算符int& operator=(int):左操作数是可修改的左值(int&指向的对象),右操作数的int&&可以隐式转换为int类型的值,赋值操作合法,因此is_assignable_v<int&, int>返回true。
澄清引用绑定的疑问
非const的左值引用(int&)确实不能直接绑定到纯右值(比如5),但这里的场景不是绑定引用,而是赋值操作:赋值运算符只要求右操作数可以转换为目标类型,左操作数是可修改的左值即可,和引用绑定的规则无关。
内容的提问来源于stack exchange,提问作者myoldgrandpa
相关产品推荐
相关产品推荐

