2015-01-24 1 views
0

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

Вот соответствующий код 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; 
} 

Матрица имеет несколько конструкторов, как копии, пустой и т.д. Они инициализируют частных пользователей, и ничего другого. Класс итератора также перегружает оператор ++

Проблемы Я облицовка с компиляцией следующего кода в Linux с помощью г ++:

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

На окнах, в 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 ++ выдает ошибку. Как будто конструктор копирования переопределяет предыдущий конструктор, и я понятия не имею, почему.

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

+6

Отсутствует 'const' в ссылочном параметре? – Columbo

ответ

4

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

iterator(const iterator& other) 

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

Предлагаю прочитать Herb Sutter's post для более подробного объяснения.

+0

thx, вот и все. Это была проблема нехватки знаний с моей стороны, поэтому спасибо, что выяснили, что было не так! – user475680

1

Вы можете сделать это временно, так как const& (или по стоимости). Visual Studio ошибается в этом вопросе. Правильная подпись конструктора копирования будет:

iterator(const iterator& other) 
+1

Времена могут также передаваться по rvalue-reference. Хотя это не полезно, если копирование не дороже, чем перемещение. – Deduplicator

+0

@ Дедупликатор: как-то я пропустил этот тривиальный случай, исправил – erenon

Смежные вопросы