File: Function.h

package info (click to toggle)
jazz2-native 3.5.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid
  • size: 16,912 kB
  • sloc: cpp: 172,557; xml: 113; python: 36; makefile: 5; sh: 2
file content (594 lines) | stat: -rw-r--r-- 26,821 bytes parent folder | download
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
// Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
//             2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024
//           Vladimír Vondruš <mosra@centrum.cz> and contributors
// Copyright © 2020-2024 Dan R.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#pragma once

#include "../Asserts.h"
#include "../Base/Move.h"

#include <new>
#include <type_traits>

namespace Death { namespace Containers {
//###==##====#=====--==~--~=~- --- -- -  -  -   -

	/**
		@brief No-allocate initialization tag type

		Used to distinguish @ref Function<R(Args...)> "Function" construction that
		disallows allocating stateful function data on heap.
	*/
	struct NoAllocateInitT {
#ifndef DOXYGEN_GENERATING_OUTPUT
		struct Init {};
		constexpr explicit NoAllocateInitT(Init) {}
#endif
	};

	/**
		@brief No-allocate initialization tag

		Used to distinguish @ref Function<R(Args...)> "Function" construction that
		disallows allocating stateful function data on heap.
	*/
	constexpr NoAllocateInitT NoAllocateInit{NoAllocateInitT::Init{}};

	namespace Implementation
	{
		// Lower bound of the size is verified with a static_assert() in templated Function constructors below,
		// upper bound in particular FunctionTest::call*() cases.
		enum: std::size_t { FunctionPointerSize =
#if !defined(DEATH_TARGET_WINDOWS) || defined(DEATH_TARGET_MINGW)
			2 * sizeof(void*) / sizeof(std::size_t)
#else
			// On MSVC, pointers to members with a virtual base class are the biggest and have 12 bytes on 32-bit and 16 on 64-bit.
			// Pointers to incomplete class members are 16 bytes on both 32-bit and 64-bit, but such scenario is impossible
			// to happen here as there's a std::is_base_of check in Function constructor that requires the type to be complete.
#	if defined(DEATH_TARGET_32BIT)
			12 / sizeof(std::size_t)
#	else
			16 / sizeof(std::size_t)
#	endif
#endif
		};
	}

	/**
		@brief @ref Function<R(Args...)> "Function" data storage

		Type-erased base for @ref Function<R(Args...)> "Function". Suitable for storing
		type-erased function pointers in containers.
	*/
	class FunctionData
	{
	public:
		/**
		 * @brief Default constructor
		 *
		 * Creates a @cpp nullptr @ce function.
		 */
		/*implicit*/ FunctionData(std::nullptr_t = nullptr) noexcept: _storage{}, _call{nullptr} {}

		/** @brief Copying is not allowed */
		FunctionData(const FunctionData&) = delete;

		/** @brief Move constructor */
		FunctionData(FunctionData&&) noexcept;

		~FunctionData();

		/** @brief Copying is not allowed */
		FunctionData& operator=(const FunctionData&) = delete;

		/** @brief Move assignment */
		FunctionData& operator=(FunctionData&&) noexcept;

		/**
		 * @brief Whether the function pointer is non-null
		 *
		 * Returns @cpp false @ce if the instance was default-constructed,
		 * constructed from a @cpp nullptr @ce free or member function pointer
		 * or moved out, @cpp true @ce otherwise.
		 */
		explicit operator bool() const {
			return _call || _storage.functor.call;
		}

		/**
		 * @brief Whether the instance contains heap-allocated state
		 *
		 * Returns @cpp true @ce if the instance was created from a capturing
		 * lambda or a functor with a large or non-trivially copyable state,
		 * @cpp false @ce otherwise. In other words, always returns
		 * @cpp false @ce for default-constructed instances, free and member
		 * function pointers and instances constructed with the
		 * @ref NoAllocateInitT constructor.
		 */
		bool isAllocated() const { return !_call && _storage.functor.call; }

	private:
		template<class> friend class Function;

#ifndef DOXYGEN_GENERATING_OUTPUT
		// Doxygen 1.12.0 outputs also private structs/unions even if it shouldn't
		union Storage {
			// Simple, small enough and trivial functors
			char data[Implementation::FunctionPointerSize*sizeof(std::size_t) + sizeof(void*)];

			// Free functions
			void(*function)();

			// Member functions
			struct {
				char data[Implementation::FunctionPointerSize*sizeof(std::size_t)];
				void* instance;
			} member;

			// Non-trivially-destructible/-copyable or too large functors. The data points
			// to heap-allocated memory that has to be moved and deleted.
			struct {
				void* data;
				void(*free)(Storage&);
				void(*call)();
			} functor;
		};
#endif

		constexpr explicit FunctionData(const Storage& storage, void(*call)()):
			// GCC 4.8 attempts to initialize the first member (the char array) instead of performing a copy if {} is used
#if defined(DEATH_TARGET_GCC) && !defined(DEATH_TARGET_CLANG) && __GNUC__ < 5
			_storage(storage),
#else
			_storage{storage},
#endif
			_call{call} {}

		Storage _storage;
		// Calls into _storage.function, _storage.data or _storage.member. If nullptr, _storage.functor.call is used instead
		// (if not nullptr as well), and _storage.functor.data points to heap-allocated data that has to be moved and deleted.
		void(*_call)();
	};

	namespace Implementation
	{
		/* Takes the void_t trick, explained at https://stackoverflow.com/a/27688405,
		   and takes it one step further. The basic premise is that with

			template<class> using VoidT = void;
			template<class, class = void> struct HasThing {
				enum : bool { value = false };
			};
			template<class T> struct HasThing<T, VoidT<decltype(T::Thing)>> {
				enum : bool { value = true };
			};

		   when `HasThing<Foo>` is in code, `HasThing<Foo, void>` gets looked for,
		   because the second template argument wasn't specified and `void` was the
		   default. The compiler then looks for the most specialized variant of the
		   `HasThing<Foo, void>` template and falls back to the unspecialized version
		   only if nothing else matches. Thus, if `T` contains a `Thing` member, the
		   second `HasThing` from above gets picked (because it *does* specialize
		   `HasThing<Foo, void>`, although cryptically), and if it doesn't, SFINAE
		   takes care of this not being an error and a fallback to the unspecialized
		   template is picked.

		   Here, instead of having a `VoidT` that eats any type, a function overload
		   that accepts one of the four allowed member functions with desired signature
		   is picked. If the operator() doesn't exist or none of the possible overloads
		   have given signature, it again falls back to the default. */
		template<class T, class Signature, class = void> struct IsFunctor;
		template<class T, class R, class ...Args, class U> struct IsFunctor<T, R(Args...), U> {
			enum : bool { value = false };
		};
		/* Originally this was a set of
			template<class Class, class R, class ...Args> void functorSignature(R(Class::*)(Args...)) {}
			...
		   overloads because that seemed to work as well, was simpler, and this was
		   present only for MSVC 2017 (but not 2015) because it ICEs when it encounters
		   `decltype(functionSignature<T, R, Args...>())`. However, the problem with
		   function template arguments is that they get autodetected if not passed.
		   Thus, with just a function, asking for e.g.
			functionSignature<T, int>(&T::operator())
		   would match not only `int()` but also `int(float)`, `int(float, short)` and
		   just any other argument combination because they would ultimately match as
			functionSignature<T, int, float>(&T::operator())
			functionSignature<T, int, float, short>(&T::operator())
		   etc. The robust solution is to put these templates into a struct instead,
		   where they cannot be auto-filled. */
		template<class> struct FunctorSignature;
		template<class Class, class R,  class ...Args> struct FunctorSignature<R(Class::*)(Args...)> {
			static void match(R(Class::*)(Args...)) {}
			static void match(R(Class::*)(Args...) &) {}
			static void match(R(Class::*)(Args...) const) {}
			static void match(R(Class::*)(Args...) const &) {}
		};
		template<class T, class R, class ...Args> struct IsFunctor<T, R(Args...), decltype(FunctorSignature<R(T::*)(Args...)>::match(&T::operator()))> {
			enum : bool { value = !std::is_convertible<T, R(*)(Args...)>::value };
		};
	}

	/**
		@brief Function wrapper

		See the @ref Function<R(Args...)> specialization.
	*/
	template<class> class Function;

	/**
		@brief Function wrapper

		An alternative to @m_class{m-doc-external} [std::move_only_function](https://en.cppreference.com/w/cpp/utility/functional/move_only_function)
		from C++23 or a move-only alternative to @ref std::function from C++11,
		providing a common interface for free functions, member functions, (capturing)
		lambdas and generic functors. The wrapped function is then called through @ref operator()().

		To prevent accidental type conversions and potential extra overhead coming from
		those, the wrapper only accepts functions that match the signature *exactly*.
		If a function or a functor has a set of overloads, an overload matching
		the signature is picked. If you have a function which has a different signature,
		wrap it in a lambda of a matching singature first.

		@section Containers-Function-usage-overhead Function call overhead

		On construction, a stateless wrapper lambda is created that then delegates to
		the particular free function pointer, member function pointer, or a stateful
		functor / lambda. In the common case this means that invoking a
		@ref Function<R(Args...)> "Function" always involves two function calls, one
		for the wrapper lambda and one for the actual function being called.

		If the wrapped function is inlineable, in optimized builds this can reduce to
		just a single function call to the wrapper lambda, which then has the actual
		function call inlined inside.

		@section Containers-Function-usage-stateful Stateful function storage

		The @ref Function<R(Args...)> "Function" class is internally made large enough
		to fit any free or member function pointer. But because member function
		pointers can increase in size if multiple inheritance and/or virtual
		inheritance is involved, that space can be repurposed also for saving up to 24
		bytes of stateful lambda / functor data on 64-bit platforms (and up to 16 bytes
		on 32-bit platforms). If larger, the data is allocated on heap instead. For
		implementation simplicity reasons the state is also allocated if isn't
		trivially copyable. You can use @ref isAllocated() to check whether the
		function state needed a heap allocation or not.
		If heap allocation is undesirable, the @ref Function(NoAllocateInitT, F&&)
		overload can be used to prevent wrapping any function with state that would
		need to be allocated.

		@section Containers-Function-usage-type-erased Type-erased function storage

		The class derives from a type-erased @ref FunctionData base, which owns all
		state and also takes care of proper moving and destruction for non-trivial
		functors. This allows it to be used as a type-erased storage in various
		containers for example. Cast the instance back to a concrete
		@ref Function<R(Args...)> "Function" in order to use it.
	*/
	template<class R, class ...Args> class Function<R(Args...)> : public FunctionData
	{
	public:
		/** @brief Function type */
		typedef R(Type)(Args...);

		/**
		 * @brief Default constructor
		 *
		 * Creates a @cpp nullptr @ce function.
		 */
		/*implicit*/ Function(std::nullptr_t = nullptr) noexcept : FunctionData{nullptr} {}

		/**
		 * @brief Wrap a free function pointer
		 *
		 * If @p f is @cpp nullptr @ce, the constructor is equivalent to
		 * @ref Function(std::nullptr_t).
		 */
		/*implicit*/ Function(R(*f)(Args...)) noexcept;

		/**
		 * @brief Wrap a member function pointer
		 *
		 * Default, @cpp & @ce, @cpp const @ce and @cpp const & @ce r-value
		 * overloads are supported, @cpp && @ce and @cpp const && @ce however
		 * isn't, as the member function is always called on a l-value. If @p f
		 * is @cpp nullptr @ce, the constructor is equivalent to
		 * @ref Function(std::nullptr_t).
		 */
		template<class Instance, class Class> /*implicit*/ Function(Instance& instance, R(Class::*f)(Args...)) noexcept;
		/** @overload */
		template<class Instance, class Class> /*implicit*/ Function(Instance& instance, R(Class::*f)(Args...) &) noexcept;
		/** @overload */
		template<class Instance, class Class> /*implicit*/ Function(Instance& instance, R(Class::*f)(Args...) const) noexcept;
		/** @overload */
		template<class Instance, class Class> /*implicit*/ Function(Instance& instance, R(Class::*f)(Args...) const &) noexcept;

		/**
		 * @brief Create a null member function pointer
		 *
		 * Equivalent to @ref Function(std::nullptr_t).
		 */
		template<class Instance> /*implicit*/ Function(Instance&, std::nullptr_t) noexcept : Function{nullptr} {}

		/**
		 * @brief Wrap a lambda or a functor
		 *
		 * The functor is expected to *exactly* match the signature, no
		 * implicit conversions on either the arguments or return type are
		 * allowed. If the lambda capture or functor state is small enough and
		 * trivially copyable, it's stored inline, otherwise allocated on heap.
		 */
		template<class F
#ifndef DOXYGEN_GENERATING_OUTPUT
			// Enabling this only for functors and lambdas convertible to function pointers,
			// regular function pointers should go through the R(*)(Args...) overload above.
			, typename std::enable_if<std::is_convertible<typename std::decay<F>::type, R(*)(Args...)>::value || Implementation::IsFunctor<typename std::decay<F>::type, R(Args...)>::value, int>::type = 0
#endif
		> /*implicit*/ Function(F&& f) noexcept(sizeof(typename std::decay<F>::type) <= sizeof(Storage) &&
			std::is_trivially_copyable<typename std::decay<F>::type>::value
		) : Function{nullptr, Death::forward<F>(f)} {}

		/**
		 * @brief Wrap a small enough and trivial lambda / functor
		 *
		 * Compared to @ref Function(F&&) compiles only if the lambda capture
		 * or functor state is small enough and trivially copyable to not need
		 * to be allocated on heap.
		 *
		 * Note that there's no @ref NoAllocateInit variant for free or member
		 * function pointers, as they never need to be allocated on heap.
		 */
		template<class F
#ifndef DOXYGEN_GENERATING_OUTPUT
			// Enabling this only for functors that aren't convertible to function pointers,
			// everything else never allocates so using this overload makes no sense
			, typename std::enable_if<Implementation::IsFunctor<typename std::decay<F>::type, R(Args...)>::value, int>::type = 0
#endif
		> explicit Function(NoAllocateInitT, F&& f) noexcept;

		/**
		 * @brief Call the function pointer
		 *
		 * Expects that the pointer is not @cpp nullptr @ce.
		 */
		R operator()(Args... args);

	private:
		// Functor convertible to a function pointer, delegates to the function pointer variant
		template<class F, typename std::enable_if<std::is_convertible<typename std::decay<F>::type, R(*)(Args...)>::value, int>::type = 0> explicit Function(std::nullptr_t, F&& f) noexcept : Function{static_cast<R(*)(Args...)>(f)} {}

		// Simple, small enough and trivial functor which is not convertible to a function pointer,
		// delegates to the NoAllocateInit variant
		template<class F, typename std::enable_if<!std::is_convertible<typename std::decay<F>::type, R(*)(Args...)>::value && sizeof(typename std::decay<F>::type) <= sizeof(Storage) &&
			std::is_trivially_copyable<typename std::decay<F>::type>::value
		, int>::type = 0> explicit Function(std::nullptr_t, F&& f) noexcept :
			// Note that, as this is a trivially copyable functor, it doesn't need std::forward<F>(f)
			Function{NoAllocateInit, f} {}

		// Non-trivially-destructible/-copyable or too large functor. MSVC 2015 and 2017 has all lambdas not trivially
		// copyable, so it has to additionally check that it isn't convertible to a function pointer to avoid ambiguity
		// with the constructor taking a functor convertible to a function pointer.
		template<class F, typename std::enable_if<
#if defined(DEATH_MSVC2017_COMPATIBILITY)
			!std::is_convertible<typename std::decay<F>::type, R(*)(Args...)>::value &&
#endif
			(sizeof(typename std::decay<F>::type) > sizeof(Storage) ||
			!std::is_trivially_copyable<typename std::decay<F>::type>::value
		), int>::type = 0> explicit Function(std::nullptr_t, F&& f);
	};

	inline FunctionData::FunctionData(FunctionData&& other) noexcept :
		// GCC 4.8 attempts to initialize the first member (the char array) instead of performing a copy if {} is used
#if defined(DEATH_TARGET_GCC) && !defined(DEATH_TARGET_CLANG) && __GNUC__ < 5
		_storage(other._storage),
#else
		_storage{other._storage},
#endif
		_call{other._call}
	{
		// Move out the other instance, if it's heap-allocated data
		if(!_call && _storage.functor.call)
			other._storage.functor.call = nullptr;
	}

	inline FunctionData::~FunctionData() {
		// If it's heap-allocated data, delete
		if(!_call && _storage.functor.call)
			_storage.functor.free(_storage);
	}

	inline FunctionData& FunctionData::operator=(FunctionData&& other) noexcept {
		using Death::swap;
		swap(other._storage, _storage);
		swap(other._call, _call);
		return *this;
	}

	template<class R, class ...Args> inline R Function<R(Args...)>::operator()(Args... args) {
		void(*const call)() = _call ? _call : _storage.functor.call;
		return DEATH_DEBUG_CONSTEXPR_ASSERT(call, "The function is null"),
			reinterpret_cast<R(*)(Storage&, Args...)>(call)(_storage, Death::forward<Args>(args)...);
	}

	// Free function
	template<class R, class ...Args> Function<R(Args...)>::Function(R(*f)(Args...)) noexcept {
		_storage.function = reinterpret_cast<void(*)()>(f);
		// The + is to decay the lambda to a function pointer so we can cast it. MSVC 2015 says it's "illegal on a class"
		// so there it's an explicit cast to the function pointer type (and the parentheses are for both to have only one ifdef).
		_call = !f ? nullptr : reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return reinterpret_cast<R(*)(Args...)>(storage.function)(Death::forward<Args>(args)...);
		}));
	}

#ifndef DOXYGEN_GENERATING_OUTPUT
	// Doxygen 1.12.0 outputs also some template specializations, so suppress it
	// Simple, small enough and trivial functor which is not convertible to a function pointer 
	template<class R, class ...Args> template<class F, typename std::enable_if<Implementation::IsFunctor<typename std::decay<F>::type, R(Args...)>::value, int>::type> Function<R(Args...)>::Function(NoAllocateInitT, F&& f) noexcept {
		static_assert(sizeof(typename std::decay<F>::type) <= sizeof(FunctionData::Storage) &&
			std::is_trivially_copyable<typename std::decay<F>::type>::value
		, "Functor too large or non-trivial to be stored without allocation");

		// GCC 4.8 attempts to initialize the first member instead of performing a copy if {} is used.
#if defined(DEATH_TARGET_GCC) && !defined(DEATH_TARGET_CLANG) && __GNUC__ < 5
		new(&_storage.data) typename std::decay<F>::type(f);
#else
		// std::is_trivially_copyable can be true for classes that have deleted copy constructors
		// (but non-deleted trivial move constructors), so we need a move here.
		// On GCC 4.8 the __has_trivial_copy() is false for such classes, so the move isn't needed in the above variant.
		new(&_storage.data) typename std::decay<F>::type{Death::move(f)};
#endif
		// The + is to decay the lambda to a function pointer so we can cast it. MSVC 2015 says it's "illegal on a class"
		// so there it's an explicit cast to the function pointer type (and the parentheses are for both to have only one ifdef).
		_call = reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return reinterpret_cast<F&>(storage.data)(Death::forward<Args>(args)...);
		}));
	}
#endif

	// Non-trivially-destructible/-copyable or too large functor. MSVC 2017 has all lambdas not trivially copyable,
	// so it has to additionally check that it isn't convertible to a function pointer to avoid ambiguity with the
	// constructor taking a functor convertible to a function pointer.
	template<class R, class ...Args> template<class F, typename std::enable_if<
#if defined(DEATH_MSVC2017_COMPATIBILITY)
		!std::is_convertible<typename std::decay<F>::type, R(*)(Args...)>::value &&
#endif
		(sizeof(typename std::decay<F>::type) > sizeof(FunctionData::Storage) ||
		!std::is_trivially_copyable<typename std::decay<F>::type>::value
	), int>::type> Function<R(Args...)>::Function(std::nullptr_t, F&& f) {
		// GCC 4.8 attempts to initialize the first member instead of performing a copy if {} is used.
#if defined(DEATH_TARGET_GCC) && !defined(DEATH_TARGET_CLANG) && __GNUC__ < 5
		reinterpret_cast<typename std::decay<F>::type*&>(_storage.functor.data) = new typename std::decay<F>::type(Death::forward<F>(f));
#else
		reinterpret_cast<typename std::decay<F>::type*&>(_storage.functor.data) = new typename std::decay<F>::type{Death::forward<F>(f)};
#endif
		_storage.functor.free = [](Storage& storage) {
			delete reinterpret_cast<typename std::decay<F>::type*>(storage.functor.data);
		};
		// The + is to decay the lambda to a function pointer so we can cast it. MSVC 2015 says it's "illegal on a class"
		// so there it's an explicit cast to the function pointer type (and the parentheses are for both to have only one ifdef).
		_storage.functor.call = reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return (*reinterpret_cast<typename std::decay<F>::type*>(storage.functor.data))(Death::forward<Args>(args)...);
		}));
		// The actual call is put into _storage.functor.call and _call is nullptr in order to be able
		// to tell whether it's needed to move / delete the data pointer
		_call = nullptr;
	}

	// Member function and const, &, const & variants. There can't really be any common helper for those because passing
	// lambdas to delegated constructors is broken in MSVC 2015, losing knowledge of template parameters.
	template<class R, class ...Args> template<class Instance, class Class> Function<R(Args...)>::Function(Instance& instance, R(Class::*f)(Args...)) noexcept {
		static_assert(sizeof(f) <= sizeof(_storage.member.data),
			"Size of member function pointer is incorrectly assumed to be smaller");
		// If the pointer is null, don't save anything, not even the instance, as otherwise this would
		// get confused with a heap-allocated functor (that has nullptr _call but non-null _storage.functor.call,
		// which aliases _storage.member.instance)
		if(!f) return;

		_storage.member.instance = &instance;
		reinterpret_cast<R(Class::*&)(Args...)>(_storage.member.data) = f;
		// The + is to decay the lambda to a function pointer so we can cast it. MSVC 2015 says it's "illegal on a class"
		// so there it's an explicit cast to the function pointer type (and the parentheses are for both to have only one ifdef).
		_call = reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return (static_cast<Instance*>(storage.member.instance)->*reinterpret_cast<R(Class::*&)(Args...)>(storage.member.data))(Death::forward<Args>(args)...);
		}));
	}
	template<class R, class ...Args> template<class Instance, class Class> Function<R(Args...)>::Function(Instance& instance, R(Class::*f)(Args...) &) noexcept {
		static_assert(sizeof(f) <= sizeof(_storage.member.data),
			"Size of member function pointer is incorrectly assumed to be smaller");
		if(!f) return;

		_storage.member.instance = &instance;
		reinterpret_cast<R(Class::*&)(Args...) &>(_storage.member.data) = f;
		_call = reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return (static_cast<Instance*>(storage.member.instance)->*reinterpret_cast<R(Class::*&)(Args...) &>(storage.member.data))(Death::forward<Args>(args)...);
		}));
	}
	template<class R, class ...Args> template<class Instance, class Class> Function<R(Args...)>::Function(Instance& instance, R(Class::*f)(Args...) const) noexcept {
		static_assert(sizeof(f) <= sizeof(_storage.member.data),
			"Size of member function pointer is incorrectly assumed to be smaller");
		if(!f) return;

		_storage.member.instance = &instance;
		reinterpret_cast<R(Class::*&)(Args...) const>(_storage.member.data) = f;
		_call = reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return (static_cast<Instance*>(storage.member.instance)->*reinterpret_cast<R(Class::*&)(Args...) const>(storage.member.data))(Death::forward<Args>(args)...);
		}));
	}
	template<class R, class ...Args> template<class Instance, class Class> Function<R(Args...)>::Function(Instance& instance, R(Class::*f)(Args...) const &) noexcept {
		static_assert(sizeof(f) <= sizeof(_storage.member.data),
			"Size of member function pointer is incorrectly assumed to be smaller");
		if(!f) return;

		_storage.member.instance = &instance;
		reinterpret_cast<R(Class::*&)(Args...) const &>(_storage.member.data) = f;
		_call = reinterpret_cast<void(*)()>(
#if !defined(DEATH_MSVC2015_COMPATIBILITY)
			+
#else
			static_cast<R(*)(Storage&, Args...)>
#endif
		([](Storage& storage, Args... args) -> R {
			return (static_cast<Instance*>(storage.member.instance)->*reinterpret_cast<R(Class::*&)(Args...) const &>(storage.member.data))(Death::forward<Args>(args)...);
		}));
	}

#if defined(__cpp_deduction_guides)
	template<class Instance, class Class, class R, class ...Args>
	Function(Instance&, R(Class::*)(Args...)) -> Function<R(Args...)>;
#endif

}}