Sign in to follow this  

Capturing lambda & templates/typedefs

Recommended Posts

I'm just starting to use lambdas, due to a specific problem I'm trying to solve. So basically I need a lambda with a capture to simulate a function, that is required to store some internal state. To achieve this, I want to overload a function, which currently is defined as follows:
 

template<typename Return, typename... Args>
using GlobalBindFunction = Return(*)(Args...);

template<typename Return, typename... Args>
void registerBindFunction(GlobalBindFunction<Return, Args...> pFunction)
{
  //...
}

Now if I happen to pass in a capturing lambda, I need to call a different overload, and here's where the problem comes in - if it wasn't required to have access to "Return" and "Args...", it would be sufficient to just do:

template<typename Lambda> // typename Return, typename... Args => required
void registerBindFunction(Lambda&& pFunction)
{
  //...
}

std::string_view strIdentifier;
auto lambda = 
		[strIdentifier](CallState& state)
	{
		// ...
	};

registerBindFunction(std::move(lambda));

Most of the code could actually just work with the lambda-object instead of a function-pointer, but I've got no idea how extract the return-value & argument-list this way. Is there any way to define a template-alias like in the function-ptr example?

template<typename Return, typename... Args>
using Lambda = Return(???)(Args...);

I havn't been able to find much out via googling and/or looking at the type of my lambda via intellisense, but does somebody with expertise on lambdas got any idea? Thanks!

Share this post


Link to post
Share on other sites

To the best of my knowledge there is no standard syntax for lambda types, however given a lambda typename T, one can extract the type information by pulling the structs () operator (I.e. the lambda function):

template<typename T>
struct LambdaFunctionTraits : public LambdaFunctionTraits<decltype(&T::operator())> { };

template<typename C, typename R, typename... A>
struct LambdaFunctionTraits<R(C::*)(A...) const /*1*/ > {
	static constexpr UInt32 kArgCount = sizeof...(A);
	using ReturnType = R;
	using ArgTypes = std::tuple<A...>;
};

// Example usage, F is guarenteed to be a lambda type
template <typename F, typename TRAITS = LambdaFunctionTraits<F>>
void Foo(F&& foo) {
	using R = typename TRAITS::ReturnType;
	using A = typename TRAITS::ArgTypes;
} 

*1. Note that for mutable lambdas you would probably have to specialize for a non const function callback, but I have not implemented this yet so I can't say for sure.

In case you need the argument list as a parameter pack instead of a tuple (Or whatever intermediate type you chose), you could expand it with a proxy function that would extract the types.

Edited by Migi0027

Share this post


Link to post
Share on other sites

Thanks, works as intendet :) Having the Args as tuple isn't exactly what I need (I do require an arg-pack), but right now I can just overload the 2-3 functions being called to expand the tuple:

template<typename Return, typename... Args>
  struct GlobalExecuteHelper
{
  template<typename Function, typename State, RuntimeCommand::SlotType... I>
    static Return Call(Function func, State& state, std::index_sequence<I...>)
  {
    constexpr auto vCallSlots = CalculateCallSlots<Args...>(0);

    return func(getAttribute<Args, std::get<I>(vCallSlots)>(state)...);
  }
};

template<typename Return, typename... Args>
  struct GlobalExecuteHelper<Return, std::tuple<Args...>> :
public GlobalExecuteHelper<Return, Args...>
{
};

As for the mutable-bit, lambdas shouldn't be mutable in this case anyways; mutable state needs to be explicitely handled by a "state" object, as those functors are being instantiatied by a compiler and can be called from different places.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this