August 19th, 2026
heart1 reaction

On wrapping a callable in a lambda that just calls it with the same parameters

Suppose you have a function that accepts a lambda and wants to use it when calling another function. I’ve seen people wrap the lambda inside another lambda:

template<typename Lambda>
bool Widget::QueueToWorkerThread(Lambda&& lambda)
{
    CreateWorkerThreadIfNeeded();
    return m_dispatcherQueue.TryEnqueue(
        [lambda = std::forward<Lambda>(lambda)]() { lambda(); });
}

But there’s no point in wrapping a lambda inside another lambda if you are just calling the inner lambda with the same parameters as the outer one. You can use the inner lambda’s function call operator directly.

template<typename Lambda>
bool Widget::QueueToWorkerThread(Lambda&& lambda)
{
    CreateWorkerThreadIfNeeded();
    return m_dispatcherQueue.TryEnqueue(
        std::forward<Lambda>(lambda));
}

My guess is that some people don’t realize that a lambda is not a special entity in the C++ language, where if somebody says that a function accepts a lambda, they think that it means that you must literally pass a lambda.

In C++, a lambda is just syntactic sugar for a class with a function call operator. And if you already have a class with a function call operator, there’s no need to wrap it inside another class with the same function call operator.

Wrapping a lambda is basically doing this:

template<typename Lambda>
bool Widget::QueueToWorkerThread(Lambda&& lambda)
{
    CreateWorkerThreadIfNeeded();
    struct wrapper {                                   
        wrapper(Lambda&& lambda) :                     
            m_lambda(std::forward<Lambda>(lambda)) {}  
        auto operator()() const { return m_lambda(); } 
    private:                                           
        const std::remove_reference_t<Lambda> m_lambda;
    };                                                 
    return m_dispatcherQueue.TryEnqueue(
        wrapper(std::forward<Lambda>(lambda)));
}

There’s no need to introduce the extra level of indirection. The incoming lambda is already in the form you want. Just use it.

Bonus chatter: Wrapping a lambda is significant if there is a transformation on the parameters, such as cocercing them to a particular type or forcing them to be passed by value.

Topics

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments