Неявное приведение типов не работает для класса шаблона - PullRequest
2 голосов
/ 06 апреля 2020

У меня есть две структуры, A и B, так что B может быть приведен к A, и я определил operator+ для 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);
}

Без определения operator+ для B, Компилятор знает, как неявно приводить объекты B к A, а затем добавлять их. Это означает, что следующие работы B b1 = {1.0f}; B b2 = {2.0f}; A a = b1 + b2

Однако, когда я преобразовываю свои структуры в шаблонные классы и пытаюсь выполнить ту же самую операцию на D вместо Bs, я получаю ошибку:

ошибка: нет совпадения с оператором + (типы операндов: D и 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);
}

Почему преобразование моих структур в шаблоны приводит к тому, что неявное приведение перестает работать?

1 Ответ

2 голосов
/ 06 апреля 2020

Проблема в том, что ваш оператор является шаблоном, и поэтому должен соответствовать его аргументу, неявное преобразование не может быть применено для удержания.

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

Теперь , вы можете выполнять функции c + c, c + d, d + c.

, у друзей есть специальные правила с ADL, поэтому для d + d мы не смотрим на friend operator+(C,C).

Итак, нам нужна еще одна friend функция в 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);
  }
};

Демо

...