I don't think you actually need to specialize for void return type. A void function is allowed to return the "result" of another void function for exactly this scenario.
void foo() { }
void bar() { return foo(); } //this is OK
int main()
{
bar();
}
So your only problem would be how to determine the return type.
It appears that boost::function
has a typedef for result_type
(see http://beta.boost.org/doc/libs/1_37_0/doc/html/boost/functionN.html)
#include <boost/function.hpp>
template<class T>
class Container
{
public:
typedef typename boost::function<T>::result_type result_type;
private:
boost::function<T> f;
};
Container<bool(int, int)>::result_type r = true;
Edit:
Now that you know what the result_type
is, and you do need to distinguish between void/non-void results, you can employ enable_if
and disable_if
. The only complication is that those only work with function templates, so a non-template foo
calls a templated do_foo
.
#include <boost/function.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <cstdio>
template<class T>
class Container
{
public:
typedef typename boost::function<T>::result_type result_type;
result_type foo()
{
return do_foo<result_type>();
//note that this still works because you can return the void result! :)
}
private:
//use this if the result_type is void
template <class U>
typename boost::enable_if<boost::is_same<U, void>, U >::type do_foo()
{
std::puts("for void");
}
//else
template <class U>
typename boost::disable_if<boost::is_same<U, void>, U>::type do_foo()
{
std::puts("other");
return U();
}
private:
boost::function<T> f;
};
int main()
{
Container<void()> a;
a.foo();
Container<int()> b;
b.foo();
}