Checking the type of a function at compile time

Started by
4 comments, last by RobTheBloke 21 years, 8 months ago
I stumbled on a bit of code today that I''m thinking there may be a solution to. I need to export a virtual function from a class and be able to call it as though it were virtual. I know that this isn''t possible and the only way around it is to create an additional function that passes the parameters to the virtual function, ie
  
class Obj
{
public:
	virtual void Func(int);

	__declspec(dllexport) void VFunc(int a) {
		Func(a);
	}
};
  
I happen to be doing this an awful lot (for reasons I won''t go into) and there are other people working on the project so ideally I''d like to make this look a lot nicer with some sort of macro (just to make sure mistakes aren''t made), ie:
  
#define VIRTUAL1(FUNC,ARG1) \
	__declspec(dllexport) void VIRTUAL_##FUNC(ARG1 a) { \
		FUNC(a);  \
	}

class Obj
{
public:
	virtual void Func(int);
	VIRTUAL1(Func,int);
};
  
I''m not too bothered if things stay like that, but it would be nice to make sure that no mistakes are ever made when specifying the return and/or argument types in the macro''s. Ideally I''d like to add to the macro something that runs a compile time check on the function pointer type to compare the params with the macro created one. I know this is a bit pedantic, but I kinda got thinking about if this was possible or not. Rob p.s I use VC6
Advertisement
AFIAK, this isn''t possible. There are two reasonable possibilies... Firstly, declare both the virtual and the exported functions with the same macro. Then you only pass the argument list once, thus there can be no mismatch problem.

If you can''t declare them at the same time... Can #define expansions contain other #define commands? If yes, I''d suggest, tentatively, something like:

#define DEF_CLASS(name) \#ifdef __CLASSNAME \#undef __CLASSNAME \#endif \#define __CLASSNAME name \  class name \#define DEF_VITRUAL(name, args) \#define __CLASSNAME_ ## name ## _ARGS args \void virtual name args#define DEF_EXPORT(name) \__declspec(dllexport) void V ## name __CLASSNAME_ ## name ## _ARGSDEF_CLASS(Obj){  DEF_VIRTUAL(Func, (int));  DEF_EXPORT(Func);} 


I''d use the __CLASSNAME so we didn''t get Foo::wombat and Baz::wombat mixed up. However, I don''t know if the preprocessor works like this, and I don''t think it''s a good idea anyway: what about polymorphic functions? If the same function name is associated with several different actual functions, there''s no way to make it work without repeating the parameter list each time.

I''d opt for defining both methods with one macro.


Hail Eris! All fnord hail Discordia!
CoV
no, pre-processor stuff cannot exist within macors. I think I''ve almost got a solution though, although this only works for global functions at the moment....


  template<class T> struct FuncCheck {	FuncCheck( T a, T b) {}};#define VIRTUAL1(FUNC,ARG0) \	__declspec(dllexport) void VIRTUAL_##FUNC(ARG0 a) { \		typedef void (*func)(ARG0); \		FuncCheck<func>(FUNC,VIRTUAL_##FUNC); \		FUNC(a);	\	}void funca(int i) {}VIRTUAL1(funca,int);   // compiles fineVIRTUAL1(funca,float); // chucks up a compile error  


now I''ve got to get it working within a class definition....
I''ve now got this, not perfect cos the error message is pretty cacky and it involves pointless use of a function pointer, but it kinda works. Doubt I''ll use it though.....


  #ifdef _DEBUG#define VVIRTUAL1(CLASS,FUNC,ARG0) \	__declspec(dllexport) void VIRTUAL_##FUNC(ARG0 a) { \		typedef void (CLASS::*func##FUNC)(ARG0); \		func##FUNC pF = FUNC;	\		FUNC(a);	\	}#else#define VVIRTUAL1(CLASS,FUNC,ARG0) \	__declspec(dllexport) void VIRTUAL_##FUNC(ARG0 a) { \		FUNC(a);	\	}#endif  
Sorted

template struct ERROR_Function_Defined_With_VIRTUAL_Macro_Does_Not_Match_Real_Function
{
ERROR_Function_Defined_With_VIRTUAL_Macro_Does_Not_Match_Real_Function(T a,T b) {};
};


#define VVIRTUAL1(CLASS,FUNC,ARG0) __declspec(dllexport) void VIRTUAL_##FUNC(ARG0 a) { typedef void (CLASS::*func##FUNC)(ARG0); ERROR_Function_Defined_With_VIRTUAL_Macro_Does_Not_Match_Real_Function(FUNC,VIRTUAL_##FUNC); FUNC(a); }

[edited by - RobTheBloke on July 29, 2002 7:43:57 AM]
Even though you''ve figured it out, you might find this approach to be of interest:

http://www.accu-usa.org/Listings/2000-05-Listing01.html
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man

This topic is closed to new replies.

Advertisement