-
Notifications
You must be signed in to change notification settings - Fork 1
/
call_utils.hpp
71 lines (58 loc) · 2.47 KB
/
call_utils.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright (c) 2023 Francesco Cavaliere
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef CAV_INCLUDE_UTILS_CALL_UTILS_HPP
#define CAV_INCLUDE_UTILS_CALL_UTILS_HPP
#include <type_traits>
#include "../comptime/mp_base.hpp"
#include "../comptime/syntactic_sugars.hpp"
/// @brief Wrap a function call within a lambda, useful since function-templates are second class
/// citizens and cannot be passed as template parameters (implementing everything in Circle-lang
/// would have been a good idea).
#define LAMBDA_WRAP(FN) [&](auto&&... args) { return FN(FWD(args)...); }
namespace cav {
/// @brief Sanititze lambda and get its return type
template <typename CallT, typename... Args>
struct lambda_ret {
static_assert(std::is_invocable_v<no_cvr<CallT>, Args...>,
"Tried to invoke a lambda having incompatible arguments.");
using ret_type = std::invoke_result_t<CallT, Args...>;
};
template <typename CallT, typename... Args>
using lambda_ret_t = typename lambda_ret<CallT, Args...>::ret_type;
/// @brief Some lambdas return a boolean to notify a possible early exit criterium (from a loop).
/// This wrapper eclose the needed checks always returning a boolean
[[nodiscard]] constexpr bool ret_bool_or_false(auto&& lambda, auto&&... args) {
if constexpr (eq<bool, TYPEOF(FWD(lambda)(FWD(args)...))>)
return FWD(lambda)(FWD(args)...);
else
FWD(lambda)(FWD(args)...);
return false;
}
/// @brief Callable class/struct builder.
/// Given a function pointer, defines an equivalent callble struct
///
/// @tparam *F Function pointer
template <auto* F>
struct Ftor {};
template <class Ret, class... Args, auto (*F)(Args...)->Ret>
struct Ftor<F> {
using return_type = Ret;
using args_type = pack<Args...>;
constexpr Ret operator()(Args... args) {
return F(FWD(args)...);
}
};
} // namespace cav
#endif /* CAV_INCLUDE_UTILS_CALL_UTILS_HPP */