template help please(c++)

Started by
8 comments, last by DrEvil 16 years, 3 months ago
Can someone help me out with some template issues I'm having. I have this struct for a script binding interface that I have some explicit specialized function inside of. This compiles and works as I expect in MSVC2005, but not in GCC 4.1.0 GCC gives the error: error: explicit specialization in non-namespace scope 'struct ParentClass<ClassT>' error: enclosing class templates are not explicitly specialized errot: 'Get' is not a function template I don't quite understand how to change this to do it 'correctly' despite some digging around on google and such. Here it is trimmed up a bit.

template<typename ClassT>
struct ParentClass
{
	template<typename T>
	static int Get(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset) { return 1; }
	//////////////////////////////////////////////////////////////////////////
	template<>
	static int Get<bool>(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset)
	{
		// do stuff with bool type
		return 1;
	}

	template<>
	static int Get<int>(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset)
	{
		// do stuff with int type
		return 1;
	}
	template<>
	static int Get<float>(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset)
	{
		// do stuff with float type
		return 1;
	}
}
Advertisement
You cannot specialize template inside a class, only in a namespace. MVS does allows for such specialization, but GCC is more correct.

Just move Get outside of class.
template<typename ClassT, typename T>static int Get(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset) { return 1; }template<typename ClassT>static int Get<ClassT, bool>(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset){	// do stuff with bool type	return 1;}// and so on


Hmm, error C2768: 'Get' : illegal use of explicit template arguments

edit:

should it be this?

template<typename ClassT, typename T>static int Get(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset) { return 1; }template<typename ClassT, bool>static int Get(ClassT *p, gmThread *a_thread, gmVariable *a_operands, size_t a_offset){	// do stuff with bool type	return 1;}


checking in gcc to see, this compiles in msvc at least. will report back
IIRC, it isn't legal to partially specialize a function template.
ok yea that doesn't work.

Grr, not sure how to accomplish what I need to do.

I don't see why this has to be so difficult. Standards or not something that seems like it should be a simple matter turns into a raging pain as soon as I bring GCC into it.

Basically I need to explicitly specialize a set of functions that also takes another templated class type as an argument, as shown. Any ideas?
I suppose I can remove ClassT and pass a void *
Create a template-class complete with a specialisation for bool. Each should have a templated static member function that does the actual work.

Then (optionally) create a templated wrapper function that forwards to the right specialisation.

Example:

template<typename T>struct gizmo{    template<typename U>    static void apply( /* ... */ );};template<>struct gizmo<bool>{    template<typename U>    static void apply( /* ... */ );};template<typename T, typename U>void convenient_wrapper_function( /* ... */ ){    gizmo<T>::apply<U>( /* ... */ );    //        ^    // might need "template" key word in here,    // I can never remember!?}
thanks. I'll give that a shot.
Quote:Original post by Nitage
IIRC, it isn't legal to partially specialize a function template.


Yes, I was thinking of classes, it's what I had to deal with.


Still, I'm no longer sure about this, there appears to be a bug in gcc as well, that applies to this problem.

Personally, I solved the problem by avoiding partial specialization of this type altogether, didn't think it was worth dealing with it further.

Since these functions don't appear to depend on ParentClass<T> in any way (only on T), why nest the functions in the first place?

It wasn't necessary for ParentClass to be there. I was using it more like a namespace than a struct. The code you pasted compiled in MSVC2005, until I added a version for float and std::string, etc. I should be able to get away with passing a void* instead of ClassT *. Internally the functions are setting/getting a <T> type based on the address + offset, so I don't think I think a void * will do just as well. That failing, I'll try the method the_edd posted, though that would require a number of other changes if it comes to that.

Thanks everyone for the help.

This topic is closed to new replies.

Advertisement