Skip to content

Instantly share code, notes, and snippets.

@Garciat
Last active September 25, 2016 15:54
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 Garciat/06fec39ffb589783f889e234747fd33d to your computer and use it in GitHub Desktop.
Save Garciat/06fec39ffb589783f889e234747fd33d to your computer and use it in GitHub Desktop.
#include <functional>
#include <iostream>
#include <utility>
using namespace System;
using namespace System::Linq;
using namespace System::Collections::Generic;
template <typename T>
struct identity { using type = T; };
template <typename F>
struct function_of : function_of<decltype(&F::operator())> {};
template <typename C, typename R, typename... A>
struct function_of<R(C::*)(A...)> : identity<R(A...)> {};
template <typename C, typename R, typename... A>
struct function_of<R(C::*)(A...) const> : identity<R(A...)> {};
template <typename R, typename... A>
struct function_of<R(*)(A...)> : identity<R(A...)> {};
template <typename R, typename... A>
struct function_of<R(A...)> : identity<R(A...)> {};
template <typename F>
using function_of_t = typename function_of<F>::type;
template <typename...>
struct to_delegate;
template <typename R>
struct to_delegate<R> : identity<Func<R>> {};
template <typename T1, typename R>
struct to_delegate<T1, R> : identity<Func<T1, R>> {};
template <typename T1, typename T2, typename R>
struct to_delegate<T1, T2, R> : identity<Func<T1, T2, R>> {};
template <typename... Ts>
using to_delegate_t = typename to_delegate<Ts...>::type;
template <typename>
ref struct DelegateHelper;
template <typename R, typename... A>
ref struct DelegateHelper<R(A...)> {
using delegate_type = to_delegate_t<A..., R>;
template <typename F>
DelegateHelper(F &&f) {
func = new std::function<R(A...)>(std::move(f));
}
~DelegateHelper() {
this->!DelegateHelper();
}
!DelegateHelper() {
if (func) {
delete func;
func = nullptr;
}
}
R Call(A... args) {
return (*func)(std::forward<A>(args)...);
}
auto ToDelegate() {
return gcnew delegate_type(this, &DelegateHelper::Call);
}
static operator delegate_type ^ (DelegateHelper ^helper) {
return helper->ToDelegate();
}
private:
std::function<R(A...)> *func;
};
template <typename F>
auto make_delegate(F &&f) {
// we leak `helper`. let the GC finalize it whenever...
auto helper = gcnew DelegateHelper<function_of_t<F>>(std::move(f));
return helper->ToDelegate();
}
void example(Func<int, int> ^f) {
Console::WriteLine(f(10));
}
struct multiplier {
int operator()(int x) {
return x * k;
}
int k;
};
int main(array<System::String ^> ^args) {
int z = 10;
example(make_delegate([z](int x) { return x * z; }));
example(make_delegate(multiplier{ 10 }));
example(gcnew DelegateHelper<int(int)>([](int x) { return x; }));
auto sum = make_delegate([](int a, int b) { return a + b; });
Console::WriteLine(Enumerable::Aggregate(Enumerable::Range(0, 10), sum));
Console::ReadKey();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment