Wouldn't it be easier to implement an overloaded version of no-op print (void)?
Good. Function templates and overloading can easily handle this at runtime.
It gets a little more sticky if you wanted to process it at compile time, for use with #if macros or with moments of static compilation.
But since you only need the first one, can I suggest something like this as a starting point:
(Tested under (GCC) 3.4.4 and 4.0.1. - I know, I need to update!)
#include <iostream> using namespace std; struct Foo { void operator()() {} }; struct Bar { bool operator()() { return false; } }; Foo foo; Bar bar; bool baz() { return false; } void bang() {} struct IsVoid { typedef char YES[1]; typedef char NO[2]; /* Testing functions for void return value. */ template <typename T> static IsVoid::NO & testFunction( T (*f)() ); static IsVoid::YES & testFunction( void (*f)() ); static IsVoid::NO & testFunction( ... ); /* Testing Objects for "void operator()()" void return value. */ template <typename C, void (C::*)()> struct hasOperatorMethodStruct { }; template <typename C> static YES & testMethod( hasOperatorMethodStruct<C, &C::operator()> * ); template <typename C> static NO & testMethod( ... ); /* Function object method to call to perform test. */ template <typename T> bool operator() (T & t) { return ( ( sizeof(IsVoid::testFunction(t)) == sizeof(IsVoid::YES) ) || ( sizeof(IsVoid::testMethod<T>(0)) == sizeof(IsVoid::YES) ) ); } };
Well, I'm starting to see more of a problem.
So far, we can do something like that:
#include <iostream> using namespace std; struct FooA { void operator()() {} }; struct FooB { bool operator()() { return false; } }; struct FooC { int operator()() { return 17; } }; struct FooD { double operator()() { return 3.14159; } }; FooA fooA; FooB fooB; FooC fooC; FooD fooD; void barA() {} bool barB() { return false; } int barC() { return 17; } double barD() { return 3.14159; } namespace N { /* Functions */ template <typename R> R run( R (*f)() ) { return (*f)(); } bool run( void (*f)() ) { (*f)(); return true; } /* Methods */ template <typename T, typename R> R run( T & t, R (T::*f)() ) { return (t .* f) (); } template <typename T> bool run( T & t, void (T::*f)() ) { (t .* f) (); return true; } };
You still have such an unpleasant need for the root & CLASS :: operator () as an argument.
Ultimately, although we can determine whether the object () method returns the void method, we cannot normally overload it based on the returned types.
We can get around this overload restriction with specialized specialization. But then we get into this ugliness, in which we still need to specify types ... Especially the return type! Either manually or by passing a suitable argument from which we can extract the necessary types.
By the way: #define macros won't help either. Tools like ?: Require the same type for both? and: part.
So this is the best I can do ...
Of course...
If you do not need a return type ...
If you just pass the result to another function ...
You can do something like this:
#include <iostream> using namespace std; struct FooA { void operator()() {} }; struct FooB { bool operator()() { return false; } }; struct FooC { int operator()() { return 17; } }; struct FooD { double operator()() { return 3.14159; } }; FooA fooA; FooB fooB; FooC fooC; FooD fooD; void barA() {} bool barB() { return false; } int barC() { return 17; } double barD() { return 3.14159; }