Проблемы с конструкторами для вложенного класса шаблона (копия 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)