помогите с шаблоном
От: Socket Ниоткуда http://www.samborsky.com
Дата: 28.08.07 10:19
Оценка:
Добрый день!
В шаблонах как и в STL делаю первые шаги, потому прошу не судить строго.

Пытаюсь создать класс (чтобы не писать одинаковых два). Разница в том что в одном классе уникальность должна соблюдатся по
полю url класса UrlContainer, во втором по parent.
В литературе по С++ примеры с шаблонами очень скудны, потому прошу помощи — как сделать класс-шаблон такой.
Набросок есть, но он не компилируется.

class UrlContainer {
public:
    string url;
    string parent;
    bool used;
};

class SortCriterionByUrl {
public:
    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
        return u1.url < u2.url;
    }
};

class SortCriterionByParent {
public:
    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
        return u1.parent < u2.parent;
    }
};

template< class T >
class CUrlContainer {
public:
    CUrlContainer();
    ~CUrlContainer();

    enum alloc_method{
        only_alloc,
        alloc_and_cute,
    };

    enum delete_method{
        by_parent,
        by_url
    };

    bool Init();
    bool add(const string& url,const string& parent);
    bool pop(string &url);
    void del(delete_method dm,const string& s);
    bool alloc_all(string& s,alloc_method am);
    bool alloc_all(CMem& mem,alloc_method am);

    void saveLines(LPCVOID lpMem,DWORD dwSize);
    void saveLines(const string& s);

    size_t count();
    void clear();

private:
    CLock lock;

    set<UrlContainer,T> m_set;

protected:
};

// Все функции не привожу, т.к. они однообразны

template < class T >
CUrlContainer<T>::CUrlContainer(){
}

template < class T >
CUrlContainer<T>::~CUrlContainer(){
}

template < class T >
bool CUrlContainer<T>::add(const string& url,const string& parent){

    bool ret = false;

    if( lock.Lock() ){

        UrlContainer url_cont;

        url_cont.url = url;
        url_cont.used = false;
        url_cont.parent = parent;

        pair< set<UrlContainer,T>::iterator,bool > status = m_set.insert(url_cont);

        ret = status.second;

        lock.Unlock();
    }

    return ret;

}


И собственно как я пытаюсь объявлять и использовать класс

    CUrlContainer<SortCriterionByUrl> m_url_container;

    CUrlContainer<SortCriterionByParent> m_url_container2;


очень хочется понять в чем я не прав
http://www.samborsky.com — мой блог
Re: помогите с шаблоном
От: Bell Россия  
Дата: 28.08.07 10:29
Оценка:
Здравствуйте, Socket, Вы писали:

S>очень хочется понять в чем я не прав


Обычно очень хочется видеть полный минимальный пример, и описание проблемы.

Рискну предположить, что проблема в строке
pair< set<UrlContainer,T>::iterator,bool > status = m_set.insert(url_cont);


Если я прав, то проблема в том, что компилятор не может решить, что такое set<UrlContainer,T>::iterator — то ли это тип, то ли статическая переменная-член, то ли еще что-то.
Нужно просто немного помочь компилятору, указав ему, что set<UrlContainer,T>::iterator является типом:

pair< typename set<UrlContainer,T>::iterator,bool > status = m_set.insert(url_cont);
Любите книгу — источник знаний (с) М.Горький
Re[2]: помогите с шаблоном
От: Socket Ниоткуда http://www.samborsky.com
Дата: 28.08.07 11:53
Оценка:
Здравствуйте, Bell, Вы писали:

С ошибками компиляции разобрался более-менее, теперь ошибка линкера возникает
не могу понять что не так



class UrlContainer {
public:
    string url;
    string parent;
    bool used;
};

class SortCriterionByUrl {
public:
    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
        return u1.url < u2.url;
    }
};

class SortCriterionByParent {
public:
    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
        return u1.parent < u2.parent;
    }
};

template< class T >
class CUrlContainer {
public:
    CUrlContainer();
    ~CUrlContainer();

    OPERATORS;

    enum alloc_method{
        only_alloc,
        alloc_and_cute,
    };

    enum delete_method{
        by_parent,
        by_url
    };

    typedef set<UrlContainer,T> MySetType;

    bool Init();
    bool add(const string& url,const string& parent);

private:
    CLock lock;

    MySetType m_set;

protected:
};


cpp — файл
#include "CUrlContainer.h"

template < class T >
CUrlContainer<T>::CUrlContainer(){
}

template < class T >
CUrlContainer<T>::~CUrlContainer(){
}

template < class T >
bool CUrlContainer<T>::Init(){

    bool ret = false;

    if( lock.Init() ){
        ret = true;
    }

    return ret;

}

template < class T >
bool CUrlContainer<T>::add(const string& url,const string& parent){

    bool ret = false;

    if( lock.Lock() ){

        UrlContainer url_cont;

        url_cont.url = url;
        url_cont.used = false;
        url_cont.parent = parent;

        pair< MySetType::iterator,bool > status = m_set.insert(url_cont);

        ret = status.second;

        lock.Unlock();
    }

    return ret;

}


// Вызов кода

int _tmain(int argc, _TCHAR* argv[]){

    CUrlContainer<SortCriterionByUrl> uc;

    if( uc.Init() ){

        uc.add("http://wasm.ru/1/2/","wasm.ru");

    }
    return 0;
}


и ошибки линкера

Linking...
LINK : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
small_test.obj : error LNK2001: unresolved external symbol "public: __thiscall CUrlContainer<class SortCriterionByUrl>::~CUrlContainer<class SortCriterionByUrl>(void)" (??1?$CUrlContainer@VSortCriterionByUrl@@@@$$FQAE@XZ)
small_test.obj : error LNK2001: unresolved external symbol "public: bool __thiscall CUrlContainer<class SortCriterionByUrl>::add(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?add@?$CUrlContainer@VSortCriterionByUrl@@@@$$FQAE_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0@Z)
small_test.obj : error LNK2001: unresolved external symbol "public: bool __thiscall CUrlContainer<class SortCriterionByUrl>::Init(void)" (?Init@?$CUrlContainer@VSortCriterionByUrl@@@@$$FQAE_NXZ)
small_test.obj : error LNK2001: unresolved external symbol "public: __thiscall CUrlContainer<class SortCriterionByUrl>::CUrlContainer<class SortCriterionByUrl>(void)" (??0?$CUrlContainer@VSortCriterionByUrl@@@@$$FQAE@XZ)
Debug/small_test.exe : fatal error LNK1120: 4 unresolved externals
http://www.samborsky.com — мой блог
Re[3]: помогите с шаблоном
От: Bell Россия  
Дата: 28.08.07 12:17
Оценка:
Здравствуйте, Socket, Вы писали:

S>Здравствуйте, Bell, Вы писали:


S>С ошибками компиляции разобрался более-менее, теперь ошибка линкера возникает

S>не могу понять что не так

Если коротко: определение шаблона должно лежать в заголовке. Всё целиком.
За подробностями обратись в поиск — эта тема обсуждается очень часто.

ЗЫ
Не проще сделать компаратор с параметром?

class SortCriterion {
   bool ByUrl_;
public:
    SortCriterion(bool ByUrl) : ByUrl_(ByUrl) {}
    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
        if(ByUrl_)
           return u1.url < u2.url;
        else
           return u1.parent < u2.parent ;
    }
};


Это конечно, если не требуется, чтобы эти 2 класса CUrlContainer имели разный тип...
Любите книгу — источник знаний (с) М.Горький
Re[3]: помогите с шаблоном
От: rg45 СССР  
Дата: 28.08.07 12:34
Оценка:
Здравствуйте, Socket, Вы писали:

S>Здравствуйте, Bell, Вы писали:


S>С ошибками компиляции разобрался более-менее, теперь ошибка линкера возникает

S>не могу понять что не так...

Хочу дополнить ответ Bell'а
Автор: Bell
Дата: 28.08.07
.
Вместо того, чтобы выносить определение шаблона в заголовок, можно в конце cpp-файла добавить две следующие строчки:
template class CUrlContainer<UrlContainer>;
template class CUrlContainer<SortCriterionByUrl>;

Это явные запросы на инстанцирование шаблона CUrlContainer с парпметрами UrlContainer и SortCriterionByUrl. При такой реализации шаблоном CUrlContainer можно будет пользоваться только для типов UrlContainer и SortCriterionByUrl. При попытке использования с любым другом типом будут возникать ошибки линковки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: помогите с шаблоном
От: Кодт Россия  
Дата: 28.08.07 12:47
Оценка:
Здравствуйте, Socket, Вы писали:

S>Здравствуйте, Bell, Вы писали:


S>С ошибками компиляции разобрался более-менее, теперь ошибка линкера возникает

S>не могу понять что не так

Определения шаблонов функций (в т.ч. функций-членов шаблонов классов) должны быть в .h
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: помогите с шаблоном
От: Socket Ниоткуда http://www.samborsky.com
Дата: 28.08.07 22:08
Оценка: +1 :)
B>ЗЫ
B>Не проще сделать компаратор с параметром?
B>
B>class SortCriterion {
B>   bool ByUrl_;
B>public:
B>    SortCriterion(bool ByUrl) : ByUrl_(ByUrl) {}
B>    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
B>        if(ByUrl_)
B>           return u1.url < u2.url;
B>        else
B>           return u1.parent < u2.parent ;
B>    }
B>};
B>


Может быть и проще, но как я написал в первом посте — я только учусь, и хотелось бы
в дальнейшем использовать шаблоны. Ваша идея с параметром мне сразу пришла, но хотелось
бы воспользоватся новым для себя инструментом — шаблонами.

Что касается сабжа — все решилось включением процедур в h файл.
ps — следующий раз буду юзать поиск внимательнее — я смотрю что каждая 3я тема примерно с текстом поиска
"Шаблон" дает примерно мой вопрос

Всем спасибо за помощь
http://www.samborsky.com — мой блог
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.