mpc
Haskell-like feature supports in C++
function.hpp
Go to the documentation of this file.
1
2#pragma once
3#include <functional> // std::invoke
4#include <memory> // std::shared_ptr
6
7namespace mpc {
8 // https://stackoverflow.com/questions/53977787/constexpr-version-of-stdfunction
9 template <class Ret, class Arg>
10 struct _function {
11 constexpr virtual ~_function() = default;
12 constexpr virtual Ret operator()(Arg&&) const = 0;
13 };
14
15 template <class F, class Ret, class Arg>
16 struct _function_impl : _function<Ret, Arg> {
17 private:
18 F f_;
19
20 public:
21 constexpr _function_impl(const F& f) : f_(f) {}
22 constexpr _function_impl(F&& f) : f_(std::move(f)) {}
23 constexpr Ret operator()(Arg&& arg) const override {
24 return std::invoke(f_, std::move(arg));
25 }
26 };
27
28 template <class>
29 struct function;
30
31 template <class Ret, class Arg>
32 requires (not std::is_reference_v<Arg>)
33 struct function<Ret(Arg)> {
34 private:
35 std::shared_ptr<_function<Ret, Arg>> instance_ = nullptr;
36
37 public:
38 function() = default;
39 template <class F>
40 requires std::invocable<std::decay_t<F>&, Arg> and std::same_as<std::invoke_result_t<std::decay_t<F>&, Arg>, Ret>
41 constexpr function(F&& f)
42 : instance_(std::make_shared<_function_impl<std::decay_t<F>, Ret, Arg>>(
43 std::forward<F>(f))) {}
44 constexpr Ret operator()(const Arg& arg) const {
45 auto tmp = arg;
46 return instance_->operator()(std::move(tmp));
47 }
48 constexpr Ret operator()(Arg&& arg) const {
49 return instance_->operator()(std::move(arg));
50 }
51 constexpr Ret operator%(const Arg& arg) const {
52 auto tmp = arg;
53 return instance_->operator()(std::move(tmp));
54 }
55 constexpr Ret operator%(Arg&& arg) const {
56 return instance_->operator()(std::move(arg));
57 }
58 };
59} // namespace mpc
Definition: function.hpp:16
Definition: function.hpp:10
Definition: function.hpp:29