Created
February 21, 2021 14:02
-
-
Save adityaruplaha/bd200527b4d420f17e8c96c8c498c88b to your computer and use it in GitHub Desktop.
Function Reflection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
#include <type_traits> | |
namespace Common { | |
template <typename... Ts> | |
class TypeSeq; | |
template <> | |
class TypeSeq<> { | |
public: | |
constexpr static unsigned int length = 0; | |
constexpr static bool has = false; | |
constexpr static bool is = false; | |
template <typename... Us> | |
constexpr static bool is_eq(const TypeSeq<Us...> = {}) { | |
return false; | |
} | |
template <typename U> | |
constexpr static bool is_eq(const TypeObject<U> = {}) { | |
return false; | |
} | |
}; | |
template <typename T> | |
class TypeObject { | |
using self = Common::TypeObject<T>; | |
public: | |
template <typename U> | |
constexpr static bool has = (std::is_same_v<T, U>); | |
template <typename U, typename... Un> | |
constexpr static bool is = (TypeSeq<Un...>::length == 0 ? self::has<U> : false); | |
template <typename... Us> | |
constexpr static bool is_eq(const TypeSeq<Us...> = {}) { | |
return self::is<Us...>; | |
} | |
template <typename U> | |
constexpr static bool is_eq(const TypeObject<U> = {}) { | |
return self::is<U>; | |
} | |
}; | |
template <typename T> | |
class TypeSeq<T> { | |
using self = Common::TypeSeq<T>; | |
public: | |
template <unsigned N, std::enable_if_t<N == 0, bool> = true> | |
using member = T; | |
constexpr static unsigned int length = 1; | |
template <typename U> | |
constexpr static bool has = (std::is_same_v<T, U>); | |
template <typename U, typename... Un> | |
constexpr static bool is = (TypeSeq<Un...>::length == 0 ? self::has<U> : false); | |
template <typename... Us> | |
constexpr static bool is_eq(const TypeSeq<Us...> = {}) { | |
return self::is<Us...>; | |
} | |
template <typename U> | |
constexpr static bool is_eq(const TypeObject<U> = {}) { | |
return self::is<U>; | |
} | |
}; | |
template <typename T0, typename... Tn> | |
class TypeSeq<T0, Tn...> { | |
using self = Common::TypeSeq<T0, Tn...>; | |
public: | |
constexpr static unsigned int length = 1 + TypeSeq<Tn...>::length; | |
template <unsigned N, std::enable_if_t<(self::length > N), bool> = true> | |
using member = decltype(std::get<N>(std::declval<std::tuple<T0, Tn...>>())); | |
template <typename U> | |
constexpr static bool has = (std::is_same_v<T0, U> || TypeSeq<Tn...>::template has<U>); | |
template <typename U0, typename... Un> | |
constexpr static bool is = self::length == TypeSeq<U0, Un...>::length && | |
std::is_same_v<T0, U0> && (TypeSeq<Tn...>::template is<Un...>); | |
template <typename... Us> | |
constexpr static bool is_eq(const TypeSeq<Us...> = {}) { | |
return self::is<Us...>; | |
} | |
template <typename U> | |
constexpr static bool is_eq(const TypeObject<U> = {}) { | |
return false; | |
} | |
}; | |
} // namespace Common |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
#include "common.hpp" | |
namespace FunctionReflection { | |
template <typename R, typename... Args> | |
class FunctionReflector { | |
public: | |
explicit constexpr FunctionReflector(R (*)(Args...)) {} | |
explicit constexpr FunctionReflector(std::function <R (Args...)>) {} | |
// No function reflection on C-style variadic functions. | |
explicit constexpr FunctionReflector(R (*)(Args..., ...)) = delete; | |
explicit constexpr FunctionReflector(std::function <R (Args..., ...)>) = delete; | |
using return_type = R; | |
template <unsigned N> | |
using argument = typename Common::TypeSeq<Args...>::member<N>; | |
constexpr static unsigned int arg_count = Common::TypeSeq<Args...>::length; | |
}; | |
} // namespace FunctionReflection |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include "fn_reflect.hpp" | |
bool efn(int, int, float, long); | |
bool vfn(char, int, float, double, ...); | |
int main() { | |
constexpr auto t0 = decltype(FunctionReflection::FunctionReflector(&efn))::arg_count; | |
// Not allowed. | |
// constexpr auto t0 = decltype(FunctionReflection::FunctionReflector(&vfn))::arg_count; | |
constexpr auto t1 = decltype(FunctionReflection::FunctionReflector(&efn))::argument<3>{}; | |
constexpr bool s0 = Common::TypeSeq<int, int, float, float, long>::has<float>; | |
using s1_p0 = Common::TypeSeq<int, int, float, float, long>; | |
using s1_p1 = Common::TypeSeq<int, int, float, float, long>; | |
constexpr bool s1 = (s1_p0::is_eq(s1_p1{})); | |
printf("t0: %d\n", t0); | |
printf("t1: %s\n", typeid(t1).name()); | |
printf("s0: %s\n", s0 ? "true" : "false"); | |
printf("s1: %s\n", s1 ? "true" : "false"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment