You can use enable_if
or tag dispatching. Enable_if
seems to be the quicker way in this case:
#include <type_traits>
template <class Fn, class... Args>
auto timer(Fn fn, Args && ... args) -> typename std::enable_if<
// First template argument is the enable condition
!std::is_same<
decltype( fn( std::forward<Args>(args) ... )),
void >::value,
// Second argument is the actual return type
std::pair<double, decltype(fn(std::forward<Args>(args)...))> >::type
{
// Implementation for the non-void case
}
template <class Fn, class... Args>
auto timer(Fn fn, Args &&... args) -> typename std::enable_if<
std::is_same<
decltype( fn( std::forward<Args>(args) ... )),
void >::value,
double>::type
{
// Implementation for void case
}
Also you should use perfect forwarding to pass the arguments to the called function:
auto timer(Fn fn, Args && ... args) // ...
~~~^
And when you call the function:
auto ret = fn( std::forward<Args>(args)...);
Demo. Notice that this works with functions, lambda and callable objects; pretty much everything with an operator()
.
From a design standpoint, I see no problem in returning a std::pair
. Since C++11 has std::tie
, returning a pair
/ tuple
is the legitimate way of returning multiple results from a function. I would go forward and say that for consistency in the void case you should return a tuple with only one element.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…