Skip to content

Instantly share code, notes, and snippets.

@mtao
Created November 13, 2017 20:29
Show Gist options
  • Save mtao/cff91eccb16da687ef0752b46a943ef0 to your computer and use it in GitHub Desktop.
Save mtao/cff91eccb16da687ef0752b46a943ef0 to your computer and use it in GitHub Desktop.
a bizarre (working) attempt at getting c++ to "see" the functions on the lhs of an equals sign.
#include <tuple>
#include <functional>
#include <iostream>
template <int N>
struct int_c {constexpr static int value = N;};
template <typename CallType>
void f() {};
template <int... N>
auto seq(std::integer_sequence<int,N...>) {
return std::make_tuple(N...);
}
template <int N>
auto f(int_c<N> ) {
return seq(std::make_integer_sequence<int,N>());
}
struct Return {};
template <typename CallType>
struct func {
template <typename... Args, int... N>
auto add(std::integer_sequence<int,N...>, Args... args) {
return std::make_tuple((args + N)...);
}
template <typename... Args>
auto operator()(Args... args) {
if constexpr(std::is_same<CallType, Return>::value) {
return std::make_tuple(std::forward<Args>(args)...);
} else {
return add(std::make_integer_sequence<int,CallType::value>(), std::forward<Args>(args)...);
}
}
};
template <template<typename> typename Func, typename... Args>
struct left_aware_func {
left_aware_func(Args... a): inputs{std::forward<Args>(a)...} {}
constexpr static int size() { return sizeof...(Args); }
std::tuple<Args...> inputs;
};
template <template<typename> typename Func, typename... Args>
auto make_laf(Args... a) {
return left_aware_func<Func,Args...>(std::forward<Args>(a)...);
}
template <typename CallType, typename... Args>
struct tied_caller {
tied_caller(tied_caller<CallType, Args...>&& other) = default;
tied_caller(Args&... a) {
set_ptrs(std::make_integer_sequence<int,sizeof...(Args)>(),std::forward<Args&>(a)...);
}
template <int... N>
void set_ptrs( std::integer_sequence<int,N...>, Args&... a) {
(set_ptr(std::get<N>(args),a),...);
}
template <typename T>
void set_ptr(T*& a, T& b) {
a = &b;
}
constexpr static int size() {
return sizeof...(Args);
}
template <template<typename> typename Func, typename... Args2>
tied_caller& operator=(const left_aware_func<Func,Args2...>& laf) {
return assign_laf(laf, std::make_integer_sequence<int,sizeof...(Args2)>());
}
template <template<typename> typename Func, typename... Args2, int... N>
tied_caller& assign_laf(const left_aware_func<Func,Args2...>& laf, std::integer_sequence<int,N...>) {
return operator=(Func<CallType>()(std::get<N>(laf.inputs)...));
}
tied_caller& operator=(const std::tuple<Args...>& t) {
assign(t,std::make_integer_sequence<int,size()>());
return *this;
}
template <typename A, typename B>
void set(A* a, const B& b) {
*a = b;
}
template <typename... Args2, int... N>
void assign(const std::tuple<Args2...> &t, std::integer_sequence<int,N...>) {
(set(std::get<N>(args),std::get<N>(t)), ...);
}
std::tuple<typename std::add_pointer<Args>::type...> args;
};
template <typename... Args>
auto tied_call(Args&... args) {
return tied_caller<int_c<sizeof...(Args)>,Args...>(std::forward<Args&>(args)...);
};
template <typename T, typename... Args>
auto tied_callc(Args&... args) {
return tied_caller<T,Args...>(std::forward<Args&>(args)...);
};
int main() {
int a, b, c;
tied_call(a,b) = std::make_tuple<int,int>(2,3);
std::cout << a << " " << b << std::endl;
tied_call(a,b) = make_laf<func>(0,0);
std::cout << a << " " << b << std::endl;
tied_call(a,b) = make_laf<func>(10,11);
std::cout << a << " " << b << std::endl;
tied_call(a,b,c) = make_laf<func>(0,0,0);
std::cout << a << " " << b << " " << c << std::endl;
tied_call(a,b,c) = make_laf<func>(4,3,2);
std::cout << a << " " << b << " " << c << std::endl;
tied_callc<Return>(a,b,c) = make_laf<func>(4,3,2);
std::cout << a << " " << b << " " << c << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment