OXYGENHUB
◆ main openmsx / src / utils / function_ref.hh
2.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
// This is a simplified / stripped-down version of:
2
//   https://github.com/TartanLlama/function_ref/blob/master/include/tl/function_ref.hpp
3
4
///
5
// function_ref - A low-overhead non-owning function
6
// Written in 2017 by Simon Brand (@TartanLlama)
7
//
8
// To the extent possible under law, the author(s) have dedicated all
9
// copyright and related and neighboring rights to this software to the
10
// public domain worldwide. This software is distributed without any warranty.
11
//
12
// You should have received a copy of the CC0 Public Domain Dedication
13
// along with this software. If not, see
14
// <http://creativecommons.org/publicdomain/zero/1.0/>.
15
///
16
17
#ifndef FUNCTION_REF_HH
18
#define FUNCTION_REF_HH
19
20
#include <functional>
21
#include <type_traits>
22
#include <utility>
23
24
template<typename F> class function_ref;
25
26
template<typename R, typename... Args>
27
class function_ref<R(Args...)>
28
{
29
public:
30
	constexpr function_ref() noexcept = delete;
31
32
	template<typename F,
33
	         std::enable_if_t<!std::is_same_v<std::decay_t<F>, function_ref> &&
34
	                          std::is_invocable_r_v<R, F &&, Args...>>* = nullptr>
35
	constexpr function_ref(F&& f) noexcept
36
		: obj(const_cast<void*>(static_cast<const void*>(std::addressof(f))))
37
	{
38
		callback = [](void* o, Args... args) -> R {
39
			return std::invoke(*static_cast<std::add_pointer_t<F>>(o),
40
			                   std::forward<Args>(args)...);
41
		};
42
	}
43
44
	template<typename F,
45
	         std::enable_if_t<std::is_invocable_r_v<R, F &&, Args...>>* = nullptr>
46
	constexpr function_ref& operator=(F&& f) noexcept
47
	{
48
		obj = reinterpret_cast<void*>(std::addressof(f));
49
		callback = [](void* o, Args... args) {
50
			return std::invoke(*reinterpret_cast<std::add_pointer_t<F>>(o),
51
			                   std::forward<Args>(args)...);
52
		};
53
		return *this;
54
	}
55
56
	constexpr R operator()(Args... args) const
57
	{
58
		return callback(obj, std::forward<Args>(args)...);
59
	}
60
61
private:
62
	void* obj = nullptr;
63
	R (*callback)(void*, Args...) = nullptr;
64
};
65
66
template<typename R, typename... Args>
67
function_ref(R(*)(Args...)) -> function_ref<R(Args...)>;
68
69
#endif