Как правильно написать этот код с шаблонами?

160
27 декабря 2018, 07:20

При компиляции выводиться ошибка, вот такая

c++ main.cpp vi.cpp -o l
vi.cpp:4:3: error: template<class T> class vi used without template parameters
 T vi::operator[](int idx)
   ^~
vi.cpp:4:25: error: T operator[](int)’ must be a nonstatic member function
 T vi::operator[](int idx)

Вот код.

main.cpp

#include <iostream>
#include "vi.h"
int main () 
{       
        vi<int> v;
        int s = v[0];
        std::cout << s << "\n";
} 

vi.h

#include <vector>
template<typename T>
class vi {
        std::vector<T> vr;
        public:
        T operator[](int idx);
};

vi.cpp

#include "vi.h"
template<typename T>
T vi::operator[](int idx)
{
        return 1;
}   
Answer 1
  1. Шаблон - это не класс, шаблон - это не функция. Шаблон - это просто чертеж(паттерн, план), который будет использоваться компилятором для генерации семейства классов/функций.

  2. Если компилятор генерирует функцию/класс из шаблона, он должен 'видеть' определения генерируемых им функций/методов класса.

  3. Компилятор не собирает проект, т.е. он не видит связей между несколькими .cpp файлами. Это делает ваша IDE.

В вашем случае: в main.cpp будет создан экземпляр vi<int> и объявлен(не определен!) метод vi::operator[]. Он будет просто объявлен, т.к. в шаблоне вы однозначно указали компилятору: 'Только объяви!'(T operator[](int idx);). И это все не будет иметь никакого отношения к вашим определениям в vi.cpp.

Это все наводит на мысль, что лучше определять реализацию методов прямо в шаблоне класса, или в том же файле, где объявляется шаблон.

При крайней необходимости или огромном желании разделить интерфейс и реализацию, вы можете воспользоваться следующим подходом:

// vi.h
#include <vector>
template<typename T>
class vi {
        std::vector<T> vr;
        public:
        T operator[](int idx);
};
#include "vi"
// ^^^^^^^^^^
// vi (файл без расширения)
// реализация из бывшего vi.cpp
template<typename T>
T vi<T>::operator[](int idx)
{
        return 1;
}  

Это позволит компилятору 'видеть' одновременно и объявление шаблона, и определение шаблонных методов Вместо файла без расширения vi вы можете выбрать любое другое имя с любым расширением.

Одно замечание: ваша IDE может жаловаться на подобный код, но это абсолютно легальный подход. Вы можете выполнить компиляцию и линковку из командой строки при необходимости.

Templates definition and declaration. C++ FAQ

Answer 2
template<typename T>
T vi<T>::operator[](int idx)
{
        return 1;
}   
READ ALSO
C/C++, GetLastError() и errno()

C/C++, GetLastError() и errno()

Я бы хотел разобраться в том, каким образом названные функции реализуют сохранение информации о последней возникшей ошибке в текущем вызывающем...

157
Работа с wav файлами в с++

Работа с wav файлами в с++

Необходимо создать wav файл в котором будут сохранены дорожки нескольких wav файлаМожно посоветовать и библиотеку которая занимается этим...

170
Сохранения состояния отсчета в Android

Сохранения состояния отсчета в Android

У меня идет обратный отсчет, который отображается в TextViewПри смене ориентации текст в TextView становится указанным в xml разметке

160
Особенности работы с MySQL: Statement и PreparedStatement

Особенности работы с MySQL: Statement и PreparedStatement

Просьба специалистов помочь в понимании технического вопроса при работе с MySQL

148