Skip to content

Instantly share code, notes, and snippets.

@cbsmith
Last active December 14, 2015 00:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbsmith/5002638 to your computer and use it in GitHub Desktop.
Save cbsmith/5002638 to your computer and use it in GitHub Desktop.
Me proving myself wrong.
// -*- compile-command: "clang++ -std=c++11 -stdlib=libc++ -Wall -Werror func.cc -o func" -*-
#include <iostream>
#include <functional>
#include <utility>
#include <iomanip>
//The ugly beast we're wrapping
template <typename T1, typename T2, typename T3>
struct Hooks3 {
virtual bool Fire (int *, T1 t1, T2 t2, T3 t3) { return false; }
};
//More generic version of a hook wrapper... Who creates classes called Hook2, Hook3...? ;-)
template <template <typename...> class H, typename... Ts>
struct LambdaHook : public H<Ts...> {
typedef H<Ts...> hook_t;
typedef std::function<bool(Ts...)> func_t;
//Since we are doing return type polymorphism, we can afford for this to be
//explicit
inline explicit LambdaHook(func_t&& a_func)
: hook_t(), func(std::move(a_func)) {}
bool Fire(int* ignored, Ts... args) override {
if (nullptr != ignored)
std::cout << "Ignoring " << (*ignored) << std::endl;
else
std::cout << "Ignoring a null pointer" << std::endl;
return func(std::forward<Ts>(args)...);
}
private:
func_t func;
};
template <typename F>
struct return_type_polymorphism_magic {
typedef F raw_func_t;
inline return_type_polymorphism_magic(raw_func_t&& a_func)
: f(std::move(a_func)) {}
template <template <typename...> class H, typename... Args>
inline operator H<Args...>*()&& {
typedef LambdaHook<H, Args...> lambda_t;
//this whole instance is meant to be single use, so pass f with move semantics.
return new lambda_t(typename lambda_t::func_t(std::move(f)));
}
private:
//keep this away from prying eyes
raw_func_t f;
};
//Make's a hook out of any function... even a lambda... even a lambda whose closure isn't void.
//
//Okay, actually it doesn't. It really just copies the object in to a class designed to detect the
//return type by way of conversion operation, and THAT class does all the work
template <typename P>
inline auto make_hook(P p) -> decltype( return_type_polymorphism_magic<P>(std::forward<P>(p)) ) {
return return_type_polymorphism_magic<P>(std::forward<P>(p));
}
int main (int argc, char **argv)
{
std::string foobar = "Help, I've been captured by a closure!";
Hooks3<int, int, int>* hook =
make_hook([foobar](int a, int b, int c) -> bool {
std::cout << "a: " << a << std::endl
<< "b: " << b << std::endl
<< "c: " << c << std::endl
<< "foobar: " << foobar << std::endl;
return true;
});
int ignored = 42;
bool fired = hook -> Fire (&ignored, 3, 5, 8);
std::cout << "fired: " << std::boolalpha << fired << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment