c++: использование template-функций в классах

Модератор: Модераторы разделов

IMB
Сообщения: 2565
ОС: Debian

c++: использование template-функций в классах

Сообщение IMB »

Доброго дня!
Есть несколько классов в которых одна из функций формирует вектор указателей. По завершению обработки этого вектора память надо вернуть обратно, для этого каждый класс имеет функцию free принимающаю ссылку на вектор. Так как функции free отличаются только типом указателей, то я решил определить эту функции через template.

Код: Выделить всё

template <class T>
void free(std::vector <T *> &data)
{
    if (data.size()) {
        std::vector <T *>::iterator tmp;

        for (tmp = data.begin(); tmp != data.end(); tmp++)
            delete *tmp;
        data.clear();
    }
}

Проблема возникает на этапе компиляции:

Код: Выделить всё

inc/librtnl_tmp.hpp: In function ‘void free(std::vector<T*, std::allocator<T*> >&)’:
inc/librtnl_tmp.hpp:5: error: expected ‘;’ before ‘tmp’
inc/librtnl_tmp.hpp:7: error: ‘tmp’ was not declared in this scope
make: *** [library] Error 1

Вопрос:
- почему возникает ошибка
- смогу ли я потом использовать эту функцию в своих классах как public-функцию и если смогу, то какие условия для этого необходимо соблюсти
Спасибо.
Спасибо сказали:
aumit
Сообщения: 28

Re: c++: использование template-функций в классах

Сообщение aumit »

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

Код: Выделить всё

typename std::vector <T *>::iterator tmp;

Чтобы не писать free, используй умные указатели такие как shared_ptr. Он есть как в boost так и в последнем стандарте
Спасибо сказали:
IMB
Сообщения: 2565
ОС: Debian

Re: c++: использование template-функций в классах

Сообщение IMB »

Я только начинаю работать с C++, поэтому не всё понял.
Итак, благодаря typename ошибка компиляции решена, теперь возникла ошибка на этапе линковки.
Что я сделал:
- подключил h-файл с template-функцией к файлу с определением своего класса в котором прописана функция free с параметрами для этого класса
- в c-файле класса закомментировал реализацию функции free
При компиляции получаю следующее:

Код: Выделить всё

/tmp/ccHm4VHF.o: In function `main':
main.cpp:(.text+0x1d1e): undefined reference to `RTNL_addr::free(std::vector<rtnl_addr_info_s*, std::allocator<rtnl_addr_info_s*> >&)'
main.cpp:(.text+0x22b1): undefined reference to `RTNL_addr::free(std::vector<rtnl_addr_info_s*, std::allocator<rtnl_addr_info_s*> >&)'
collect2: ld returned 1 exit status
Спасибо сказали:
aumit
Сообщения: 28

Re: c++: использование template-функций в классах

Сообщение aumit »

Он хочет метод free класса RTNL_addr.
Смотри оъявление класса RTNL_add, и что написано в main.cpp
Очисти весь проект и собери все заново, может make не обновил объектные файлы по зависимости.
Спасибо сказали:
IMB
Сообщения: 2565
ОС: Debian

Re: c++: использование template-функций в классах

Сообщение IMB »

Определение класса:

Код: Выделить всё

class RTNL_addr {
    public:
        RTNL_addr() {};
        ~RTNL_addr() {};
        int info(const unsigned int index, const unsigned char family,
                    std::vector <rtnl_addr_info_s *> &data);
        void free(std::vector <rtnl_addr_info_s *> &data); //предполагается, что здесь исползуется template-функция
};

Ну и main.cpp всё банально:

Код: Выделить всё

RTNL_addr    addr;
std::vector<rtnl_addr_info_s *>    adata;
...................
addr.free(adata);

Спасибо сказали:
aumit
Сообщения: 28

Re: c++: использование template-функций в классах

Сообщение aumit »

Значит нет реализации метода free, класса RTNL_addr.
Спасибо сказали:
IMB
Сообщения: 2565
ОС: Debian

Re: c++: использование template-функций в классах

Сообщение IMB »

Непонял, есть template-функция с реалицией, файл с ней подключен в файле определения класса. Этой реализации недостаточно?
Спасибо сказали:
aumit
Сообщения: 28

Re: c++: использование template-функций в классах

Сообщение aumit »

IMB писал(а):
05.01.2012 18:23
Непонял, есть template-функция с реалицией, файл с ней подключен в файле определения класса. Этой реализации недостаточно?

- в c-файле класса закомментировал реализацию функции free


В main.cpp вы вызываете метод класса, а не шаблонную функцию.
Т.е. нужно делать

Код: Выделить всё

RTNL_addr    addr;
std::vector<rtnl_addr_info_s *>    adata;
...................
free(adata);
Спасибо сказали:
IMB
Сообщения: 2565
ОС: Debian

Re: c++: использование template-функций в классах

Сообщение IMB »

Хм, это немного не то, что предполагалось. А возможно это как то решить через метод класса?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: c++: использование template-функций в классах

Сообщение NickLion »

Я уже ничего не понимаю :) Ну, шаблонный метод, это вполне возможно:

Код: Выделить всё

#include <stdio.h>
#include <vector>

/* really have to be header-file part */
class RTNL_addr
{
public:
    template< class T >
    void free( std::vector< T* > &data );
};

/* also header-file */
template< class T >
void RTNL_addr::free( std::vector< T* > &data )
{
    if( data.size() ) {
        typename std::vector< T* >::iterator tmp;
        for( tmp = data.begin(); tmp != data.end(); ++tmp ) {
            delete *tmp;
        }
        data.clear();
    }
}

class rtnl_addr_info_s
{
public:
    int big[1024];
};

/* cpp file */

int main()
{
    RTNL_addr addr;
    std::vector< rtnl_addr_info_s* > data;
    data.push_back( new rtnl_addr_info_s() );
    data.push_back( new rtnl_addr_info_s() );
    data.push_back( new rtnl_addr_info_s() );
    data.push_back( new rtnl_addr_info_s() );
    addr.free( data );
}
Спасибо сказали:
IMB
Сообщения: 2565
ОС: Debian

Re: c++: использование template-функций в классах

Сообщение IMB »

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

UPD: Да, подход через создание класса с шаблонной функцией сработал.

Код: Выделить всё

class RTNL_Base
{
    public:
        template <class T>
        void free(std::vector <T *> &data)
        {
            if (data.size()) {
                typename std::vector <T *>::iterator tmp;

                for (tmp = data.begin(); tmp != data.end(); tmp++)
                    delete *tmp;
                data.clear();
            }
        }
};
Спасибо сказали: