Skip to content

Instantly share code, notes, and snippets.

@tclamb
Created September 2, 2013 21:25
Show Gist options
  • Save tclamb/6417416 to your computer and use it in GitHub Desktop.
Save tclamb/6417416 to your computer and use it in GitHub Desktop.
helper function for lambda type erasure (converting from lambda to std::function)
#include <functional>
#include <type_traits>
#include <utility>
namespace
{
/* SFNIAE helper struct for call signature extraction of
* member functions */
template<typename T> struct remove_class {};
template<typename R, typename C, typename... A>
struct remove_class<R(C::*)(A...)>
{
using type = R(A...);
};
template<typename R, typename C, typename... A>
struct remove_class<R(C::*)(A...) const>
{
using type = R(A...);
};
/* lambda functions are never volatile (see 5.1.2:5 of the standard)
* these specializations are provided for completeness */
template<typename R, typename C, typename... A>
struct remove_class<R(C::*)(A...) volatile>
{
using type = R(A...);
};
template<typename R, typename C, typename... A>
struct remove_class<R(C::*)(A...) const volatile>
{
using type = R(A...);
};
}
template<typename F>
using function_t = std::function< typename remove_class<
decltype( &std::remove_reference<F>::type::operator() )
>::type >;
template <typename F>
function_t<F> make_function(F&& functor) {
return {std::forward<F>(functor)};
}
#include "make_function.h"
int main() {
/* identity function: decltype( f ) == std::function<int(int)> */
auto f = make_function([](int a){ return a; });
/* zero function: decltype( make_function(g) ) == std::function<int()>
* declared as mutable to test non-const R(C::*)(A...)
* overload of remove_class
* see 5.1.2:5 of standard for use of mutable with lambdas */
int x = 1;
auto g = [x]() mutable { x = 0; return x; };
/* should return 0 */
return f(0) + make_function(g)();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment