2017-02-10 22 views
0

Я создал шаблонный класс vect, который позволяет создавать массивы элементов типа T, получать к ним доступ от 1 до n (вместо 0 до n-1) и переставлять их (мне нужно переставить они вместо этого переставляют их классическим способом).Ошибка компиляции в отношении оператора []

Вот заголовок файла:

#ifndef VECT_HPP 

#define VECT_HPP 

#include <vector> 

template <class T> 
class vect 
{ 
public: 
    vect(int=0); 
    ~vect(); 
    void show(void) const; 
    void permute(int,int); 
    T& operator[](int); 
    const T& operator[](int) const; 
    void init_perm(void); 
private: 
    int n; 
    double* p; 
    std::vector<int> s; 
}; 

#endif /* GUARD_VECT_HPP */ 
#include "vect.cpp" 

и вот исходный файл:

#ifndef VECT_CPP 
#define VECT_CPP 

#include "vect.hpp" 
#include <iostream> 

using namespace std; 

template <class T> 
vect<T>::vect(int a): n(a) 
{ 
    p=new double[n]; 
    s.resize(n); 
    init_perm(); 
} 

template <class T> 
vect<T>::~vect() 
{ 
    delete [] p; 
} 

template <class T> 
void vect<T>::show(void) const 
{ 
    for (int i = 0; i < n; i++) 
     cout << p[i] << endl; 
} 

template <class T> 
void vect<T>::permute(int a,int b) 
{ 
    static int c; 
    a--; 
    b--; 
    c=s[a]; 
    s[a]=s[b]; 
    s[b]=c; 
} 
template <class T> 
T& vect<T>::operator[](int i) 
{ 
    return p[s[i-1]-1]; 
} 

template <class T> 
const T& vect<T>::operator[](int i) const 
{ 
    return p[s[i-1]-1]; 
} 

template <class T> 
void vect<T>::init_perm(void) 
{ 
    for (int i = 0; i < n; i++) 
     s[i]=i+1; 
} 

#endif 

и вот файл main.cpp, что я уезда, чтобы проверить класс:

#include "vect.hpp" 
#include <iostream> 

using namespace std; 

int main(void) 
{ 
    vect<int> v(5); 
    v.show(); 
    for (int i = 1; i <=5; i++) 
     v[i]=10*i; 
    v.show(); 
    cout << "Permuted 3 and 5" << endl; 
    v.permute(3,5); 
    v.show(); 
    v.init_perm(); 
    cout << "Initialized permutations" << endl; 
    v.show(); 
    return 0; 
} 

Я получаю следующее сообщение об ошибке:

In file included from vect.hpp:25:0, 
       from main.cpp:1: 
vect.cpp: In instantiation of ‘T& vect<T>::operator[](int) [with T = int]’: 
main.cpp:11:6: required from here 
vect.cpp:43:19: error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’ 
    return p[s[i-1]-1]; 

Я искал в Интернете об этой ошибке и о том, как это может быть вызвано плохой реализацией operator[], но после коррекции у меня все еще такая же ошибка, даже когда я возвращаю p[i-1] вместо p[s[i-1]].

Не могли бы Вы помочь мне?

+0

Обычно векторные индексы основаны на нулевом значении. Почему вы изменили это, чтобы сделать ваши векторные индексы одними? –

+1

'double * p;' - почему? – Mat

+1

'double * p;' должно быть 'T * p;'. Звучит как опечатка. –

ответ

2

Проблема связана с несоответствием типа p по сравнению с шаблоном T.

У вас есть массив из double, указывающий на p. И шаблон T - это номер int. Обычно это не является большой проблемой, поскольку double может быть неявно преобразован в int. Но это не обычный случай, потому что вы хотите вернуть ссылку на номер int.

Компилятор выполняет преобразование в int для вас, но это преобразованное значение является Rvalue и временным, и ссылки не могут связываться с rvalues.

Решение состоит в том, чтобы не иметь несоответствия типов и иметь p вместо массива T. Или еще лучше, пусть это будет std::vector.

+0

Большое спасибо за ваш ответ! Вы правы, я должен объявить 'p' как' T * 'вместо' double * '. – Scientifica

2

Проблема здесь:

template <class T> 
T& vect<T>::operator[](int i) 
{ 
    return p[s[i-1]-1]; 
} 

в вашем примере, T выводится на int, но p всегда типа double. Поэтому, когда вы возвращаете p[s[i-1]-1], int& пытается привязать к double. В этот момент значение неявно преобразуется в значение int, которое не может быть связано с int&.

+0

Большое спасибо за ваш ответ! Вы правы, я должен объявить 'p' как' T * 'вместо' double * '. – Scientifica