c++operator-overloadingimplicit-conversionconversion-operator

Supported Operations for Implicitly Defined User Conversion Operators


I'm currently learning how implicitly defined conversion operators (also known as user-defined conversions) work for a given class. In my particular case, I wanted to test out my class to be implicitly converted to the default integer type. Found below is my code snippet.

#include <iostream>

using std::cout;
using std::cin;
using std::endl;

class A {
    public:
        A(int);
        operator int() const;
    protected:
        int value;
};

A::A(int input) : value(input) {
}

A::operator int() const {
    return this->value;
}

int main() {
    A foo = 1; 
    foo = foo + 1;          // no error
    foo = foo * 1;          // no error
    foo = foo / 1;          // no error
    cout << foo << endl;    // no error
    !foo;                   // no error
    &foo;                   // no error
    foo%1;                  // no error
    foo != 1;               // no error
    foo == 1;               // no error
    foo >= 1;               // no error
    foo <= 1;               // no error
    foo < 1;                // no error
    foo > 1;                // no error
    foo && 1;               // no error
    foo || 1;               // no error
    A *boo = &foo;          // no error
    *boo = 5;               // no error
    cin >> foo;             // error
    foo *= 2;               // error
    foo++;                  // error
    return 0;
}

As you can see, these operators provide no errors, but the >>, *=, and ++ yield errors; i.e. the object of class A is not implicitly converted for these operators. I noticed that it isn't converted for similar assignment operators. Can someone explain why this is the case, and what the supported operators are for implicit user conversions?


Solution

  • These operators:

    cin >> foo;  // >> endl is a bug     
    foo *= 2;               
    foo++;  
    

    can only be called on an l-value. Your conversion operator returns a temporary int, which is not an l-value. Also, your operator is const qualified, which means it can only be called on const A instances.

    You need to provide a conversion operator that returns an l-value like this:

    class A {
        public:
            operator int&();
        // ...
    };
    
    A::operator int&() {
        return this->value;
    }
    

    Note that this operator can't be const if you want it to return a modifiable l-value.

    Here's a demo.