3

I have the following code:

template <typename L>
double measure( L&& action )
{
    using namespace std::chrono;

    high_resolution_clock::time_point start, end;
    duration<double> timeSpan;

    start = high_resolution_clock::now();
    action();
    end = high_resolution_clock::now();

    timeSpan = duration_cast<milliseconds>(end - start);
    return timeSpan.count();
}

and I use it like this:

    cout << measure([](){ mergeSort<float>(array, 0, 10000); }) << endl << endl;

And so far, this is the only way I know to pass lambda functions. BUT, I was trying to make this function more complete, allowing to pass a ratio<> as template argument, to specify the ratio<> of the timeSpan template, to return time in other measure than milliseconds...

So, I want to know how can I pass multiple template arguments to a function and pass a lambda together. What should I specify on the template as the lambda's type or, what else can I do to achieve something like this:

    timer::measure<ratio<1,1000>>([](){ mergeSort<float>(array, 0, 10000); })

?

Pedro V. G.
  • 353
  • 1
  • 4
  • 13

2 Answers2

4

You can just have something like this:

template <typename Ratio, typename L>
//        ^^^^^^^^^^^^^^^^
double measure( L&& action )
{
    using namespace std::chrono;

    auto start = high_resolution_clock::now();
    action();
    auto end = high_resolution_clock::now();

    auto timeSpan = duration_cast<duration<double, Ratio>>(end - start);
    //                            ^^^^^^^^^^^^^^^^^^^^^^^
    return timeSpan.count();
}

Live demo

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • g++ gives me a long error output when I've tried this. Tried again just to check if I typed something wrong, but no. g++ basically complains this: `note: template argument deduction/substitution failed:` – Pedro V. G. Oct 26 '15 at 00:01
  • 2
    @PedroVernetti [Cannot reproduce](http://coliru.stacked-crooked.com/a/6f8bbe8a1116b843). That sounds like an error [that would happen](http://coliru.stacked-crooked.com/a/f429852574e23240) if you forgot to update your call to `measure` with `measure>`. – Shoe Oct 26 '15 at 00:03
  • No. Really not the case. I've typed exactly as I proposed. – Pedro V. G. Oct 26 '15 at 00:06
  • @PedroVernetti Can you provide a [SSCCE](http://sscce.org/) regarding this error? – Shoe Oct 26 '15 at 00:07
  • 1
    While shortening the code to show you, I've realized there was a missing '>' in the `duration_cast< ...` I'm sorry. When you said I may have forget to update the call, I only checked the call.. – Pedro V. G. Oct 26 '15 at 00:14
-4

First of all, the standard way to pass lambda functions is to use std:function:

#include <functional>

...

double measure( std::function<void()> action ){
    ...
}

Then use it in the same way you use

cout << measure([&](){ mergeSort<float>(array, 0, 10000); }) << endl << endl;

Then, you can apply Jefffrey's answer with removal of template parameter L.

Earth Engine
  • 10,048
  • 5
  • 48
  • 78
  • The "standard" i.e. recommended way to _store_ lambda functions is `std::function`. In contrast, when **passing**, using a function template on the receiving side is superior, because doing so avoids the added overhead of `std::function`... which itself is a template _anyway, **but**_ with a pile of added bloat to enable type-erasure, which in this case isn't required. See http://stackoverflow.com/questions/14677997 – underscore_d Jul 17 '16 at 08:08