Archived

This topic is now archived and is closed to further replies.

RobTheBloke

Checking the type of a function at compile time

Recommended Posts

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

Share this post


Link to post
Share on other sites
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 ## _ARGS

DEF_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!

Share this post


Link to post
Share on other sites
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 fine

VIRTUAL1(funca,float); // chucks up a compile error




now I''ve got to get it working within a class definition....

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites