Reputation: 1940
Consider following code snippet:
template <typename U>
struct Un {
Un (int p) : n {p} {}
U operator+ (U v) const {
return U {n + v.n};
}
int n {};
};
struct R : Un<R> {
using Un::Un;
};
struct D : Un<D> {
using Un::Un;
D (R v) : Un {v.n} {}
operator R () const {
return n;
}
};
and usage is as follows:
template <typename T>
void what_type (T t) {
std::cout << "type R = " << std::is_same<T, R>::value << std::endl;
std::cout << "type D = " << std::is_same<T, D>::value << std::endl;
}
R r {10};
D d {10};
what_type (r+d);
what_type (d+r);
output is:
type R = 1
type D = 0
type R = 0
type D = 1
which means that if in the arithmetic expression R
type occurs as the first one, the whole expression is of type R
and if D
type occurs firstly then the expression is of type D
.
So, my understanding is like this:
in r+d
firstly we create object of R
type, then object of D
type and because D
has operator R()
implemented, D
object is converted to R
, which gives us in fact r+r
.
in d+r
firstly we create object of D
type, then object of R
type and because D
has constructor which takes R
object it creates D
object from previously created r
, which gives us in fact d+d
.
Is my understanding correct? Or are there other rules for that kind of situation?
Upvotes: 4
Views: 134
Reputation: 16431
Your understanding is flawed. You defined binary operator+
as a member function. That means that the left hand of the assignment is set in stone. For D
and R
it's D
and R
, respectively.
d+r
is essentially the same thing as d.operator+(r)
, which for Un<D>
returns D
. It's the same thing in reverse for r+d
.
In neither expression you "create" the left operand. The right one is indeed converted in both.
Upvotes: 6
Reputation: 32504
Return type depending on the order in arithmetic operation. Is it correct?
This can be true only if overloaded operators are involved. For builtin operators the order of arguments doesn't affect the type of the expression.
In case of overloaded operators, the type of the expression depends on the outcome of overloading resolution.
Consider a simpler example where the operator is overloaded globally:
struct A { operator int() const; };
struct B { operator int() const; };
A operator+(A, int);
B operator+(B, int);
A a;
B b;
a + b // resolved as a + (int)b; the type of the expression is A
b + a // resolved as b + (int)a; the type of the expression is B
Note that if B operator+(B, int);
was not defined, b + a
would still be resolved, but now as (int)a + (int)b
, and therefore its type would be int
.
Upvotes: 1