C2679 бинарный '- =': не найден оператор, который принимает правый операнд типа 'T' (или нет приемлемого преобразования) - PullRequest
0 голосов
/ 29 апреля 2020

Я создал класс Vector, который содержит 3 параметра, и перегрузил оператор - =

template <class T>
class Static3Vector
    {
    public:
        Static3Vector() : m_coords{ 0, 0, 0 } {}
        Static3Vector(T x, T y, T z) : m_coords{ x, y, z } {}

        T operator [] (const size_t& i) { return m_coords[i]; }
        T operator [] (const size_t& i) const { return m_coords[i]; }

        Static3Vector operator -= (const Static3Vector& rhs)    
        {
          for (int i = 0; i < sizeof(m_coords) / sizeof(m_coords[0]); i++) 
             this[i] -= rhs[i];
          return *this; 
        }
    private:
        T m_coords[3];
    };

, но когда я пытаюсь использовать этот оператор

Static3Vector<int> vec1(1,2,3);
Static3Vector<int> vec2(1,2,3);
vec1 -= vec2;

, я получаю сообщение об ошибке, набранное мной в заголовке.

Ответы [ 3 ]

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

this - указатель, а this[i] не выполняет то, что вы ожидаете. Он принимает this и выполняет арифметику указателей c. Тогда единственным значением i, которое не является UB, является 0, а тип этого выражения: Static3Vector<T>

Это в значительной степени эквивалентно этому:

Static3Vector<int> vec1(1,2,3);
Static3Vector<int>* ptr = &vec1;
ptr[0]; //ok, equivalent to *ptr
ptr[1]; //compiles, but invokes UB

Вы можете решите это несколькими способами:

(*this)[i] -= rhs[i]; //dereference first
this->operator[](i) -= rhs[i]; //call operator explicitly
m_coords[i] -= rhs[i]; //don't use overloaded operator, use data directly

Еще одна вещь: первые два не будут работать с вашей текущей реализацией, потому что ваша operator[] возвращает копию значения, которое она хранит. Для operator[] более типично возвращать ссылку на сохраненный объект:

    T& operator [] (const size_t& i) { return m_coords[i]; }
    const T& operator [] (const size_t& i) const { return m_coords[i]; }

См. Также Каковы основные c правила и идиомы для перегрузки операторов?

0 голосов
/ 29 апреля 2020

неправильное использование оператора индекса. В определениях операторов, как, например, в этом

    Static3Vector operator -= (const Static3Vector& rhs)    
    {
      for (size_t i = 0; i < sizeof(m_coords) / sizeof(m_coords[0]); i++) 
         this[i] -= rhs[i];
      return *this; 
    }

, в этом операторе

         this[i] -= rhs[i];

используется встроенный оператор индекса b для объекта типа указателя Static3Vector * .

Вам нужно написать

         ( * this )[i] -= rhs[i];

или

         this->operator[]( i ) -= rhs[i];

Также тип возвращаемого значения должен быть ссылочным типом, таким как

    T &  operator [] (const size_t& i) { return m_coords[i]; }
    const T & operator [] (const size_t& i) const { return m_coords[i]; }

и

    Static3Vector & operator -= (const Static3Vector& rhs)    
    {
      for (size_t i = 0; i < sizeof(m_coords) / sizeof(m_coords[0]); i++) 
         ( *this )[i] -= rhs[i];
      return *this; 
    }
0 голосов
/ 29 апреля 2020

Взгляните на свои операторы индексации:

T operator [] (const size_t& i) { return m_coords[i]; }
T operator [] (const size_t& i) const { return m_coords[i]; }

Единственное различие между ними состоит в том, что один вызывается для константных объектов, и возникает вопрос, почему вы их вообще дублировали.

Это легко ответить, хотя:
Оба должны возвращать ссылки, последний const -качественный, чтобы избежать копий и разрешить изменение для первого.

Исправьте это как первый шаг к устранению вашей ошибки .


В качестве второго шага следует признать, что this был введен до того, как ссылки существовали, и, таким образом, является указателем на экземпляр, а не ссылкой таким образом, this[n] является указателем-арифметикой c, не вызывая ваш пользовательский оператор индексации. К счастью, это приводит к другому типу и, следовательно, к ошибке разрешения перегрузки.

...