Проблемы с конструкторами для вложенного класса шаблона (копия ctor, кажется, перекрывает другие ctor)

У меня есть домашнее задание, чтобы сделать шаблонный класс Matrix, который включает в себя довольно простые и простые вещи. Нам также нужно создать класс прямого итератора для него (вложенный), который ведет себя стандартным образом, он должен специально поддерживать конструктор копирования.

Вот соответствующий код matrix.h:

template<class T>
class Matrix
{
public:
    //nested iterator class
    class iterator
    {

    public:
        typedef iterator self_type;
        typedef T value_type;
        typedef T& reference;
        typedef T* pointer;
        typedef std::vector<T>& vector;

        iterator(Matrix &other, int index) :
            _currIndex(index), _currMatrix(other)
        {

        }

        iterator(iterator& other) :
            _currIndex(other._currIndex), _currMatrix(other._currMatrix)
        {

        }
    private:
        int _currIndex;
        Matrix<T>& _currMatrix;
    }

    //function that creates an iterator for the current matrix
    iterator begin()
    {
        return iterator(*this, 0);
    }

    iterator end()
    {
        return iterator(*this, _data.size());
    }

private:
    unsigned int _rows;
    unsigned int _cols;
    vector<T> _data;
}

Matrix имеет несколько конструкторов, таких как copy, empty и т. Д. Они инициализируют закрытые члены и ничего больше. Класс итератора также перегружает оператор ++

Проблема, с которой я сталкиваюсь, заключается в компиляции следующего кода в Linux с использованием g++:

for(auto it = m.begin(); it != m.end(); it++)
{
    cout << *it;
}

В Windows в Visual Studio код компилируется и запускается нормально, без проблем. В Linux при компиляции появляется следующая ошибка:

debug.cpp: In function ‘int main()’:
debug.cpp:63:24: error: no matching function for call to ‘Matrix<int>::iterator::iterator(Matrix<int>::iterator)’
  for (auto it = m.begin(); it != m.end(); it++)
                        ^
debug.cpp:63:24: note: candidates are:
In file included from debug.cpp:11:0:
matrix.h:35:3: note: Matrix<T>::iterator::iterator(Matrix<T>::iterator&) [with T = int]
   iterator(iterator& other) :
   ^
matrix.h:35:3: note:   no known conversion for argument 1 from ‘Matrix<int>::iterator’ to ‘Matrix<int>::iterator&’
matrix.h:29:3: note: Matrix<T>::iterator::iterator(Matrix<T>, int) [with T = int]
   iterator(Matrix other, int index) :
   ^
matrix.h:29:3: note:   candidate expects 2 arguments, 1 provided

Если я закомментирую конструктор копирования для класса итератора, то код прекрасно компилируется в Linux (и Windows). Если я оставлю оба конструктора, то g ++ выдаст ошибку. Как будто конструктор копирования переопределяет предыдущий конструктор, и я понятия не имею, почему.

Кто-нибудь может поделиться некоторым пониманием того, почему это происходит? может быть, как я могу это исправить?

2 ответа

Решение

const в конструкторе копирования важно, потому что только l-значения могут быть связаны с неконстантными ссылками, но временные объекты являются r-значениями, и они не могут быть связаны с неконстантными ссылками. Вам нужно изменить подпись на;

iterator(const iterator& other) 

Visual C++ допускает это, но по умолчанию выдает предупреждение "используется нестандартное расширение".

Я предлагаю прочитать пост Херба Саттера для более подробного объяснения.

Вы можете пройти временный как const& (или по значению) только. Visual Studio не прав в этом вопросе. Подходящая подпись вашего конструктора копирования:

iterator(const iterator& other) 
Другие вопросы по тегам