No, you need the specialization since you cannot store void (as in T result = Func();
).
If you're never gonna use the value, and you are fine with calling Func as the last thing, then you can actually:
return Func( );
both if func returns void or a type since the following is legal:
void f();void g() { return f();}
But if you need to temporarily store the return value, you need the specialization.
However, if you're gonna create a lot of these helper functions (Foo), and you don't want to have to specialize the particular Foo's for void each time, you can create a wrapper caller, which will perform the call, and when you want, return the value, be it void or some real type:
template< typename R >class call_wrapper {public: call_wrapper( std::function< R( void ) > f ) : temp( std::move( f( ) ) ) { } R&& return_and_destroy( ) { return std::move( temp ); }private: R temp;};template< >class call_wrapper< void > {public: call_wrapper( std::function< void(void) > f ) { f( ); } void return_and_destroy( ) { }};
You can then do the following in all your Foo's you're gonna write, without specialization, since it's been taken care of once and for all in the wrapper above:
template<typename T>T Foo( T(*Func)() ) { // do something first (e.g. some setup) call_wrapper< T > cw( Func ); // do something after (e.g. some tear down) return cw.return_and_destroy( );}