python - Nested Template Functions as Parameters -


in python, there way of decorating function such can add additional functionality before and/or after function. in simple form, looks this:

from random import systemrandom time import time import functools  rdev = systemrandom()  def time_function(func):     @functools.wraps(func)     def run(*args, **kwargs):         start = time()         ret = func(*args, **kwargs)         print("took {:0.5f}s".format(time()-start))         return ret     return run  @time_function def foo():     x = [rdev.randint(1, 1000) _ in range(10000)]     sorted(x)  foo()  # prints "took 0.04239s" 

i wanted write similar functionality in c++. pass function arbitrary parameters , return types function , have perform action. came with:

#ifndef timeit_h #define timeit_h #include <string> #include <functional> #include <iostream> #if defined(_win32) #include <windows.h> namespace timeit {     unsigned long gettime(void) {         return gettickcount();     } } #elif defined(__linux__) namespace timeit{     unsigned long gettime(void) {         return 0; // implement later     } } #endif  namespace timeit {     template <typename> struct timer_s;      template<typename... args> // required void function     struct timer_s<void(args ...)> {         std::function<void(args ...)> func;         timer_s(std::function<void(args ...)> f) : func{ f } {}         void operator()(unsigned long &time, args ... args) {             unsigned long start = gettime();             func(args ...);             time = gettime() - start;             return;         }     };      template <typename t, typename... args> // other return type     struct timer_s<t(args ...)> {         std::function<t(args ...)> func;         timer_s(std::function<t(args ...)> f) : func{ f } { }         t operator()(unsigned long &time, args ... args) {             unsigned long start = gettime();             t ret = func(args ...);             time = gettime() - start;             return ret;         }     };      template<typename t, typename... args>     timer_s<t(args...)> timer(t(*func)(args ...)) {         return timer_s<t(args ...)>(std::function<t(args ...)>(func));     } } #endif//timeit_h 

this working rather well. example, can time function following:

static std::random_device rdev;  unsigned int foo(size_t size){     std::vector<unsigned int> nums(size);     std::mt19937 rand(rdev());     std::generate(nums.begin(), nums.end(), rand);     std::sort(nums.begin(), nums.end());     return nums.back(); // return largest number }  int main(){     //foo(0xffff); // normal call     unsigned long foo_time = 0;     auto t_foo = timeit::timer(foo);     unsigned int largest = t_foo(foo_time, 0xffff); // stores time     std::cout << "took " << foo_time << "ms\nlargest number: " << largest << "\n";     return 0; } 

the trouble arises when try time templated function such std::sort directly. can if specify exact type. supposed wondering if c++ capable of doing nested template deduction. want deduce form of std::sort using , change implementation of t_sort dynamically:

what doing:

static std::random_device rdev;  int main(){     std::vector<unsigned int> nums(size);     std::mt19937 rand(rdev());     std::generate(nums.begin(), nums.end(), rand);     auto t_sort = timeit::timer(std::sort<std::vector<unsigned int>::iterator>);     unsigned long sort_time = 0;     t_sort(sort_time, nums.begin(), nums.end()); } 

what like:

static std::random_device rdev;  int main(){     std::vector<unsigned int> nums(size);     std::mt19937 rand(rdev());     std::generate(nums.begin(), nums.end(), rand);     auto t_sort = timeit::timer(std::sort); // line different     unsigned long sort_time = 0;     t_sort(sort_time, nums.begin(), nums.end()); } 

is possible? initial reaction not, if not, why?

std::sort not function function template,

one solution accept functor instead:

namespace timeit {      template <typename functor>     struct timer_s {         functor func;         double time = 0;         timer_s(functor  f) : func{ f } {}          template <typename ... ts>         auto operator()(ts ... args) {             struct {                 ~finally() {                     time = std::chrono::duration_cast<std::chrono::milliseconds>                               (std::chrono::system_clock::now() - start).count();                 }                 double& time;                 std::chrono::time_point<std::chrono::system_clock> start;             } finally{time, std::chrono::system_clock::now()};             return func(std::forward<ts>(args)...);         }     };      template<typename f>     timer_s<f> timer(f f) {         return timer_s<f>(f);     } } 

and call it:

// generic lambda wrap std::sort , call correct one. auto t_sort = timeit::timer([](auto b, auto e){ return std::sort(b, e); });  std::vector<int> v {4, 8, 23, 42, 15, 16};  t_sort(v.begin(), v.end()); 

demo


Comments

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -