template class member function msvc++
hi
i had a little problem with msvc++ last night
in the header file
template<class T>
someclass
{
public:
void somefunction();
}
and inthe source file .cpp
template<class T> someclass<T>::somefunction()
{
}
the code looks correct to me and the object file compiles fine but when i use the class in another module it brings a linking error
unresolved external symbol
it doesn t find the member function
with gcc it seems to work is it a bug in their compiler or am i doing something wrong here?
when i move the implementation completely into the header file everything works fine
The file using this class only gets the header, not the source file. Why would you even expect it to know that the function is a template?
All code for a templated class must be in a header file, including non-inlined functions. This may seem strange, but it's quite logical if you think about it. A templated function isn't defining a function itself, it's defining a template for a function, from which an actual function can be generated. There will be a seperate version of the templated function in question created for each different set of template parameters that you supply in different areas of the program. Each time it encounters a new set of parameters, it needs to create a new implemented version of the template in that module. The only way this can be done is if the compiler has the template for that function when it is compiling that module.
I use msvc and template, and put the implementation in a .cpp file. What I did was at the end of the cpp file, define something like this:
template class CSomeTemplate<short>;
template class CSomeTemplate<int>;
... etc, for all types of templates you want (eg. short and int).
template class CSomeTemplate<short>;
template class CSomeTemplate<int>;
... etc, for all types of templates you want (eg. short and int).
Quote:Original post by xinvar
I use msvc and template, and put the implementation in a .cpp file. What I did was at the end of the cpp file, define something like this:
template class CSomeTemplate<short>;
template class CSomeTemplate<int>;
... etc, for all types of templates you want (eg. short and int).
Although it works, it's more upkeep. It's better just stick it in the .h file and forget about it. Usually, once I write a templated class, I forget about it's implementation and just use it over and over again. Now, I'll usually have a large number of template classes in my application. It'd be a real pain to have to go back through all of those source files every time I add a new class that needs templates.
which STL are you using?
Dinkumware?
SGI
or
SGIPort?
currently i am working with msvc++6.0 and the stl shipped with the compiler
but i encountered another problem
Iget the following error message meaning that he can convert _Node* to char*(I used the allocator with std:list<char,alloc>
typedef cross:pool_allocator<char> alloc; without the typedef it doesn t seem to compile it
i think i ll install the gcc for windows tomorrow, the ms compiler drives me crazy
Dinkumware?
SGI
or
SGIPort?
currently i am working with msvc++6.0 and the stl shipped with the compiler
but i encountered another problem
namespace cross{ template<typename T> class pool_allocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; template<class U> struct rebind { typedef pool_allocator<U> other; }; //return a object of n bytes char *_Charalloc(size_type n) { }; //constructor pool_allocator() { assert((m_pPool = new pool_list<T,1024>()) != NULL); }; //copy constructor /*pool_allocator(const pool_allocator& alloc) { assert((m_pPool = alloc.m_pPool) != NULL); };*/ template<class U>pool_allocator(const pool_allocator<U> & arg) { }; //deconstructor ~pool_allocator() { delete m_pPool; }; //returns a pointer to x pointer address(reference x) const { return &x; }; //returns a const_pointer to x const_pointer address(const_reference x) { return &x; }; //allocates a array of n elements pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) { if(n==1) return m_pPool->allocate(); return NULL; }; //deallocate a array of n elements void deallocate(pointer p, size_type n) { if(n==1) m_pPool->deallocate(p); }; size_type max_size() {return 0;}; //placement new: call the constructor of the object p void construct(pointer p, const T& val) { new(p) T(val); } //call the destructor of the object p void destroy(pointer p) { p->T::~T(); } private: pool_list<T,1024> *m_pPool; };}
Iget the following error message meaning that he can convert _Node* to char*(I used the allocator with std:list<char,alloc>
typedef cross:pool_allocator<char> alloc; without the typedef it doesn t seem to compile it
i think i ll install the gcc for windows tomorrow, the ms compiler drives me crazy
Quote:
c:\programme\microsoft visual studio\vc98\include\list(392) : error C2664: 'deallocate' : Konvertierung des Parameters 1 von 'struct std::list<char,class cross::pool_allocator<char> >::_Node *' in 'char *' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
c:\programme\microsoft visual studio\vc98\include\list(392) : Bei der Kompilierung der Member-Funktion 'void __thiscall std::list<char,class cross::pool_allocator<char> >::_Freenode(struct std::list<char,class cross::pool_allocator<char> >::
_Node *)' der Klassenvorlage
Quote:Original post by Basiror
currently i am working with msvc++6.0 and the stl shipped with the compiler
Well that says it all, VC++ 6.0 is a poorly standard compliant C++ compiler (especially for templates) and a poorly implemented standard library. VC++ 6.0 doesn't support template members correctly i.e. rebind trick doesn't work on VC++ 6.0, VC++ 6.0 does an ugly hack to get round that limitation for its imp of the standard library.
Anyways i suggest either you use different modern C++ compiler otherwise if you want an MS compiler get VC++ 7.1 or 8.0 both of which is freely downloadable (VC++ 7.1 toolkit comes with no IDE, you can hook it up VC++ 6.0 IDE however).
On a side note, its not a good idea for max_size to return return 0, if you don't have a particular maximum size to return then return size_type(-1) / sizeof(T);.
Also p->T::~T(); is redundant, just do p->~T() and make sure your including header new to get placement new operator. Next, you better define equality and inequality operators for you allocator type (be it member or free function it makes no difference). Lastly you still need to define a copy constructor (unless the default behaviour of a member-wise copy is fine) because a templated constructor isn't a copy constructor, you need them both however for STL compliant allocator type as far as i'm aware.
[Edited by - snk_kid on July 29, 2005 6:46:17 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement