Почему не компилируется...
От: Аноним  
Дата: 13.09.09 10:41
Оценка:
#pragma once

template <class T>
class Stack
{
public:
    Stack(void);
    Stack(const Stack&);
    ~Stack(void);
    Stack& operator=(const Stack&);
    int size() const;
    bool empty() const;
    T& top();
    void push(const T&);
    void pop();

protected:
    T* _;
    int _size;
    int _cap;
    static const int _CAP = 4;
    void rebuild();
};


#include "Stack.h"

template <class T>
Stack<T>::Stack() : _(new T[_CAP]), _size(0), _cap(_CAP)
{    
}

template <class T>
Stack<T>::Stack(const Stack& s) : _(new T[s._size]), _size(s._size), _cap(s._cap)
{
    for (int i = 0; i < _cap; i++) {
        _[i] = s._[i];
    }
}
    
template <class T>
Stack<T>::~Stack(void)
{
    delete [] _;
}

template <class T>
Stack<T>& Stack<T>::operator=(const Stack& s)
{
    _ = new T[s._size];
    _size = s._size;
    _cap = s._cap;
    for(int i = 0; i < _cap; i++)
    {
        _[i] = s._[i];
    }
}

template <class T>
int Stack<T>::size() const
{
    return _size;
}

template <class T>
bool Stack<T>::empty() const
{
    return _size == 0;
}
    
template <class T>
T& Stack<T>::top()
{
    return _[_size - 1];
}

template <class T>
void Stack<T>::pop()
{
    --_size;
}

template <class T> 
void Stack<T>::push(const T& x)
{
    if(_size == _cap) rebuild();

    _[_size++] = x;
}

template <class T>
void Stack<T>::rebuild()
{
    _cap *= 2;
    T* temp = new T[_cap];
    for(int i = 0; i <_size; i++)
    {
        temp[i] = _[i];
    }
    delete [] _;

    _ = temp;
}




#include <iostream>
#include "Stack.h"

void main () {
    Stack<char> s;
}


Ошибка:
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Stack<char>::~Stack<char>(void)" (??1?$Stack@D@@QAE@XZ) referenced in function _main
Re: Почему не компилируется...
От: Murom Россия  
Дата: 13.09.09 14:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ошибка:

А>1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Stack<char>::~Stack<char>(void)" (??1?$Stack@D@@QAE@XZ) referenced in function _main

На момент инстанциации компилятор видит только содержание заголовочного файла. Он дожен видеть все тела методов, чтобы их заинстанциировать.
Вариантов несколько:
1. Все запихать в .h файл (и прототипы и реализации)
2. В конце .h файла написать #include "Stack.cpp"
3. Переименовать Stack.cpp в Stack.tpl, и уже его заинклудить по аналогии с пунктом 2.

На счет того как правильно — правильно по разному, решать тебе и Coding Guide'ам твоей конторы.
- Eugeny
Re: Почему не компилируется...
От: __mayor  
Дата: 13.09.09 14:44
Оценка:
Здравствуйте, Аноним, Вы писали:


потому-что msvc, g++ не поддерживают keyword export, позволяющий хранить реализацию шаблона в отдельном юните трансляции

так, что лучше поступить как в стл — запихнуть всю реализацию в хидер, хотя в принципе можно отделить реализацию от объявления с целью удобочитаемости
Re[2]: Почему не компилируется...
От: MichaelLa  
Дата: 14.09.09 07:02
Оценка:
Здравствуйте, Murom, Вы писали:

M>Здравствуйте, Аноним, Вы писали:


А>>Ошибка:

А>>1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Stack<char>::~Stack<char>(void)" (??1?$Stack@D@@QAE@XZ) referenced in function _main

M>На момент инстанциации компилятор видит только содержание заголовочного файла. Он дожен видеть все тела методов, чтобы их заинстанциировать.

M>Вариантов несколько:
M>1. Все запихать в .h файл (и прототипы и реализации)
M>2. В конце .h файла написать #include "Stack.cpp"
M>3. Переименовать Stack.cpp в Stack.tpl, и уже его заинклудить по аналогии с пунктом 2.

M>На счет того как правильно — правильно по разному, решать тебе и Coding Guide'ам твоей конторы.


это странно для меня. т.к. я создал visual studio проект. положил в папку headers сам хедер и в папку source реализацию.
а также создал доп. файл main.cpp из которого это всё вызываю.

раньше это работало для других классов, но этот пример почему-то ругается.
Re[3]: Почему не компилируется...
От: Lorenzo_LAMAS  
Дата: 14.09.09 07:33
Оценка:
ML>раньше это работало для других классов, но этот пример почему-то ругается.

А это проблема с шаблонами С++. Тебе придется либо держать определения в заголовке (ну или явно включать их, как тебе уже посоветовали). Либо можно использовать явное инстанцирование, что очень неудобно, ну или найти компилятор, поддерживающий раздельную компиляцию шаблонов и ключевое слово export
Of course, the code must be complete enough to compile and link.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.