简体   繁体   中英

how does operator overload resolution work based on return type in the following code of c++

I know that there is no legal overload based on return type in C++; ie you cannot do something like:

int operator ++ getOwner();
char operator ++ getOwner();

However, I stumbled upon the following:

https://stackoverflow.com/a/9569120/1376317

class Proxy
{
    My const* myOwner;
public:
    Proxy( My const* owner ) : myOwner( owner ) {}
    operator int() const
    {
        return myOwner->getInt();
    }
    operator char() const
    {
        return myOwner->getChar();
    }
};

My question is how does operator overload work in this configuration. How do you call this in your main.cpp to get this kind of overloading. How does the compiler deduce , how to call the right overload?

My question is how does operator overload work in this configuration.

These operators provide implicit conversions . That means that this class can be used in many contexts where an int or char is expected, and will use these operators to provide the expected value.

How do you call this in your main.cpp to get this kind of overloading.

Here are a few examples of implicit conversions:

Proxy p = whatever();
int i = p;   // convert to int
char c = p;  // convert to char
long l = p;  // ERROR: ambiguous

void f(int);
f(p);        // convert to int

void g(int);
void g(char);
g(p);        // ERROR: ambiguous

You can also request explicit conversions using the usual cast notations:

long l = static_cast<int>(p);  // convert to int, then to long
g((char)p);                    // convert to char

How does the compiler deduce , how to call the right overload?

Whenever there's a type mismatch, the compiler looks for a conversion sequence. The rules are quite complicated, but basically the sequence can include at most one user-defined conversion (using either an operator like this, or a converting construction), as well as standard conversions such as int to long .

This is sometimes called the Return Type Resolver idiom or "overload on return type". The conversion operator to call is selected thanks to the context of use where an implicit conversion is needed (for example based on the type of an object to initialize or assign to). For example:

#include <stdio.h>

class RtR {
public:
    operator int() const
    {
        puts("operator int()");
        return 42;
    }
    operator double() const
    {
        puts("operator double()");
        return 3.14;
    }
};

void f(int) {}

int main()
{
    RtR x;
    int i = x; // or int i = RtR();
    double d = x;
    f(x);
}

output:

operator int()
operator double()
operator int()

See it live .

In 13.1 Overloadable declarations:

Function declarations that differ only in the return type cannot be overloaded. [ Note: ... It does not apply to sets of functions fabricated as a result of name lookup (eg, because of using-directives) or overload resolution (eg, for operator functions) ... ]

Hence this is valid:

struct X {
    // Conversion function:
    operator int () { return 1; }
    operator double () { return 2; }
};

In addition (not relating directly to the question):

struct Y
{
    // Operator (Function call):
    int operator () (int) { return 1; }
    double operator () (double) { return 2; }

    // Operator (Subscripting):
    int operator [] (int) { return 1; }
    double operator [] (double) { return 2; }

    // Operator (Shift):
    int operator << (int) { return 1; }
    double operator << (double) { return 2; }

    // and more ...
};

上面的代码用于operator类型转换,并提供了一种隐式方式将Proxy类型转换为intchar

The compiler "knows" based on the context of the conversion calls, for instance:

Proxy p;

// p_int will be set equal to p.my_owner->getInt()
int p_int = p;

// p_char will be set equal to p.my_owner->getChar()
char p_char = p;

The fact that it's a proxy is irrelevant; the same thing works for any class. Those are conversion operators, and the compiler does select the right version based on how it's used in the calling code.

struct S {
    operator int() const { return 1; }
    operator double() const { return 2.0; }
};

int main() {
    S s;
    int i = s;
    double d = s;
    std::cout << i << ' ' << d << '\n';
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM