簡體   English   中英

為什么以及何時三元運算符返回左值?

[英]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 ;
}

ij都是glvalues (有關詳細信息,請參閱此值類別參考 )。

然后,如果您閱讀此條件運算符引用,我們就會到達這一點:

4)如果E2和E3是相同類型和相同值類別的glvalues,則結果具有相同的類型和值類別

那么(i < 3) ? i : j的結果(i < 3) ? i : j (i < 3) ? i : j是一個glvalue,可以分配給它。

但是做這樣的事情真的不是我推薦的。

有關這方面的規則詳見[expr.cond] 對於幾種類型和值類別的組合,有許多分支。 但最終,表達式是默認情況下的prvalue。 第5段涵蓋了您的示例中的案例:

如果第二個和第三個操作數是相同值類別的glvalues並且具有相同的類型,則結果是該類型和值類別,如果第二個或第三個操作數是位字段,則它是位字段,或者如果兩者都是位字段。

作為變量名的ij都是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的操作數應使它們不會發生衰減(例如衰減到指針的數組)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM