Actual source code: functional.hpp
1: #pragma once
3: #include <petsc/private/cpp/macros.hpp>
4: #include <petsc/private/cpp/utility.hpp>
5: #include <petsc/private/cpp/type_traits.hpp>
6: #include <petsc/private/cpp/tuple.hpp>
8: #include <functional>
10: namespace Petsc
11: {
13: namespace util
14: {
16: namespace detail
17: {
19: struct can_call_test {
20: template <typename F, typename... A>
21: static decltype(std::declval<F>()(std::declval<A>()...), std::true_type()) f(int);
23: template <typename F, typename... A>
24: static std::false_type f(...);
25: };
27: // generic template
28: template <typename T>
29: struct func_traits_impl : func_traits_impl<decltype(&T::operator())> { };
31: // function pointers
32: template <typename Ret, typename... Args>
33: struct func_traits_impl<Ret (*)(Args...)> {
34: using result_type = Ret;
36: template <std::size_t ix>
37: struct arg {
38: using type = util::tuple_element_t<ix, std::tuple<Args...>>;
39: };
40: };
42: // class-like operator()
43: template <typename C, typename Ret, typename... Args>
44: struct func_traits_impl<Ret (C::*)(Args...) const> {
45: using result_type = Ret;
47: template <std::size_t ix>
48: struct arg {
49: using type = util::tuple_element_t<ix, std::tuple<Args...>>;
50: };
51: };
53: template <typename C, typename Ret, typename... Args>
54: struct func_traits_impl<Ret (C::*)(Args...)> {
55: using result_type = Ret;
57: template <std::size_t ix>
58: struct arg {
59: using type = util::tuple_element_t<ix, std::tuple<Args...>>;
60: };
61: };
63: } // namespace detail
65: template <typename F, typename... A>
66: struct can_call : decltype(detail::can_call_test::f<F, A...>(0)) { };
68: template <typename... A, typename F>
69: inline constexpr can_call<F, A...> is_callable_with(F &&) noexcept
70: {
71: return can_call<F, A...>{};
72: }
74: template <typename T>
75: struct func_traits : detail::func_traits_impl<decay_t<T>> {
76: template <std::size_t idx>
77: using arg_t = typename detail::func_traits_impl<decay_t<T>>::template arg<idx>::type;
78: };
80: } // namespace util
82: } // namespace Petsc
84: #define PETSC_ALIAS_FUNCTION_WITH_PROLOGUE_AND_EPILOGUE_(alias, original, prologue, epilogue) \
85: template <typename... Args> \
86: PETSC_NODISCARD auto alias(Args &&...args) PETSC_DECLTYPE_NOEXCEPT_AUTO(original(std::forward<Args>(args)...)) \
87: { \
88: prologue; \
89: auto ret = original(std::forward<Args>(args)...); \
90: epilogue; \
91: return ret; \
92: }
94: // PETSC_ALIAS_FUNCTION() - Alias a function
95: //
96: // input params:
97: // alias - the new name for the function
98: // original - the name of the function you would like to alias
99: //
100: // notes:
101: // Using this macro in effect creates
102: //
103: // template
104: // auto alias(T&&... args)
105: // {
106: // return original(std::forward(args)...);
107: // }
108: //
109: // meaning it will transparently work for any kind of alias (including overloads).
110: //
111: // example usage:
112: // PETSC_ALIAS_FUNCTION(bar,foo);
113: #define PETSC_ALIAS_FUNCTION(alias, original) PETSC_ALIAS_FUNCTION_WITH_PROLOGUE_AND_EPILOGUE_(alias, original, ((void)0), ((void)0))
115: // Similar to PETSC_ALIAS_FUNCTION() this macro creates a thin wrapper which passes all
116: // arguments to the target function ~except~ the last N arguments. So
117: //
118: // PETSC_ALIAS_FUNCTION_GOBBLE_NTH_ARGS(bar,foo,3);
119: //
120: // creates a function with the effect of
121: //
122: // returnType bar(argType1 arg1, argType2 arg2, ..., argTypeN argN)
123: // {
124: // IGNORE(argN);
125: // IGNORE(argN-1);
126: // IGNORE(argN-2);
127: // return foo(arg1,arg2,...,argN-3);
128: // }
129: //
130: // for you.
131: #define PETSC_ALIAS_FUNCTION_GOBBLE_NTH_LAST_ARGS_(alias, original, gobblefn, N) \
132: static_assert(std::is_integral<decltype(N)>::value && ((N) >= 0), ""); \
133: template <typename TupleT, std::size_t... idx> \
134: static inline auto gobblefn(TupleT &&tuple, Petsc::util::index_sequence<idx...>) PETSC_DECLTYPE_NOEXCEPT_AUTO_RETURNS(original(std::get<idx>(tuple)...)) \
135: template <typename... Args> \
136: PETSC_NODISCARD auto alias(Args &&...args) PETSC_DECLTYPE_NOEXCEPT_AUTO_RETURNS(gobblefn(std::forward_as_tuple(args...), Petsc::util::make_index_sequence<sizeof...(Args) - (N)>{}))
138: // makes prefix_lineno_name
139: #define PETSC_ALIAS_UNIQUE_NAME_INTERNAL_(a, b, c, d, e) a##b##c##d##e
140: #define PETSC_ALIAS_UNIQUE_NAME_INTERNAL(prefix, name) PETSC_ALIAS_UNIQUE_NAME_INTERNAL_(prefix, _, __LINE__, _, name)
142: #define PETSC_ALIAS_FUNCTION_GOBBLE_NTH_LAST_ARGS(alias, original, N) PETSC_ALIAS_FUNCTION_GOBBLE_NTH_LAST_ARGS_(alias, original, PETSC_ALIAS_UNIQUE_NAME_INTERNAL(PetscAliasFunctionGobbleDispatch, original), N)