st33l
st33l

Reputation: 23

Implicit typecasting not working for template class

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

Answers (1)

Jarod42
Jarod42

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);
  }
};

Demo

Upvotes: 2

Related Questions