2

Let's say we have this simplified version of my code:

template<typename R>
R Context::executeTransient(std::function<R(VkCommandBuffer)> const &commands) {
    ...
    R result = commands(commandBuffer);
    ...
    return result;
}

I tried to pass a lambda function as a parameter to the function Context::executeTransient() but it works only if I explicitly assign the lambda to a specific std::function type. This works:

std::function<int(VkCommandBuffer)> f = [](VkCommandBuffer commandBuffer) {
    printf("Test execution");
    return 1;
};
context.executeTransient(f);

The example above works but I'd like to achieve the example below because of aesthetic reasons and don't know if this is even possible:

context.executeTransient([](VkCommandBuffer commandBuffer) {
    printf("Test execution");
    return 1;
});

My only requirement is that Context::executeTransient() should accept lambdas and functions with a templated return type and input argument with some specific type e.g. VkCommandBuffer.

1 Answer 1

3

What about simply as follows ?

template <typename F>
auto Context::executeTransient (F const & commands) {
    ...
    auto result = commands(commandBuffer);
    ...
    return result;
}

This way your method accept both standard functions and lambdas (without converting them to standard functions, that is preferable, from the performance point of view (as far as I know)) and the return type is deduced from the use (auto).

In you need to know the R type inside the method, you can apply decltype() to result

     auto result = commands(commandBuffer);

     using R = decltype(result);

If you need to know the R type as template parameter of the method, its a little more complex because involve std::declval() and, unfortunately, add redundancy

template <typename F,
          typename R = decltype(std::declval<F const &>()(commandBuffer))>
R Context::executeTransient (F const & commands) {
    ...
    R result = commands(commandBuffer);
    ...
    return result;
}
Sign up to request clarification or add additional context in comments.

2 Comments

The first code snippet works perfectly if I put the implementation in the header. The third one would also work if commandBuffer wasn't a local variable. Is there any workaround besides copying the implementation in the header?
@batthomas - Suggestion: ever (ever) put the implementation of templates (classes/structs, functions, methods) in the header. Isn't strictly necessary but usually avoid a lot of troubles. More info in this answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.