6

I want to return a lambda object from a function without casting it to a function pointer or function object. More specifically, I want to leave it to the client to decide whether or not to cast to a function object or retain the lambda as an anonymous function:

template<typename F> // F may be a std::function, boost::function, or lambda object
auto func(F f) -> decltype(???) // what do I put in here?
{
    return [=]()
    {
        return f(someParameter);
    }
}

This code doesn't work because I don't know what type to deduce. One option might be to copy the body of the lambda into the decltype call. Surely there is a better way!

My reasoning for wanting to do it this way is that I want to leave open the possibility of the compiler more intelligently inlining or unwrapping the lambdas. Does this reasoning make sense? If so, why, and when is it better simply to return std::function? Could this method ever be slower at compile time?

4
  • Is your goal to bind arguments to a function? Could be best handled using std::bind Commented Apr 3, 2014 at 3:02
  • @Anycorn My goal is to reduce the creation of function of objects and calls to std::bind. I can't control what the client will do with the return value but I want to leave open the possibility of them minimising the amount of std::binding and creation of std::function objects. Commented Apr 3, 2014 at 3:05
  • I don't think there is anything particularly bad about returning std::bind, if it's implemented like boost::bind compiler will have no problem having access to body of F. Commented Apr 3, 2014 at 3:28
  • Care to add C++1y tag to this question? Because C++1y makes it easy... Commented Apr 3, 2014 at 3:45

2 Answers 2

9

In C++11 you cannot do this. You can do a few things that are close to it, but not this.

Basically, the only way to extract a type of a C++11 lambda is to deduce it from an instance of the type, and you cannot name the type in an unevaluated context. So a function cannot return a type whose type depends on the type of a lambda. (Unless said lambda is declared, with body, prior to the function's declaration, which is not useful in this case). You can write a functor that is a manual function object, or use std::bind which does that for you.

You can have it evaluate some other functor you also pass in with the lambda, but that gets awkward (especially in C++11 where such functors either have to type erase, or have to be an old-school functor written "manually" as a struct or class).

One of the features added in C++1y makes it easy, however:

template<typename F, typename T>
auto func(F f, T t) {
  return [=]() {
    return f(t);
  };
}
int main() {
  auto f = func( [](int x){ std::cout << x << "\n"; }, 7 );
  f();
  f();
}

Live example

It is possible your compiler already has C++1y support for this feature.

Sign up to request clarification or add additional context in comments.

Comments

1
  • In C++11, type-erase with std::function<...>

  • In C++14 no need for decltype, so you can do:

    auto f() { return //lambda here }

That's all you can do for now.

Clang claims to have full c++14 support in its version 3.4, as the current draft is. Gcc has support full support for this in upcoming gcc 4.9, and partial support in gcc 4.8.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.