c++ - Perfect forwarding for void and non-void returning functions -


previously using macro measure time function call took whenever wanted check that. now, c++11 available, remove ugly peace of preprocessor code , replace this:

template <typename functor, typename ... args> auto measure(functor f, args && ... args)     -> decltype(f(std::forward<args>(args)...)) {     auto = std::chrono::high_resolution_clock::now();     auto ret = f(std::forward<args>(args)...);     auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(         std::chrono::high_resolution_clock::now() - now).count();     std::cout << "time elapsed: " << elapsed << "ms" << std::endl;      return ret; } 

which works fine functions return (i.e. not void). felt needed overload void functions - cannot overload function on return type.

i tried walk around problem using template magic, no avail; compiler still complains function measure defined 2 times:

template <     typename functor, typename ... args,     typename returntype = typename std::enable_if<         !std::is_void<             typename std::result_of<functor(args...)>::type         >::value,         typename std::result_of<functor(args...)>::type     >::type > returntype measure(functor f, args && ... args) {     auto = std::chrono::high_resolution_clock::now();     auto ret = f(std::forward<args>(args)...);     auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(         std::chrono::high_resolution_clock::now() - now).count();     std::cout << "time elapsed: " << elapsed << "ms" << std::endl;      return ret; }  template <     typename functor, typename ... args,     typename returntype = typename std::enable_if<         std::is_void<             typename std::result_of<functor(args...)>::type         >::value     >::type > returntype measure(functor f, args && ... args) {     auto = std::chrono::high_resolution_clock::now();     f(std::forward<args>(args)...);     auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(         std::chrono::high_resolution_clock::now() - now).count();     std::cout << "time elapsed: " << elapsed << "ms" << std::endl; } 

is there way around this?


update

here function using r. martinho fernandes:

template <typename functor, typename ... args> auto measure(functor f, args && ... args)     -> decltype(f(std::forward<args>(args)...)) {     struct scoped_timer     {         scoped_timer() : now_(std::chrono::high_resolution_clock::now()) {}         ~scoped_timer()         {             auto elapsed = std::chrono::duration_cast<                     std::chrono::milliseconds                 >(std::chrono::high_resolution_clock::now() - now_).count();             std::cout << "time elapsed: " << elapsed << "ms" << std::endl;         }          private:             std::chrono::high_resolution_clock::time_point const now_;     } scoped_timer;      return f(std::forward<args>(args)...); } 

the problem default template arguments don't make different templates, same way default function arguments don't make different overloads. there ways around this, , described them in remastered enable_if article.

however, not that. take advantage of fact in generic code can "return void", , use raii print out elapsed time:

template <typename functor, typename ... args> auto measure(functor f, args && ... args)     -> decltype(f(std::forward<args>(args)...)) {     scoped_timer timer;     return f(std::forward<args>(args)...); } 

the scoped_timer class can written trivially: save now in constructor, , compute , output elapsed in destructor.


Comments