2

I read about Lvalue-to-rvalue conversion and Comparison operators

This quote from Comparison operators :

after the application of the lvalue-to-rvalue, array-to-pointer and function-to-pointer standard conversions. The comparison is deprecated if both operands have array type prior to the application of these conversions. (since C++20)

This quote from Lvalue-to-rvalue conversion :

An lvalue (until C++11)A glvalue (since C++11) of any non-function, non-array type T can be implicitly converted to an rvalue (until C++11)a prvalue (since C++11):

If T is not a class type, the type of the rvalue (until C++11)prvalue (since C++11) is the cv-unqualified version of T. Otherwise, the type of the rvalue (until C++11)prvalue (since C++11) is T. If an lvalue-to-rvalue conversion from an incomplete type is required by a program, that program is ill-formed.

I just want to make sure that I understand how this conversion works right ( My Understand ) :

Example 1 :

#include <iostream>
using namespace std;
int main() {
    int x=9;
    if(x == 0){
     cout<<"Okay"<<endl;    
    }
    return 0;
}

Example 2 :

#include <iostream>
using namespace std;
int main() {
    int x=9;
    if(0 == x){
     cout<<"Okay"<<endl;    
    }
    return 0;
}

I concluded two points :

The point number 1 : in Example 1 Lvalue-to-rvalue conversion is applied to the two operands ( x and 0 ) of the operator == before the The comparison and that is why the Example 2 is also compiled and run .

The point number 2 : Lvalue-to-rvalue conversion is never applied to class type . ( is that the exact meaning of this section ( because the english is not my native language so I want to make sure that I understand this section totally right ) ? : )

If T is not a class type, the type of the rvalue (until C++11)prvalue (since C++11) is the cv-unqualified version of T. Otherwise, the type of the rvalue (until C++11)prvalue (since C++11) is T. If an lvalue-to-rvalue conversion from an incomplete type is required by a program, that program is ill-formed.

So at the end is my conclusion ( the two points ) totally right ?

Edit : enter image description here

here the Inside class definition of operators and the Outside class definition for example for equal to Operator ( == ) the Inside class definition is ( for class T )
bool T::operator==(const T2& b) const;
and the Outside class definition is bool operator==(const T& a, const T2& b); So I have four questions for you @Caleth you in your last comment ( under your answer ) " bool operator==(int &, Foo&) takes lvalues, whereas bool operator(int, Bar) takes rvalues "

question number 1 - what I understand from your comment is Foo is a class and Bar is also a class is that right ?

you said in another comment " for the built-in operators, i.e. both operands are of scalar type, then lvalue-to-rvalue conversion is done because all built-in operators are by-value. For user defined operators, it is or isn't done depending on the declared type of the parameter "

question number 2 - " the built-in operators, i.e. both operands are of scalar type, then lvalue-to-rvalue conversion is done because all built-in operators are by-value. " I don not understand you said " because all built-in operators are by-value. " when we take a look on the table ( the photo ) we can see that the Outside class definition is bool operator==(const T& a, const T2& b);

Is the Outside class definition the definition of built-in operators ?

question number 3 - if the answer of the question number 2 is YES then why is the lvalue-to-rvalue conversion done when we use built-in operators ( if the parameter in the definition of the built-in operators is not by - value ) and if the answer of the question number 2 is NO then What is the difference between Outside class definition and the definition of built-in operators ?

you said " For user defined operators, it is or isn't done depending on the declared type of the parameter " and you explain this by said " bool operator==(int &, Foo&) takes lvalues, whereas bool operator(int, Bar) takes rvalues " If we apply your words

#include <iostream>
using namespace std;
class test {
public:
    test() {
        cout << "test()" << endl;
    }
    test(test&& p) {
        cout << "test( test&& p )" << endl;
    }
    test(const test& p) {
        cout << "test( const test& p )" << endl;
    }
    test& operator==(test p) {
        return p;
    }
};
int main() {
    test p;
    test o;
    p == o;
    return 0;
} 

the output of this code is :

test() ------- for test p
test() ------- for test o
test( const test& p ) -------- for operator ==

so here the parameter of the overloaded operator == is test p ( is by - value ) and the lvalue-to-rvalue conversion does not applied

question number 4 - does not that make the lvalue-to-rvalue conversion does not applied when you use a class type ( any class type ) with an overloaded operator ( any overloaded operator ) ( even if the parameter of the overloaded operator is by - value or not ) ( there is no case that the lvalue-to-rvalue conversion is applied when you use a class type ( any class type ) with an overloaded operator ( any overloaded operator ) ) ?

you said "There are user-defined operators that require lvalue-to-rvalue conversions, e.g. bool operator==(int, Bar), and ones that don't, e.g. bool operator==(int &, Foo&)."

question number 5 - you said " bool operator==(int, Bar) requires lvalue-to-rvalue conversions " here bool operator==(int, Bar) The lvalue-to-rvalue conversion happens with the parameter int and The lvalue-to-rvalue conversion does not happen with the parameter Bar , right ?

sorry for bothering you @Caleth

8
  • um, you don't have a class type in example two. Commented May 31, 2023 at 13:35
  • I know example 1 and example 2 does not contain a class type the two examples are for point number 1
    – f877576
    Commented May 31, 2023 at 13:42
  • I expect every modern compiler to directly return 0. Commented May 31, 2023 at 13:42
  • 1
    "If T is not a class type ... Otherwise, the type of the rvalue (until C++11)prvalue (since C++11) is T" It is unclear how you conclude that "Lvalue-to-rvalue conversion is never applied to class type" Commented May 31, 2023 at 13:44
  • 1
    @akirahinoshiro the quesiton is not about what the example code returns or how it can be optimized Commented May 31, 2023 at 13:46

1 Answer 1

3

in Example 1 Lvalue-to-rvalue conversion is applied to the two operands ( x and 0 )

No. The expression x is an lvalue, so it is converted. The expression 0 is already an rvalue, so it is not.

Lvalue-to-rvalue conversion is never applied to class type .

No. There is a sentence starting "Otherwise" after the non-class type case, there is a different rule for class types.

61
  • 1
    @f877576 yes, class types keep the cv qualification
    – Caleth
    Commented Jun 13, 2023 at 7:33
  • 1
    The table in the question is unfortunately not very enlightening when it comes down to language lawyer questions. The actual comparison operators used for scalar types, as in x == 0 in your example code, are the hypothetical overloads listed far down the page in a paragraph starting with "In overload resolution against user-defined operators". As you can see, these take the arguments by value and require the lvalue-to-rvalue conversion. Therefore, x undergoes the conversion, but 0 need not because it is already an rvalue.
    – j6t
    Commented Jun 23, 2023 at 5:49
  • 1
    @f877576 that table on cppreference describes user defined operators, and uses const T & because it's a good idea to, not because the language requires it.
    – Caleth
    Commented Jun 27, 2023 at 7:34
  • 1
    If the operator accepts paramters by value, whenever you use an lvalue expression, there needs to be lvalue-to-rvalue conversion, which is copy initialising the parameter object from the argument. If you pass an prvalue, it isn't converted, the temporary is materialised into the parameter object
    – Caleth
    Commented Jul 3, 2023 at 8:12
  • 1
    @f877576 the purpose of the conversion is to create a new object. That's the same for scalar types, class types and pointer types
    – Caleth
    Commented Jul 3, 2023 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.