2

Consider this code snippet

#include <chrono>
auto wrapAndCallLambda = 
[] (auto fn, auto &&... params)
{
    const auto start = std::chrono::system_clock::now();

    auto result = fn(std::forward<decltype(params)>(params)...);
    const auto end = std::chrono::system_clock::now();

    const auto elapsed = end - start;
    std::cout << "Elapsed time: " << elapsed.count() << "s";
    return result;
};


template <typename Fn, typename... Args>
auto wrapAndCall(Fn fn, Args &&... params)
 {
    const auto start = std::chrono::system_clock::now();

    auto result = fn(std::forward<decltype(params)>(params)...);
    const auto end = std::chrono::system_clock::now();

    const auto elapsed = end - start;
    std::cout << "Elapsed time: " << elapsed.count() << "s";
    return result;
 }

Is it stricly equivalent ? Is there any consideration to have in mind (not related to opinion and style) guiding which one to choose ? Code bloating ? Performances ? Compile time if used extensively ?

sandwood
  • 2,038
  • 20
  • 38

1 Answers1

5

wrapAndCallLambda is an actual object, whereas wrapAndCall is a template.

This means that you can pass wrapAndCallLambda directly to other functions, and you have to either explicitly pass &wrapAndCall<fn_type, arg1, arg2, ...>, or wrap it into another lambda which forwards its arguments.

This also means that you cannot overload or specialize wrapAndCallLambda, but you can easily write another overload for wrapAndCall.

You also can never find wrapAndCallLambda via ADL. Which may be a feature you want.

Artyer
  • 31,034
  • 3
  • 47
  • 75
  • w.r.t. "explicitly pass" - you're not actually passing the lambda object in that case, but instead a pointer-to-function that the (instantiated) method got converted to, right? And if so does that mean it only works for captureless-lambdas? – davidbak Nov 12 '20 at 19:08