template class member function msvc++

Started by
7 comments, last by Basiror 18 years, 8 months ago
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
http://www.8ung.at/basiror/theironcross.html
Advertisement
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.
ok that should explain everything
thx
http://www.8ung.at/basiror/theironcross.html
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).
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.
Quit screwin' around! - Brock Samson
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


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
http://www.8ung.at/basiror/theironcross.html
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]
the max_size isn t correct yes because i havent finished the allocator yet
i just let it return 0 to make it compile

as for the copy constructor, the vc6.0 compiler brings an error message that it s already declared maybe another bug ^^
http://www.8ung.at/basiror/theironcross.html

This topic is closed to new replies.

Advertisement