三元运算符为什么以及何时返回左值?
Why and when does the ternary operator return an lvalue?
很长一段时间,我认为三元运算符总是返回一个右值。但令我惊讶的是,事实并非如此。在下面的代码中,我没有看到foo
的返回值和三元运算符的返回值之间的区别。
#include <iostream>
int g = 20 ;
int foo()
{
return g ;
}
int main()
{
int i= 2,j =10 ;
foo()=10 ; // not Ok
((i < 3) ? i : j) = 7; //Ok
std::cout << i <<","<<j << "," <<g << std::endl ;
}
i
和j
都是glvalue(有关详细信息,请参阅此值类别参考)。
然后,如果您阅读此条件运算符参考,我们将得出这一点:
4) 如果 E2 和 E3 是相同类型和相同值类别的 gl值,则结果具有相同的类型和值类别
因此,(i < 3) ? i : j
的结果是一个glvalue,可以分配给它。
但是,做这样的事情真的不是我推荐的。
[expr.cond] 中详细介绍了这方面的规则。类型和值类别的多种组合有许多分支。但最终,表达式在默认情况下是一个 prvalue。您的示例中的情况由第 5 段涵盖:
如果第二个和第三个操作数是相同值的 gl值 类别并具有相同的类型,结果是该类型和值 类别,如果第二个或第三个操作数是 位域,或者如果两者都是位字段。
i
和j
都是变量名,是类型int
的左值表达式。因此,条件运算符生成一个int
左值。
如果三元条件运算符的第二个和第三个操作数的类型是左值,则会产生一个左值。
可以使用函数模板is_lvalue
(如下)来确定操作数是否为左值,并在函数模板isTernaryAssignable
中使用它来确定是否可以将其分配给。
一个最小的例子:
#include <iostream>
#include <type_traits>
template <typename T>
constexpr bool is_lvalue(T&&) {
return std::is_lvalue_reference<T>{};
}
template <typename T, typename U>
bool isTernaryAssignable(T&& t, U&& u)
{
return is_lvalue(std::forward<T>(t)) && is_lvalue(std::forward<U>(u));
}
int main(){
int i= 2,j =10 ;
((i < 3) ? i : j) = 7; //Ok
std::cout << std::boolalpha << isTernaryAssignable(i, j); std::cout << 'n';
std::cout << std::boolalpha << isTernaryAssignable(i, 10); std::cout << 'n';
std::cout << std::boolalpha << isTernaryAssignable(2, j); std::cout << 'n';
std::cout << std::boolalpha << isTernaryAssignable(2, 10); std::cout << 'n';
}
输出:
true
false
false
false
现场演示
注意:您传递给isTernaryAssignable
的操作数应使它们不会发生衰减(例如,衰减到指针的数组)。
相关文章:
- 何时返回指针与返回对象的一般经验法则?
- C++函数何时删除返回值?
- c++:何时传递指针与返回对象
- 返回的常量引用究竟何时被销毁
- 何时返回矢量迭代器而不是矢量?
- X86-64上的C :何时通过结构/类在寄存器中返回
- 三元运算符为什么以及何时返回左值?
- Dynamic_cast何时返回0,什么时候引发异常?CPP
- 何时按值返回OK
- 返回值的复制构造函数何时发生
- 何时是函数参数并返回构建值
- 我何时应该将指针从操作员函数中返回对象(而不是对象)
- 何时通过引用 C++ 中的函数来传递和返回
- 何时从非模板和非成员函数返回 T&&
- long/int到UINT64的转换,并在C#上返回long-何时可以丢失数据
- GetByteArrayElements何时返回null
- 这个函数何时以及为什么会返回其他东西
- 使用递归在List中查找int类型-何时返回
- 何时可以应用自动返回类型
- TCP套接字上的read()何时返回?