Skip to content

Instantly share code, notes, and snippets.

@schaumb
Last active June 30, 2020 18:40
Show Gist options
  • Save schaumb/1f0f0931b5133e2611993f0f8975faae to your computer and use it in GitHub Desktop.
Save schaumb/1f0f0931b5133e2611993f0f8975faae to your computer and use it in GitHub Desktop.
#include <iostream>
#include <tuple>
#include <boost/callable_traits.hpp>
#include <boost/type_index/ctti_type_index.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
template<template <typename> typename Base, std::size_t ...Dependents>
struct Depends : Base<Depends<Base, Dependents...>> {
constexpr Depends() : Base<Depends<Base, Dependents...>>(*this) {}
template<typename T>
constexpr Depends(T&&...) : Depends() {}
template<typename T>
[[noreturn]] constexpr operator T() const { throw 0; }
template<typename T>
[[noreturn]] constexpr operator T&() const { throw 0; }
};
template<typename Lambda>
struct lambda_template_result {
template<typename ...Ts>
using type = std::invoke_result_t<Lambda, Ts...>;
};
struct empty {};
struct lam_empty {
template<typename T>
empty operator()(T&&) {
return {};
}
};
template<std::size_t V, typename BaseLam = lam_empty>
struct Placeholder : Depends<lambda_template_result<BaseLam>::template type, V> {};
template<typename BaseLam>
struct BindPlaceholder {
};
template <class Fn>
struct invocable_template_impl {
template<typename Tup, typename = void>
struct with_impl {
constexpr static bool value = false;
};
template<typename...Ts>
struct with_impl<std::tuple<Ts...>, std::void_t<decltype(&Fn::template operator() <Ts...>)>> {
constexpr static bool value = true;
using type = decltype(&Fn::template operator() <Ts...>);
};
template<typename ...Ts>
constexpr static auto with = with_impl<std::tuple<Ts...>>::value;
template<typename ...Ts>
using type = typename with_impl<std::tuple<Ts...>>::type;
};
template<typename Fun, template <std::size_t> typename PH = Placeholder, std::size_t N = 0, typename Ix = std::decay_t<decltype(std::make_index_sequence<N>())>, typename = void>
struct invocable_typeded : invocable_typeded<Fun, PH, N+1> {};
template<typename Fun, template <std::size_t> typename PH, std::size_t N, std::size_t...ix>
struct invocable_typeded<Fun, PH, N, std::index_sequence<ix...>, std::enable_if_t<(N > 10)>> {
static_assert(N <= 10, "More than 10 template parameter. Possible wrong members / operators are implemented.");
};
template<typename Fun, template <std::size_t> typename PH, std::size_t N, std::size_t...ix>
struct invocable_typeded<Fun, PH, N, std::index_sequence<ix...>, std::enable_if_t<
invocable_template_impl<Fun>::template with<PH<ix+1> ...> >> {
using type = typename invocable_template_impl<Fun>::template type<PH<ix+1> ...>;
};
#define INVOKABLE(type_param, ...) [] { \
/*BOOST_PP_SEQ_FOR_EACH(INVOKABLE_CREATE_TYPE, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) */ \
return typename invocable_typeded<type_param>::type{}; \
}
int main() {
auto l = [](int, auto y, auto) { return y; };
auto X = [] {
auto il = [](auto& type) {
struct C {
decltype(type)& first;
decltype(type)& second;
C(decltype(type)& p)
: first(p)
, second(p) {}
} c(type);
return c;
};
return Placeholder<1, decltype(il)>{};
};
std::cout << boost::typeindex::ctti_type_index::type_id<std::invoke_result_t<decltype(X)>>().pretty_name() << std::endl;
// using res = boost::callable_traits::return_type_t<invocable_template_impl<decltype(l)>::template type<Placeholder<1>, Placeholder<2>>>;
//using res = boost::callable_traits::return_type_t<invocable_typeded<decltype(l)>::type>;
auto typeded = INVOKABLE(decltype(l), first, second);
using res2 = boost::callable_traits::return_type_t<std::invoke_result_t<typeded>>;
std::cout << boost::typeindex::ctti_type_index::type_id<res2>().pretty_name() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment