Reputation: 23
I have two structs, A & B, such that B can be cast into A and I have defined the operator+
for A.
struct A
{
float x;
A(float _x) : x(_x) {}
};
struct B
{
float x;
operator A()
{
return A{x};
}
};
A operator+ (A left, A right)
{
return A(left.x+right.x);
}
Without defining the operator+
for B, the compiler knows to implicitly cast B objects to A and then add them. Which means the following works
B b1 = {1.0f}; B b2 = {2.0f}; A a = b1 + b2
However, when I convert my structs to template classes and try to perform the same operation on Ds instead of Bs, I get an error:
error: no match for 'operator+' (operand types are 'D' and 'D')
template<typename T>
struct C
{
T x;
C<T>(T _x) : x(_x) {}
};
template<typename T>
struct D
{
T x;
operator C<T>()
{
return C<T>(x);
}
};
template<typename T>
C<T> operator+ (C<T> left, C<T> right)
{
return C<T>(left.x+right.x);
}
Why does converting my structs into templates cause the implicit casting to stop working?
Upvotes: 2
Views: 53
Reputation: 217583
Issue is that your operator is template, and so should match its argument, implicit conversion cannot be applied for deduction.
friend
is your friend :)
template<typename T>
struct C
{
T x;
C(T _x) : x(_x) {}
friend C operator+ (C left, C right) // Function is no longer template
{
return C(left.x + right.x);
}
};
Now, you can do c + c
, c + d
, d + c
.
friend functions have special rules with ADL, so for d + d
, we don't look at friend operator+(C,C)
.
So we need another friend
function in D
:
template <typename T>
struct D
{
T x;
operator C<T>() { return C<T>(x); }
friend C<T> operator+ (D left, D right)
{
return C<T>(left) + C<T>(right);
}
};
Upvotes: 2