source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ d275344

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d275344 was d275344, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: fixed passing references to bind without std::ref or std::cref, now they are not modified and the user needs to use the aforementioned functions

  • Property mode set to 100644
File size: 40.9 KB
RevLine 
[e679283]1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_FUNCTIONAL
30#define LIBCPP_FUNCTIONAL
31
[22ba300]32#include <limits>
[9c00022]33#include <memory>
34#include <typeinfo>
[e679283]35#include <type_traits>
[22ba300]36#include <utility>
[9f77d98]37
[e679283]38namespace std
39{
40 namespace aux
41 {
42 /**
43 * 20.9.2, requirements:
44 */
45 template<class R, class T, class T1, class... Ts>
[22ba300]46 decltype(auto) invoke(R T::* f, T1&& t1, Ts&&... args)
[e679283]47 {
48 if constexpr (is_member_function_pointer_v<decltype(f)>)
49 {
50 if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
51 // (1.1)
[22ba300]52 return (t1.*f)(forward<Ts>(args)...);
[e679283]53 else
54 // (1.2)
[22ba300]55 return ((*t1).*f)(forward<Ts>(args)...);
[e679283]56 }
[22ba300]57 else if constexpr (is_member_object_pointer_v<decltype(f)> && sizeof...(args) == 0)
[e679283]58 {
59 /**
60 * Note: Standard requires to N be equal to 1, but we take t1 directly
61 * so we need sizeof...(args) to be 0.
62 */
63 if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
64 // (1.3)
65 return t1.*f;
66 else
67 // (1.4)
68 return (*t1).*f;
69 }
[22ba300]70
71 /**
72 * Note: If this condition holds this will not be reachable,
73 * but a new addition to the standard (17.7 point (8.1))
74 * prohibits us from simply using false as the condition here,
75 * so we use this because we know it is false here.
76 */
77 static_assert(is_member_function_pointer_v<decltype(f)>, "invalid invoke");
[e679283]78 }
79
80 template<class F, class... Args>
81 decltype(auto) invoke(F&& f, Args&&... args)
82 {
83 // (1.5)
84 return f(forward<Args>(args)...);
85 }
86 }
87
88 /**
89 * 20.9.3, invoke:
90 */
91
92 template<class F, class... Args>
93 result_of_t<F&&(Args&&...)> invoke(F&& f, Args&&... args)
94 {
95 return aux::invoke(forward<F>(f)(forward<Args>(args)...));
96 }
97
98 /**
99 * 20.9.4, reference_wrapper:
100 */
101
102 template<class T>
[65dde99]103 class reference_wrapper
104 {
105 public:
106 using type = T;
107 // TODO: conditional typedefs
108
109 reference_wrapper(type& val) noexcept
110 : data_{&val}
111 { /* DUMMY BODY */ }
112
113 reference_wrapper(type&&) = delete;
114
115 reference_wrapper(const reference_wrapper& other) noexcept
116 : data_{other.data_}
117 { /* DUMMY BODY */ }
118
119 reference_wrapper& operator=(const reference_wrapper& other) noexcept
120 {
121 data_ = other.data_;
122
123 return *this;
124 }
125
126 operator type&() const noexcept
127 {
128 return *data_;
129 }
130
131 type& get() const noexcept
132 {
133 return *data_;
134 }
135
136 template<class... Args>
137 result_of_t<type&(Args&&...)> operator()(Args&&... args) const
138 {
139 return invoke(*data_, std::forward<Args>(args)...);
140 }
141
142 private:
143 type* data_;
144 };
[e679283]145
146 template<class T>
[65dde99]147 reference_wrapper<T> ref(T& t) noexcept
148 {
149 return reference_wrapper<T>{t};
150 }
[e679283]151
152 template<class T>
[65dde99]153 reference_wrapper<const T> cref(const T& t) noexcept
154 {
155 return reference_wrapper<const T>{t};
156 }
[e679283]157
158 template<class T>
159 void ref(const T&&) = delete;
160
161 template<class T>
162 void cref(const T&&) = delete;
163
164 template<class T>
[65dde99]165 reference_wrapper<T> ref(reference_wrapper<T> t) noexcept
166 {
167 return ref(t.get());
168 }
[e679283]169
170 template<class T>
[65dde99]171 reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept
172 {
173 return cref(t.get());
174 }
[e679283]175
176 /**
177 * 20.9.5, arithmetic operations:
178 */
179
180 template<class T = void>
181 struct plus
182 {
183 constexpr T operator()(const T& lhs, const T& rhs) const
184 {
185 return lhs + rhs;
186 }
187
188 using first_argument_type = T;
189 using second_argument_type = T;
190 using result_type = T;
191 };
192
193 template<class T = void>
194 struct minus
195 {
196 constexpr T operator()(const T& lhs, const T& rhs) const
197 {
198 return lhs - rhs;
199 }
200
201 using first_argument_type = T;
202 using second_argument_type = T;
203 using result_type = T;
204 };
205
206 template<class T = void>
207 struct multiplies
208 {
209 constexpr T operator()(const T& lhs, const T& rhs) const
210 {
211 return lhs * rhs;
212 }
213
214 using first_argument_type = T;
215 using second_argument_type = T;
216 using result_type = T;
217 };
218
219 template<class T = void>
220 struct divides
221 {
222 constexpr T operator()(const T& lhs, const T& rhs) const
223 {
224 return lhs / rhs;
225 }
226
227 using first_argument_type = T;
228 using second_argument_type = T;
229 using result_type = T;
230 };
231
232 template<class T = void>
233 struct modulus
234 {
235 constexpr T operator()(const T& lhs, const T& rhs) const
236 {
237 return lhs % rhs;
238 }
239
240 using first_argument_type = T;
241 using second_argument_type = T;
242 using result_type = T;
243 };
244
245 template<class T = void>
246 struct negate
247 {
248 constexpr T operator()(const T& x) const
249 {
250 return -x;
251 }
252
253 using argument_type = T;
254 using result_type = T;
255 };
256
257 namespace aux
258 {
259 /**
260 * Used by some functions like std::set::find to determine
261 * whether a functor is transparent.
262 */
263 struct transparent_t;
[8830faa]264
265 template<class T, class = void>
266 struct is_transparent: false_type
267 { /* DUMMY BODY */ };
268
269 template<class T>
270 struct is_transparent<T, void_t<typename T::is_transparent>>
271 : true_type
272 { /* DUMMY BODY */ };
273
274 template<class T>
275 inline constexpr bool is_transparent_v = is_transparent<T>::value;
[e679283]276 }
277
278 template<>
279 struct plus<void>
280 {
281 template<class T, class U>
[22ba300]282 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]283 -> decltype(forward<T>(lhs) + forward<U>(rhs))
284 {
285 return forward<T>(lhs) + forward<T>(rhs);
286 }
287
288 using is_transparent = aux::transparent_t;
289 };
290
291 template<>
292 struct minus<void>
293 {
294 template<class T, class U>
[22ba300]295 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]296 -> decltype(forward<T>(lhs) - forward<U>(rhs))
297 {
298 return forward<T>(lhs) - forward<T>(rhs);
299 }
300
301 using is_transparent = aux::transparent_t;
302 };
303
304 template<>
305 struct multiplies<void>
306 {
307 template<class T, class U>
[22ba300]308 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]309 -> decltype(forward<T>(lhs) * forward<U>(rhs))
310 {
311 return forward<T>(lhs) * forward<T>(rhs);
312 }
313
314 using is_transparent = aux::transparent_t;
315 };
316
317 template<>
318 struct divides<void>
319 {
320 template<class T, class U>
[22ba300]321 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]322 -> decltype(forward<T>(lhs) / forward<U>(rhs))
323 {
324 return forward<T>(lhs) / forward<T>(rhs);
325 }
326
327 using is_transparent = aux::transparent_t;
328 };
329
330 template<>
331 struct modulus<void>
332 {
333 template<class T, class U>
[22ba300]334 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]335 -> decltype(forward<T>(lhs) % forward<U>(rhs))
336 {
337 return forward<T>(lhs) % forward<T>(rhs);
338 }
339
340 using is_transparent = aux::transparent_t;
341 };
342
343 template<>
344 struct negate<void>
345 {
346 template<class T>
[22ba300]347 constexpr auto operator()(T&& x) const
[e679283]348 -> decltype(-forward<T>(x))
349 {
350 return -forward<T>(x);
351 }
352
353 using is_transparent = aux::transparent_t;
354 };
355
356 /**
357 * 20.9.6, comparisons:
358 */
359
360 template<class T = void>
[22ba300]361 struct equal_to
[e679283]362 {
363 constexpr bool operator()(const T& lhs, const T& rhs) const
364 {
365 return lhs == rhs;
366 }
367
368 using first_argument_type = T;
369 using second_argument_type = T;
370 using result_type = bool;
371 };
372
373 template<class T = void>
374 struct not_equal_to
375 {
376 constexpr bool operator()(const T& lhs, const T& rhs) const
377 {
378 return lhs != rhs;
379 }
380
381 using first_argument_type = T;
382 using second_argument_type = T;
383 using result_type = bool;
384 };
385
386 template<class T = void>
387 struct greater
388 {
389 constexpr bool operator()(const T& lhs, const T& rhs) const
390 {
391 return lhs > rhs;
392 }
393
394 using first_argument_type = T;
395 using second_argument_type = T;
396 using result_type = bool;
397 };
398
399 template<class T = void>
400 struct less
401 {
402 constexpr bool operator()(const T& lhs, const T& rhs) const
403 {
404 return lhs < rhs;
405 }
406
407 using first_argument_type = T;
408 using second_argument_type = T;
409 using result_type = bool;
410 };
411
412 template<class T = void>
413 struct greater_equal
414 {
415 constexpr bool operator()(const T& lhs, const T& rhs) const
416 {
417 return lhs >= rhs;
418 }
419
420 using first_argument_type = T;
421 using second_argument_type = T;
422 using result_type = bool;
423 };
424
425 template<class T = void>
426 struct less_equal
427 {
428 constexpr bool operator()(const T& lhs, const T& rhs) const
429 {
430 return lhs <= rhs;
431 }
432
433 using first_argument_type = T;
434 using second_argument_type = T;
435 using result_type = bool;
436 };
437
438 template<>
439 struct equal_to<void>
440 {
441 template<class T, class U>
[22ba300]442 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]443 -> decltype(forward<T>(lhs) == forward<U>(rhs))
444 {
445 return forward<T>(lhs) == forward<U>(rhs);
446 }
447
448 using is_transparent = aux::transparent_t;
449 };
450
451 template<>
452 struct not_equal_to<void>
453 {
454 template<class T, class U>
[22ba300]455 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]456 -> decltype(forward<T>(lhs) != forward<U>(rhs))
457 {
458 return forward<T>(lhs) != forward<U>(rhs);
459 }
460
461 using is_transparent = aux::transparent_t;
462 };
463
464 template<>
465 struct greater<void>
466 {
467 template<class T, class U>
[22ba300]468 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]469 -> decltype(forward<T>(lhs) > forward<U>(rhs))
470 {
471 return forward<T>(lhs) > forward<U>(rhs);
472 }
473
474 using is_transparent = aux::transparent_t;
475 };
476
477 template<>
478 struct less<void>
479 {
480 template<class T, class U>
[22ba300]481 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]482 -> decltype(forward<T>(lhs) < forward<U>(rhs))
483 {
484 return forward<T>(lhs) < forward<U>(rhs);
485 }
486
487 using is_transparent = aux::transparent_t;
488 };
489
490 template<>
491 struct greater_equal<void>
492 {
493 template<class T, class U>
[22ba300]494 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]495 -> decltype(forward<T>(lhs) >= forward<U>(rhs))
496 {
497 return forward<T>(lhs) >= forward<U>(rhs);
498 }
499
500 using is_transparent = aux::transparent_t;
501 };
502
503 template<>
504 struct less_equal<void>
505 {
506 template<class T, class U>
[22ba300]507 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]508 -> decltype(forward<T>(lhs) <= forward<U>(rhs))
509 {
510 return forward<T>(lhs) <= forward<U>(rhs);
511 }
512
513 using is_transparent = aux::transparent_t;
514 };
515
516 /**
517 * 20.9.7, logical operations:
518 */
519
520 template<class T = void>
521 struct logical_and
522 {
523 constexpr bool operator()(const T& lhs, const T& rhs) const
524 {
525 return lhs && rhs;
526 }
527
528 using first_argument_type = T;
529 using second_argument_type = T;
530 using result_type = bool;
531 };
532
533 template<class T = void>
534 struct logical_or
535 {
536 constexpr bool operator()(const T& lhs, const T& rhs) const
537 {
538 return lhs || rhs;
539 }
540
541 using first_argument_type = T;
542 using second_argument_type = T;
543 using result_type = bool;
544 };
545
546 template<class T = void>
547 struct logical_not
548 {
549 constexpr bool operator()(const T& x) const
550 {
551 return !x;
552 }
553
554 using argument_type = T;
555 using result_type = bool;
556 };
557
558 template<>
559 struct logical_and<void>
560 {
561 template<class T, class U>
[22ba300]562 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]563 -> decltype(forward<T>(lhs) && forward<U>(rhs))
564 {
565 return forward<T>(lhs) && forward<U>(rhs);
566 }
567
568 using is_transparent = aux::transparent_t;
569 };
570
571 template<>
572 struct logical_or<void>
573 {
574 template<class T, class U>
[22ba300]575 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]576 -> decltype(forward<T>(lhs) || forward<U>(rhs))
577 {
578 return forward<T>(lhs) || forward<U>(rhs);
579 }
580
581 using is_transparent = aux::transparent_t;
582 };
583
584 template<>
585 struct logical_not<void>
586 {
587 template<class T>
[22ba300]588 constexpr auto operator()(T&& x) const
[e679283]589 -> decltype(!forward<T>(x))
590 {
[22ba300]591 return !forward<T>(x);
[e679283]592 }
593
594 using is_transparent = aux::transparent_t;
595 };
596
597 /**
598 * 20.9.8, bitwise operations:
599 */
600
601 template<class T = void>
602 struct bit_and
603 {
604 constexpr T operator()(const T& lhs, const T& rhs) const
605 {
606 return lhs & rhs;
607 }
608
609 using first_argument_type = T;
610 using second_argument_type = T;
611 using result_type = T;
612 };
613
614 template<class T = void>
615 struct bit_or
616 {
617 constexpr T operator()(const T& lhs, const T& rhs) const
618 {
619 return lhs | rhs;
620 }
621
622 using first_argument_type = T;
623 using second_argument_type = T;
624 using result_type = T;
625 };
626
627 template<class T = void>
628 struct bit_xor
629 {
630 constexpr T operator()(const T& lhs, const T& rhs) const
631 {
632 return lhs ^ rhs;
633 }
634
635 using first_argument_type = T;
636 using second_argument_type = T;
637 using result_type = T;
638 };
639
640 template<class T = void>
641 struct bit_not
642 {
643 constexpr bool operator()(const T& x) const
644 {
645 return ~x;
646 }
647
648 using argument_type = T;
649 using result_type = T;
650 };
651
652 template<>
653 struct bit_and<void>
654 {
655 template<class T, class U>
[22ba300]656 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]657 -> decltype(forward<T>(lhs) & forward<U>(rhs))
658 {
659 return forward<T>(lhs) & forward<U>(rhs);
660 }
661
662 using is_transparent = aux::transparent_t;
663 };
664
665 template<>
666 struct bit_or<void>
667 {
668 template<class T, class U>
[22ba300]669 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]670 -> decltype(forward<T>(lhs) | forward<U>(rhs))
671 {
672 return forward<T>(lhs) | forward<U>(rhs);
673 }
674
675 using is_transparent = aux::transparent_t;
676 };
677
678 template<>
679 struct bit_xor<void>
680 {
681 template<class T, class U>
[22ba300]682 constexpr auto operator()(T&& lhs, U&& rhs) const
[e679283]683 -> decltype(forward<T>(lhs) ^ forward<U>(rhs))
684 {
685 return forward<T>(lhs) ^ forward<U>(rhs);
686 }
687
688 using is_transparent = aux::transparent_t;
689 };
690
691 template<>
692 struct bit_not<void>
693 {
694 template<class T>
[22ba300]695 constexpr auto operator()(T&& x) const
[e679283]696 -> decltype(~forward<T>(x))
697 {
[22ba300]698 return ~forward<T>(x);
[e679283]699 }
700
701 using is_transparent = aux::transparent_t;
702 };
703
704 /**
705 * 20.9.9, negators:
706 */
707
708 template<class Predicate>
[0a414494]709 class unary_negate
710 {
711 public:
712 using result_type = bool;
713 using argument_type = typename Predicate::argument_type;
714
715 constexpr explicit unary_negate(const Predicate& pred)
716 : pred_{pred}
717 { /* DUMMY BODY */ }
718
719 constexpr result_type operator()(const argument_type& arg)
720 {
721 return !pred_(arg);
722 }
723
724 private:
725 Predicate pred_;
726 };
[e679283]727
728 template<class Predicate>
[0a414494]729 constexpr unary_negate<Predicate> not1(const Predicate& pred)
730 {
731 return unary_negate<Predicate>{pred};
732 }
[e679283]733
734 template<class Predicate>
[0a414494]735 class binary_negate
736 {
737 public:
738 using result_type = bool;
739 using first_argument_type = typename Predicate::first_argument_type;
740 using second_argument_type = typename Predicate::second_argument_type;
741
742 constexpr explicit binary_negate(const Predicate& pred)
743 : pred_{pred}
744 { /* DUMMY BODY */ }
745
746 constexpr result_type operator()(const first_argument_type& arg1,
747 const second_argument_type& arg2)
748 {
749 return !pred_(arg1, arg2);
750 }
751
752 private:
753 Predicate pred_;
754 };
[e679283]755
756 template<class Predicate>
757 constexpr binary_negate<Predicate> not2(const Predicate& pred);
758
759 /**
760 * 20.9.12, polymorphic function adaptors:
761 */
762
[9c00022]763 namespace aux
764 {
765 // TODO: fix this
766 /* template<class, class T, class... Args> */
767 /* struct is_callable_impl: false_type */
768 /* { /1* DUMMY BODY *1/ }; */
769
770 /* template<class, class R, class... Args> */
771 /* struct is_callable_impl< */
772 /* void_t<decltype(aux::invoke(declval<R(Args...)>(), declval<Args>()..., R))>, */
773 /* R, Args... */
774 /* > : true_type */
775 /* { /1* DUMMY BODY *1/ }; */
776
777 /* template<class T> */
778 /* struct is_callable: is_callable_impl<void_t<>, T> */
779 /* { /1* DUMMY BODY *1/ }; */
780
781 template<class Callable, class R, class... Args>
782 R invoke_callable(Callable* clbl, Args&&... args)
783 {
784 return (*clbl)(forward<Args>(args)...);
785 }
786
787 template<class Callable>
788 void copy_callable(Callable* to, Callable* from)
789 {
790 new(to) Callable{*from};
791 }
792
793 template<class Callable>
794 void destroy_callable(Callable* clbl)
795 {
796 if (clbl)
797 clbl->~Callable();
798 }
799 }
800
[a30c04d]801 // TODO: implement
[e679283]802 class bad_function_call;
803
804 template<class>
805 class function; // undefined
806
[9c00022]807 /**
808 * Note: Ideally, this implementation wouldn't
809 * copy the target if it was a pointer to
810 * a function, but for the simplicity of the
811 * implementation, we do copy even in that
812 * case for now. It would be a nice optimization
813 * if this was changed in the future.
814 */
[e679283]815 template<class R, class... Args>
[9c00022]816 class function<R(Args...)>
817 {
818 public:
819 using result_type = R;
820 // TODO: conditional typedefs
821
822 /**
823 * 20.9.12.2.1, construct/copy/destroy:
824 */
825
826 function() noexcept
827 : callable_{}, callable_size_{}, call_{},
828 copy_{}, dest_{}
829 { /* DUMMY BODY */ }
830
831 function(nullptr_t) noexcept
832 : function{}
833 { /* DUMMY BODY */ }
834
835 function(const function& other)
836 : callable_{}, callable_size_{other.callable_size_},
837 call_{other.call_}, copy_{other.copy_}, dest_{other.dest_}
838 {
839 callable_ = new uint8_t[callable_size_];
840 (*copy_)(callable_, other.callable_);
841 }
842
843 function(function&& other)
844 : callable_{other.callable_}, callable_size_{other.callable_size_},
845 call_{other.call_}, copy_{other.copy_}, dest_{other.dest_}
846 {
847 other.callable_ = nullptr;
848 other.callable_size_ = size_t{};
849 other.call_ = nullptr;
850 other.copy_ = nullptr;
851 other.dest_ = nullptr;
852 }
853
854 // TODO: shall not participate in overloading unless aux::is_callable<F>
855 template<class F>
856 function(F f)
857 : callable_{}, callable_size_{sizeof(F)},
858 call_{(call_t)aux::invoke_callable<F, R, Args...>},
859 copy_{(copy_t)aux::copy_callable<F>},
860 dest_{(dest_t)aux::destroy_callable<F>}
861 {
862 callable_ = new uint8_t[callable_size_];
863 (*copy_)(callable_, (uint8_t*)&f);
864 }
865
866 /**
867 * Note: For the moment we're ignoring the allocator
868 * for simplicity of the implementation.
869 */
870
871 template<class A>
872 function(allocator_arg_t, const A& a) noexcept
873 : function{}
874 { /* DUMMY BODY */ }
875
876 template<class A>
877 function(allocator_arg_t, const A& a, nullptr_t) noexcept
878 : function{}
879 { /* DUMMY BODY */ }
880
881 template<class A>
882 function(allocator_arg_t, const A& a, const function& other)
883 : function{other}
884 { /* DUMMY BODY */ }
885
886 template<class A>
887 function(allocator_arg_t, const A& a, function&& other)
888 : function{move(other)}
889 { /* DUMMY BODY */ }
890
891 // TODO: shall not participate in overloading unless aux::is_callable<F>
892 template<class F, class A>
893 function(allocator_arg_t, const A& a, F f)
894 : function{f}
895 { /* DUMMY BODY */ }
896
897 function& operator=(const function& rhs)
898 {
899 function{rhs}.swap(*this);
900
901 return *this;
902 }
903
904 /**
905 * Note: We have to copy call_, copy_
906 * and dest_ because they can be templated
907 * by a type F we don't know.
908 */
909 function& operator=(function&& rhs)
910 {
911 clear_();
912
913 callable_ = rhs.callable_;
914 callable_size_ = rhs.callable_size_;
915 call_ = rhs.call_;
916 copy_ = rhs.copy_;
917 dest_ = rhs.dest_;
918
919 rhs.callable_ = nullptr;
920 rhs.callable_size_ = size_t{};
921 rhs.call_ = nullptr;
922 rhs.copy_ = nullptr;
923 rhs.dest_ = nullptr;
924
925 return *this;
926 }
927
928 function& operator=(nullptr_t) noexcept
929 {
930 clear_();
931
932 return *this;
933 }
934
935 // TODO: shall not participate in overloading unless aux::is_callable<F>
936 template<class F>
937 function& operator=(F&& f)
938 {
939 callable_size_ = sizeof(F);
940 callable_ = new uint8_t[callable_size_];
941 call_ = aux::invoke_callable<F, R, Args...>;
942 copy_ = aux::copy_callable<F>;
943 dest_ = aux::destroy_callable<F>;
944
945 (*copy_)(callable_, (uint8_t*)&f);
946 }
947
948 template<class F>
949 function& operator=(reference_wrapper<F> ref) noexcept
950 {
951 return (*this) = ref.get();
952 }
953
954 ~function()
955 {
956 if (callable_)
957 {
958 (*dest_)(callable_);
959 delete[] callable_;
960 }
961 }
962
963 /**
964 * 20.9.12.2.2, function modifiers:
965 */
966
967 void swap(function& other) noexcept
968 {
969 std::swap(callable_, other.callable_);
970 std::swap(callable_size_, other.callable_size_);
971 std::swap(call_, other.call_);
972 std::swap(copy_, other.copy_);
973 std::swap(dest_, other.dest_);
974 }
975
976 template<class F, class A>
977 void assign(F&& f, const A& a)
978 {
979 function{allocator_arg, a, forward<F>(f)}.swap(*this);
980 }
981
982 /**
983 * 20.9.12.2.3, function capacity:
984 */
985
986 explicit operator bool() const noexcept
987 {
988 return callable_ != nullptr;
989 }
990
991 /**
992 * 20.9.12.2.4, function invocation:
993 */
994
995 result_type operator()(Args... args) const
996 {
997 // TODO: throw bad_function_call if !callable_ || !call_
998 if constexpr (is_same_v<R, void>)
999 (*call_)(callable_, forward<Args>(args)...);
1000 else
1001 return (*call_)(callable_, forward<Args>(args)...);
1002 }
1003
1004 /**
1005 * 20.9.12.2.5, function target access:
1006 */
1007
1008 const type_info& target_type() const noexcept
1009 {
1010 return typeid(*callable_);
1011 }
1012
1013 template<class T>
1014 T* target() noexcept
1015 {
1016 if (target_type() == typeid(T))
1017 return (T*)callable_;
1018 else
1019 return nullptr;
1020 }
1021
1022 template<class T>
1023 const T* target() const noexcept
1024 {
1025 if (target_type() == typeid(T))
1026 return (T*)callable_;
1027 else
1028 return nullptr;
1029 }
1030
1031 private:
1032 using call_t = R(*)(uint8_t*, Args&&...);
1033 using copy_t = void (*)(uint8_t*, uint8_t*);
1034 using dest_t = void (*)(uint8_t*);
1035
1036 uint8_t* callable_;
1037 size_t callable_size_;
1038 call_t call_;
1039 copy_t copy_;
1040 dest_t dest_;
1041
1042 void clear_()
1043 {
1044 if (callable_)
1045 {
1046 (*dest_)(callable_);
1047 delete[] callable_;
1048 callable_ = nullptr;
1049 }
1050 }
1051 };
1052
1053 /**
1054 * 20.9.12.2.6, null pointer comparisons:
1055 */
[e679283]1056
1057 template<class R, class... Args>
[9c00022]1058 bool operator==(const function<R(Args...)>& f, nullptr_t) noexcept
1059 {
1060 return !f;
1061 }
[e679283]1062
1063 template<class R, class... Args>
[9c00022]1064 bool operator==(nullptr_t, const function<R(Args...)>& f) noexcept
1065 {
1066 return !f;
1067 }
[e679283]1068
1069 template<class R, class... Args>
[9c00022]1070 bool operator!=(const function<R(Args...)>& f, nullptr_t) noexcept
1071 {
1072 return (bool)f;
1073 }
[e679283]1074
1075 template<class R, class... Args>
[9c00022]1076 bool operator!=(nullptr_t, const function<R(Args...)>& f) noexcept
1077 {
1078 return (bool)f;
1079 }
[e679283]1080
[55540fca]1081 /**
1082 * 20.9.12.2.7, specialized algorithms:
1083 */
1084
1085 template<class R, class... Args>
1086 void swap(function<R(Args...)>& f1, function<R(Args...)>& f2)
1087 {
1088 f1.swap(f2);
1089 }
1090
1091 template<class R, class... Args, class Alloc>
1092 struct uses_allocator<function<R(Args...)>, Alloc>
1093 : true_type
1094 { /* DUMMY BODY */ };
1095
[a30c04d]1096 /**
1097 * 20.9.10, bind:
1098 */
1099
1100 namespace aux
1101 {
1102 template<int N>
1103 struct placeholder_t
1104 {
1105 constexpr placeholder_t() = default;
[d275344]1106 constexpr placeholder_t(const placeholder_t&) = default;
1107 constexpr placeholder_t(placeholder_t&&) = default;
[a30c04d]1108 };
1109 }
1110
1111 template<class T>
1112 struct is_placeholder: integral_constant<int, 0>
1113 { /* DUMMY BODY */ };
1114
1115 template<int N> // Note: const because they are all constexpr.
1116 struct is_placeholder<const aux::placeholder_t<N>>
1117 : integral_constant<int, N>
1118 { /* DUMMY BODY */ };
1119
1120 template<class T>
1121 inline constexpr int is_placeholder_v = is_placeholder<T>::value;
1122
1123 namespace aux
1124 {
[800968b7]1125 template<class F, class... Args>
1126 class bind_t;
1127
[d275344]1128 /**
1129 * Filter class that uses its overloaded operator[]
1130 * to filter our placeholders, reference_wrappers and bind
1131 * subexpressions and replace them with the correct
1132 * arguments (extracts references, calls the subexpressions etc).
1133 */
[a30c04d]1134 template<class... Args>
1135 class bind_arg_filter
1136 {
1137 public:
1138 bind_arg_filter(Args&&... args)
1139 : args_{forward<Args>(args)...}
1140 { /* DUMMY BODY */ }
1141
1142 template<class T>
1143 constexpr decltype(auto) operator[](T&& t)
[d275344]1144 {
[a30c04d]1145 return forward<T>(t);
1146 }
1147
1148 template<int N>
1149 constexpr decltype(auto) operator[](const placeholder_t<N>)
[800968b7]1150 { // Since placeholders are constexpr, this is the best match for them.
[a30c04d]1151 /**
1152 * Come on, it's int! Why not use -1 as not placeholder
1153 * and start them at 0? -.-
1154 */
1155 return get<N - 1>(args_);
1156 }
1157
[800968b7]1158 template<class T>
1159 constexpr T& operator[](reference_wrapper<T> ref)
1160 {
1161 return ref.get();
1162 }
1163
1164 template<class F, class... BindArgs>
1165 constexpr decltype(auto) operator[](const bind_t<F, BindArgs...> b)
1166 {
1167 return b; // TODO: bind subexpressions
1168 }
1169
[a30c04d]1170
1171 private:
1172 tuple<Args...> args_;
1173 };
1174
1175 template<class F, class... Args>
1176 class bind_t
1177 {
1178 // TODO: conditional typedefs
1179 public:
[d275344]1180 template<class G, class... BoundArgs>
1181 constexpr bind_t(G&& g, BoundArgs&&... args)
1182 : func_{forward<F>(g)},
1183 bound_args_{forward<Args>(args)...}
[a30c04d]1184 { /* DUMMY BODY */ }
1185
[800968b7]1186 constexpr bind_t(const bind_t& other) = default;
1187 constexpr bind_t(bind_t&& other) = default;
1188
[a30c04d]1189 template<class... ActualArgs>
1190 constexpr decltype(auto) operator()(ActualArgs&&... args)
1191 {
1192 return invoke_(
1193 make_index_sequence<sizeof...(Args)>{},
1194 forward<ActualArgs>(args)...
1195 );
1196 }
1197
1198 private:
1199 function<decay_t<F>> func_;
[d275344]1200 tuple<decay_t<Args>...> bound_args_;
[a30c04d]1201
1202 template<size_t... Is, class... ActualArgs>
1203 constexpr decltype(auto) invoke_(
1204 index_sequence<Is...>, ActualArgs&&... args
1205 )
1206 {
[d275344]1207 /**
1208 * The expression filter[bound_args_[bind_arg_index<Is>()]]...
1209 * here expands bind_arg_index to 0, 1, ... sizeof...(ActualArgs) - 1
1210 * and then passes this variadic list of indices to the bound_args_
1211 * tuple which extracts the bound args from it.
1212 * Our filter will then have its operator[] called on each of them
1213 * and filter out the placeholders, reference_wrappers etc and changes
1214 * them to the actual arguments.
1215 */
[a30c04d]1216 bind_arg_filter<ActualArgs...> filter{forward<ActualArgs>(args)...};
1217
1218 return invoke(
1219 func_,
[d275344]1220 filter[get<Is>(bound_args_)]...
[a30c04d]1221 );
1222 }
1223 };
1224 }
1225
1226 template<class T>
1227 struct is_bind_expression: false_type
1228 { /* DUMMY BODY */ };
1229
1230 template<class F, class... Args>
1231 struct is_bind_expression<aux::bind_t<F, Args...>>
1232 : true_type
1233 { /* DUMMY BODY */ };
1234
1235 template<class F, class... Args>
1236 aux::bind_t<F, Args...> bind(F&& f, Args&&... args)
1237 {
1238 return aux::bind_t<F, Args...>{forward<F>(f), forward<Args>(args)...};
1239 }
1240
1241 template<class R, class F, class... Args>
[d275344]1242 aux::bind_t<F, Args...> bind(F&& f, Args&&... args)
1243 {
1244 // TODO: this one should have a result_type typedef equal to R
1245 return aux::bind_t<F, Args...>{forward<F>(f), forward<Args>(args)...};
1246 }
[a30c04d]1247
1248 namespace placeholders
1249 {
1250 /**
1251 * Note: The number of placeholders is
1252 * implementation defined, we've chosen
1253 * 8 because it is a nice number
1254 * and should be enough for any function
1255 * call.
1256 * Note: According to the C++14 standard, these
1257 * are all extern non-const. We decided to use
1258 * the C++17 form of them being inline constexpr
1259 * because it is more convenient, makes sense
1260 * and would eventually need to be upgraded
1261 * anyway.
1262 */
1263 inline constexpr aux::placeholder_t<1> _1;
1264 inline constexpr aux::placeholder_t<2> _2;
1265 inline constexpr aux::placeholder_t<3> _3;
1266 inline constexpr aux::placeholder_t<4> _4;
1267 inline constexpr aux::placeholder_t<5> _5;
1268 inline constexpr aux::placeholder_t<6> _6;
1269 inline constexpr aux::placeholder_t<7> _7;
1270 inline constexpr aux::placeholder_t<8> _8;
1271 }
1272
1273 /**
1274 * 20.9.11, member function adaptors:
1275 */
1276
1277 namespace aux
1278 {
1279 template<class F>
1280 class mem_fn_t
1281 {
1282 // TODO: conditional typedefs
1283 public:
1284 mem_fn_t(F f)
1285 : func_{f}
1286 { /* DUMMY BODY */ }
1287
1288 template<class... Args>
1289 decltype(auto) operator()(Args&&... args)
1290 {
1291 return invoke(func_, forward<Args>(args)...);
1292 }
1293
1294 private:
1295 F func_;
1296 };
1297 }
1298
1299 template<class R, class T>
1300 aux::mem_fn_t<R T::*> mem_fn(R T::* f)
1301 {
1302 return aux::mem_fn_t<R T::*>{f};
1303 }
1304
[e679283]1305 /**
1306 * 20.9.13, hash function primary template:
1307 */
1308
[22ba300]1309 namespace aux
1310 {
1311 template<class T>
1312 union converter
1313 {
1314 T value;
1315 uint64_t converted;
1316 };
1317
1318 template<class T>
1319 T hash_(uint64_t x) noexcept
1320 {
[5ae8168]1321 /**
1322 * Note: std::hash is used for indexing in
1323 * unordered containers, not for cryptography.
1324 * Because of this, we decided to simply convert
1325 * the value to uin64_t, which will help us
1326 * with testing (since in order to create
1327 * a collision in a multiset or multimap
1328 * we simply need 2 values that congruent
1329 * by the size of the table.
1330 */
1331 return static_cast<T>(x);
[22ba300]1332 }
1333
1334 template<class T>
1335 size_t hash(T x) noexcept
1336 {
1337 static_assert(is_arithmetic_v<T> || is_pointer_v<T>,
1338 "invalid type passed to aux::hash");
1339
1340 converter<T> conv;
1341 conv.value = x;
1342
1343 return hash_<size_t>(conv.converted);
1344 }
1345 }
1346
[e679283]1347 template<class T>
[9f77d98]1348 struct hash
1349 { /* DUMMY BODY */ };
[e679283]1350
1351 template<>
[9f77d98]1352 struct hash<bool>
1353 {
1354 size_t operator()(bool x) const noexcept
1355 {
[22ba300]1356 return aux::hash(x);
[9f77d98]1357 }
1358
1359 using argument_type = bool;
1360 using result_type = size_t;
1361 };
[e679283]1362
1363 template<>
[9f77d98]1364 struct hash<char>
1365 {
1366 size_t operator()(char x) const noexcept
1367 {
[22ba300]1368 return aux::hash(x);
[9f77d98]1369 }
1370
1371 using argument_type = char;
1372 using result_type = size_t;
1373 };
[e679283]1374
1375 template<>
[9f77d98]1376 struct hash<signed char>
1377 {
1378 size_t operator()(signed char x) const noexcept
1379 {
[22ba300]1380 return aux::hash(x);
[9f77d98]1381 }
1382
1383 using argument_type = signed char;
1384 using result_type = size_t;
1385 };
[e679283]1386
1387 template<>
[9f77d98]1388 struct hash<unsigned char>
1389 {
1390 size_t operator()(unsigned char x) const noexcept
1391 {
[22ba300]1392 return aux::hash(x);
[9f77d98]1393 }
1394
1395 using argument_type = unsigned char;
1396 using result_type = size_t;
1397 };
[e679283]1398
1399 template<>
[9f77d98]1400 struct hash<char16_t>
1401 {
1402 size_t operator()(char16_t x) const noexcept
1403 {
[22ba300]1404 return aux::hash(x);
[9f77d98]1405 }
1406
1407 using argument_type = char16_t;
1408 using result_type = size_t;
1409 };
[e679283]1410
1411 template<>
[9f77d98]1412 struct hash<char32_t>
1413 {
1414 size_t operator()(char32_t x) const noexcept
1415 {
[22ba300]1416 return aux::hash(x);
[9f77d98]1417 }
1418
1419 using argument_type = char32_t;
1420 using result_type = size_t;
1421 };
[e679283]1422
1423 template<>
[9f77d98]1424 struct hash<wchar_t>
1425 {
1426 size_t operator()(wchar_t x) const noexcept
1427 {
[22ba300]1428 return aux::hash(x);
[9f77d98]1429 }
1430
1431 using argument_type = wchar_t;
1432 using result_type = size_t;
1433 };
[e679283]1434
1435 template<>
[9f77d98]1436 struct hash<short>
1437 {
1438 size_t operator()(short x) const noexcept
1439 {
[22ba300]1440 return aux::hash(x);
[9f77d98]1441 }
1442
1443 using argument_type = short;
1444 using result_type = size_t;
1445 };
[e679283]1446
1447 template<>
[9f77d98]1448 struct hash<unsigned short>
1449 {
1450 size_t operator()(unsigned short x) const noexcept
1451 {
[22ba300]1452 return aux::hash(x);
[9f77d98]1453 }
1454
1455 using argument_type = unsigned short;
1456 using result_type = size_t;
1457 };
[e679283]1458
1459 template<>
[9f77d98]1460 struct hash<int>
1461 {
1462 size_t operator()(int x) const noexcept
1463 {
[22ba300]1464 return aux::hash(x);
[9f77d98]1465 }
1466
1467 using argument_type = int;
1468 using result_type = size_t;
1469 };
[e679283]1470
1471 template<>
[9f77d98]1472 struct hash<unsigned int>
1473 {
1474 size_t operator()(unsigned int x) const noexcept
1475 {
[22ba300]1476 return aux::hash(x);
[9f77d98]1477 }
1478
1479 using argument_type = unsigned int;
1480 using result_type = size_t;
1481 };
[e679283]1482
1483 template<>
[9f77d98]1484 struct hash<long>
1485 {
1486 size_t operator()(long x) const noexcept
1487 {
[22ba300]1488 return aux::hash(x);
[9f77d98]1489 }
1490
1491 using argument_type = long;
1492 using result_type = size_t;
1493 };
[e679283]1494
1495 template<>
[9f77d98]1496 struct hash<long long>
1497 {
1498 size_t operator()(long long x) const noexcept
1499 {
[22ba300]1500 return aux::hash(x);
[9f77d98]1501 }
1502
1503 using argument_type = long long;
1504 using result_type = size_t;
1505 };
[e679283]1506
1507 template<>
[9f77d98]1508 struct hash<unsigned long>
1509 {
1510 size_t operator()(unsigned long x) const noexcept
1511 {
[22ba300]1512 return aux::hash(x);
[9f77d98]1513 }
1514
1515 using argument_type = unsigned long;
1516 using result_type = size_t;
1517 };
[e679283]1518
1519 template<>
[9f77d98]1520 struct hash<unsigned long long>
1521 {
1522 size_t operator()(unsigned long long x) const noexcept
1523 {
[22ba300]1524 return aux::hash(x);
[9f77d98]1525 }
1526
1527 using argument_type = unsigned long long;
1528 using result_type = size_t;
1529 };
[e679283]1530
1531 template<>
[9f77d98]1532 struct hash<float>
1533 {
1534 size_t operator()(float x) const noexcept
1535 {
[22ba300]1536 return aux::hash(x);
[9f77d98]1537 }
1538
1539 using argument_type = float;
1540 using result_type = size_t;
1541 };
[e679283]1542
1543 template<>
[22ba300]1544 struct hash<double>
[9f77d98]1545 {
1546 size_t operator()(double x) const noexcept
1547 {
[22ba300]1548 return aux::hash(x);
[9f77d98]1549 }
1550
1551 using argument_type = double;
1552 using result_type = size_t;
1553 };
[e679283]1554
1555 template<>
[22ba300]1556 struct hash<long double>
[9f77d98]1557 {
1558 size_t operator()(long double x) const noexcept
1559 {
[22ba300]1560 return aux::hash(x);
[9f77d98]1561 }
1562
1563 using argument_type = long double;
1564 using result_type = size_t;
1565 };
[e679283]1566
1567 template<class T>
[9f77d98]1568 struct hash<T*>
1569 {
1570 size_t operator()(T* x) const noexcept
1571 {
[22ba300]1572 return aux::hash(x);
[9f77d98]1573 }
1574
1575 using argument_type = T*;
1576 using result_type = size_t;
1577 };
[e679283]1578}
1579
1580#endif
Note: See TracBrowser for help on using the repository browser.