Line data Source code
1 : ///\file
2 :
3 : /******************************************************************************
4 : The MIT License(MIT)
5 :
6 : Embedded Template Library.
7 : https://github.com/ETLCPP/etl
8 : https://www.etlcpp.com
9 :
10 : Copyright(c) 2016 John Wellbelove
11 :
12 : Permission is hereby granted, free of charge, to any person obtaining a copy
13 : of this software and associated documentation files(the "Software"), to deal
14 : in the Software without restriction, including without limitation the rights
15 : to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 : copies of the Software, and to permit persons to whom the Software is
17 : furnished to do so, subject to the following conditions :
18 :
19 : The above copyright notice and this permission notice shall be included in all
20 : copies or substantial portions of the Software.
21 :
22 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 : SOFTWARE.
29 : ******************************************************************************/
30 :
31 : #ifndef ETL_UTILITY_INCLUDED
32 : #define ETL_UTILITY_INCLUDED
33 :
34 : #include "platform.h"
35 : #include "type_traits.h"
36 :
37 : #include "private/tuple_element.h"
38 : #include "private/tuple_size.h"
39 :
40 : #if defined(ETL_IN_UNIT_TEST) || ETL_USING_STL
41 : #if ETL_USING_CPP11
42 : #include <utility>
43 : #else
44 : #include <algorithm>
45 : #endif
46 : #endif
47 :
48 : ///\defgroup utility utility
49 : ///\ingroup utilities
50 :
51 : namespace etl
52 : {
53 : #if ETL_USING_CPP11
54 : //******************************************************************************
55 : template <typename T>
56 1360 : constexpr typename etl::remove_reference<T>::type&& move(T&& t) ETL_NOEXCEPT
57 : {
58 1360 : return static_cast<typename etl::remove_reference<T>::type&&>(t);
59 : }
60 :
61 : //******************************************************************************
62 : template <typename T>
63 1713 : constexpr T&& forward(typename etl::remove_reference<T>::type& t) ETL_NOEXCEPT
64 : {
65 1713 : return static_cast<T&&>(t);
66 : }
67 :
68 : template <typename T>
69 : constexpr T&& forward(typename etl::remove_reference<T>::type&& t) ETL_NOEXCEPT
70 : {
71 : ETL_STATIC_ASSERT(!etl::is_lvalue_reference<T>::value, "Invalid rvalue to lvalue conversion");
72 : return static_cast<T&&>(t);
73 : }
74 :
75 : //******************************************************************************
76 : /// See std::forward_like https://en.cppreference.com/w/cpp/utility/forward_like
77 : /// Returns a reference to x which has similar properties to T&&.
78 : ///\return
79 : /// If etl::remove_reference_t<T> is const then returns a const reference if U is an lvalue, otherwise a const rvalue reference.
80 : /// If etl::remove_reference_t<T> is not const then returns a reference if U is an lvalue, otherwise an rvalue reference.
81 : //******************************************************************************
82 : //***********************************
83 : /// T is const & lvalue.
84 : //***********************************
85 : template <typename T, typename U>
86 : ETL_NODISCARD
87 : ETL_CONSTEXPR
88 : etl::enable_if_t<etl::is_const<etl::remove_reference_t<T>>::value && etl::is_lvalue_reference<T>::value, const etl::remove_reference_t<U>&>
89 : forward_like(U&& u) ETL_NOEXCEPT
90 : {
91 : return static_cast<const etl::remove_reference_t<U>&>(u);
92 : }
93 :
94 : //***********************************
95 : /// T is const & rvalue.
96 : //***********************************
97 : template <typename T, typename U>
98 : ETL_NODISCARD
99 : ETL_CONSTEXPR
100 : etl::enable_if_t<etl::is_const<etl::remove_reference_t<T>>::value && !etl::is_lvalue_reference<T>::value, const etl::remove_reference_t<U>&&>
101 : forward_like(U&& u) ETL_NOEXCEPT
102 : {
103 : return static_cast<const etl::remove_reference_t<U>&&>(u);
104 : }
105 :
106 : //***********************************
107 : /// T is not const & lvalue.
108 : //***********************************
109 : template <typename T, typename U>
110 : ETL_NODISCARD
111 : ETL_CONSTEXPR
112 : etl::enable_if_t<!etl::is_const<etl::remove_reference_t<T>>::value && etl::is_lvalue_reference<T>::value, etl::remove_reference_t<U>&>
113 : forward_like(U&& u) ETL_NOEXCEPT
114 : {
115 : return static_cast<etl::remove_reference_t<U>&>(u);
116 : }
117 :
118 : //***********************************
119 : /// T is not const & rvalue.
120 : //***********************************
121 : template <typename T, typename U>
122 : ETL_NODISCARD
123 : ETL_CONSTEXPR
124 : etl::enable_if_t<!etl::is_const<etl::remove_reference_t<T>>::value && !etl::is_lvalue_reference<T>::value, etl::remove_reference_t<U>&&>
125 : forward_like(U&& u) ETL_NOEXCEPT
126 : {
127 : return static_cast<etl::remove_reference_t<U>&&>(u);
128 : }
129 :
130 : //***********************************
131 : // Defines the type that forward_like would cast to.
132 : //***********************************
133 : template <typename T, typename U>
134 : using forward_like_t = decltype(etl::forward_like<T>(etl::declval<U&>()));
135 : #endif
136 :
137 : //***********************************
138 : // Gets the underlying type of an enum.
139 : //***********************************
140 : template <typename T>
141 0 : ETL_CONSTEXPR typename underlying_type<T>::type to_underlying(T value) ETL_NOEXCEPT
142 : {
143 0 : return static_cast<typename underlying_type<T>::type>(value);
144 : }
145 :
146 : // We can't have std::swap and etl::swap templates coexisting in the unit tests
147 : // as the compiler will be unable to decide which one to use, due to ADL.
148 : #if ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)
149 : //***************************************************************************
150 : // swap
151 : template <typename T>
152 347 : ETL_CONSTEXPR14 void swap(T& a, T& b) ETL_NOEXCEPT
153 : {
154 347 : T temp(ETL_MOVE(a));
155 347 : a = ETL_MOVE(b);
156 347 : b = ETL_MOVE(temp);
157 347 : }
158 :
159 : template< class T, size_t Size >
160 : ETL_CONSTEXPR14 void swap(T(&a)[Size], T(&b)[Size]) ETL_NOEXCEPT
161 : {
162 : for (size_t i = 0UL; i < Size; ++i)
163 : {
164 : swap(a[i], b[i]);
165 : }
166 : }
167 : #endif
168 :
169 : //***************************************************************************
170 : ///\brief pair holds two objects of arbitrary type
171 : ///
172 : ///\tparam T1, T2 The types of the elements that the pair stores
173 : //***************************************************************************
174 : template <typename T1, typename T2>
175 : struct pair
176 : {
177 : typedef T1 first_type; ///< @c first_type is the first bound type
178 : typedef T2 second_type; ///< @c second_type is the second bound type
179 :
180 : T1 first; ///< @c first is a copy of the first object
181 : T2 second; ///< @c second is a copy of the second object
182 :
183 : //***************************************************************************
184 : ///\brief Default constructor
185 : ///
186 : /// The default constructor creates @c first and @c second using their respective default constructors.
187 : //***************************************************************************
188 : ETL_CONSTEXPR pair()
189 : : first(T1())
190 : , second(T2())
191 : {
192 : }
193 :
194 : //***************************************************************************
195 : ///\brief Constructor from parameters
196 : ///
197 : /// Two objects may be passed to a @c pair constructor to be copied.
198 : //***************************************************************************
199 : ETL_CONSTEXPR14 pair(const T1& a, const T2& b)
200 : : first(a)
201 : , second(b)
202 : {
203 : }
204 :
205 : #if ETL_USING_CPP11
206 : //***************************************************************************
207 : ///\brief Move constructor from parameters.
208 : //***************************************************************************
209 : template <typename U1, typename U2>
210 : ETL_CONSTEXPR14 pair(U1&& a, U2&& b)
211 : : first(etl::forward<U1>(a))
212 : , second(etl::forward<U2>(b))
213 : {
214 : }
215 : #endif
216 :
217 : //***************************************************************************
218 : ///\brief Copy constructor
219 : ///
220 : /// There is also a templated copy constructor for the @c pair class itself.
221 : //***************************************************************************
222 : template <typename U1, typename U2>
223 : ETL_CONSTEXPR14 pair(const pair<U1, U2>& other)
224 : : first(other.first)
225 : , second(other.second)
226 : {
227 : }
228 :
229 : /// Copy constructor
230 : pair(const pair<T1, T2>& other)
231 : : first(other.first)
232 : , second(other.second)
233 : {
234 : }
235 :
236 : #if ETL_USING_CPP11
237 : /// Move constructor
238 : template <typename U1, typename U2>
239 : ETL_CONSTEXPR14 pair(pair<U1, U2>&& other)
240 : : first(etl::forward<U1>(other.first))
241 : , second(etl::forward<U2>(other.second))
242 : {
243 : }
244 : #endif
245 :
246 : #if defined(ETL_IN_UNIT_TEST) || ETL_USING_STL
247 : /// Converting to std::pair
248 : template <typename U1, typename U2>
249 : operator std::pair<U1, U2>()
250 : {
251 : return std::make_pair(first, second);
252 : }
253 :
254 : /// Constructing from std::pair
255 : template <typename U1, typename U2>
256 : pair(const std::pair<U1, U2>& other)
257 : : first(other.first)
258 : , second(other.second)
259 : {
260 : }
261 :
262 : #if ETL_USING_CPP11
263 : /// Constructing to etl::pair
264 : template <typename U1, typename U2>
265 : pair(std::pair<U1, U2>&& other)
266 : : first(etl::forward<U1>(other.first))
267 : , second(etl::forward<U2>(other.second))
268 : {
269 : }
270 : #endif
271 : #endif
272 :
273 : void swap(pair<T1, T2>& other)
274 : {
275 : using ETL_OR_STD::swap;
276 :
277 : swap(first, other.first);
278 : swap(second, other.second);
279 : }
280 :
281 : pair<T1, T2>& operator =(const pair<T1, T2>& other)
282 : {
283 : first = other.first;
284 : second = other.second;
285 :
286 : return *this;
287 : }
288 :
289 : template <typename U1, typename U2>
290 : pair<U1, U2>& operator =(const pair<U1, U2>& other)
291 : {
292 : first = other.first;
293 : second = other.second;
294 :
295 : return *this;
296 : }
297 :
298 : #if ETL_USING_CPP11
299 : pair<T1, T2>& operator =(pair<T1, T2>&& other)
300 : {
301 : first = etl::forward<T1>(other.first);
302 : second = etl::forward<T2>(other.second);
303 :
304 : return *this;
305 : }
306 :
307 : template <typename U1, typename U2>
308 : pair<U1, U2>& operator =(pair<U1, U2>&& other)
309 : {
310 : first = etl::forward<U1>(other.first);
311 : second = etl::forward<U2>(other.second);
312 :
313 : return *this;
314 : }
315 : #endif
316 : };
317 :
318 : //***************************************************************************
319 : ///\brief A convenience wrapper for creating a @ref pair from two objects.
320 : ///
321 : ///\param a The first object.
322 : ///\param b The second object.
323 : ///
324 : ///\return A newly-constructed @ref pair object of the appropriate type.
325 : //***************************************************************************
326 : #if ETL_USING_CPP11
327 : template <typename T1, typename T2>
328 : inline pair<T1, T2> make_pair(T1&& a, T2&& b)
329 : {
330 : return pair<T1, T2>(etl::forward<T1>(a), etl::forward<T2>(b));
331 : }
332 : #else
333 : template <typename T1, typename T2>
334 : inline pair<T1, T2> make_pair(T1 a, T2 b)
335 : {
336 : return pair<T1, T2>(a, b);
337 : }
338 : #endif
339 :
340 : #if ETL_USING_CPP11
341 : //******************************************************************************
342 : template <size_t Index, typename T1, typename T2>
343 : struct tuple_element<Index, ETL_OR_STD::pair<T1, T2> >
344 : {
345 : ETL_STATIC_ASSERT(Index < 2U, "pair has only 2 elements");
346 : };
347 :
348 : template <typename T1, typename T2>
349 : struct tuple_element<0U, ETL_OR_STD::pair<T1, T2> >
350 : {
351 : typedef T1 type;
352 : };
353 :
354 : template <typename T1, typename T2>
355 : struct tuple_element<1U, ETL_OR_STD::pair<T1, T2> >
356 : {
357 : typedef T2 type;
358 : };
359 :
360 : //******************************************************************************
361 : template <typename T1, typename T2>
362 : struct tuple_size<ETL_OR_STD::pair<T1, T2>> : public etl::integral_constant<size_t, 2U>
363 : {
364 : };
365 : #endif
366 :
367 : //******************************************************************************
368 : template <typename T1, typename T2>
369 : inline void swap(pair<T1, T2>& a, pair<T1, T2>& b)
370 : {
371 : a.swap(b);
372 : }
373 :
374 : /// Two pairs of the same type are equal if their members are equal.
375 : template <typename T1, typename T2>
376 : inline bool operator ==(const pair<T1, T2>& a, const pair<T1, T2>& b)
377 : {
378 : #include "private/diagnostic_float_equal_push.h"
379 : return (a.first == b.first) && !(a.second < b.second) && !(a.second > b.second);
380 : #include "private/diagnostic_pop.h"
381 : }
382 :
383 : /// Uses @c operator== to find the result.
384 : template <typename T1, typename T2>
385 : inline bool operator !=(const pair<T1, T2>& a, const pair<T1, T2>& b)
386 : {
387 : return !(a == b);
388 : }
389 :
390 : template <typename T1, typename T2>
391 : inline bool operator <(const pair<T1, T2>& a, const pair<T1, T2>& b)
392 : {
393 : return (a.first < b.first) ||
394 : (!(b.first < a.first) && (a.second < b.second));
395 : }
396 :
397 : /// Uses @c operator< to find the result.
398 : template <typename T1, typename T2>
399 : inline bool operator >(const pair<T1, T2>& a, const pair<T1, T2>& b)
400 : {
401 : return (b < a);
402 : }
403 :
404 : /// Uses @c operator< to find the result.
405 : template <typename T1, typename T2>
406 : inline bool operator <=(const pair<T1, T2>& a, const pair<T1, T2>& b)
407 : {
408 : return !(b < a);
409 : }
410 :
411 : /// Uses @c operator< to find the result.
412 : template <typename T1, typename T2>
413 : inline bool operator >=(const pair<T1, T2>& a, const pair<T1, T2>& b)
414 : {
415 : return !(a < b);
416 : }
417 :
418 : //***************************************************************************
419 : ///\brief Functor to select @ref pair::first
420 : ///
421 : ///\ref select1st is a functor object that takes a single argument, a @ref pair, and returns the @ref pair::first element.
422 : ///
423 : ///\b Example
424 : ///\snippet test_utility.cpp test_select1st_example
425 : ///
426 : ///\tparam TPair The function object's argument type.
427 : ///
428 : ///\see select2nd
429 : //***************************************************************************
430 : template <typename TPair>
431 : struct select1st
432 : {
433 : typedef typename TPair::first_type type; ///< type of member @ref pair::first.
434 :
435 : //***************************************************************************
436 : ///\brief Function call that return @c p.first.
437 : ///\return a reference to member @ref pair::first of the @c pair `p`
438 : //***************************************************************************
439 : type& operator()(TPair& p) const
440 : {
441 : return p.first;
442 : }
443 :
444 : //***************************************************************************
445 : ///\copydoc operator()(TPair&)const
446 : //
447 : const type& operator()(const TPair& p) const
448 : {
449 : return p.first;
450 : }
451 : };
452 :
453 : //***************************************************************************
454 : ///\brief Functor to select @ref pair::second
455 : ///
456 : ///\ref select2nd is a functor object that takes a single argument, a @ref pair, and returns the @ref pair::second element.
457 : ///
458 : ///\b Example
459 : ///\snippet test_utility.cpp test_select2nd_example
460 : ///
461 : ///\tparam TPair The function object's argument type.
462 : ///
463 : ///\see select1st
464 : //***************************************************************************
465 : template <typename TPair>
466 : struct select2nd
467 : {
468 : typedef typename TPair::second_type type; ///< type of member @ref pair::second.
469 :
470 : //***************************************************************************
471 : ///\brief Function call. The return value is `p.second`.
472 : ///\return a reference to member `second` of the pair `p`.
473 : //***************************************************************************
474 : type& operator()(TPair& p) const
475 : {
476 : return p.second;
477 : }
478 :
479 : //***************************************************************************
480 : ///\copydoc operator()(TPair&)const
481 : //***************************************************************************
482 : const type& operator()(const TPair& p) const
483 : {
484 : return p.second;
485 : }
486 : };
487 :
488 : #if ETL_NOT_USING_STL || ETL_CPP14_NOT_SUPPORTED
489 : //***************************************************************************
490 : /// exchange (const)
491 : //***************************************************************************
492 : template <typename T>
493 : T exchange(T& object, const T& new_value)
494 : {
495 : T old_value = object;
496 : object = new_value;
497 : return old_value;
498 : }
499 :
500 : template <typename T, typename U>
501 : T exchange(T& object, const U& new_value)
502 : {
503 : T old_value = object;
504 : object = new_value;
505 : return old_value;
506 : }
507 : #else
508 : //***************************************************************************
509 : /// exchange (const)
510 : //***************************************************************************
511 : template <typename T, typename U = T>
512 : T exchange(T& object, const U& new_value)
513 : {
514 : return std::exchange(object, new_value);
515 : }
516 : #endif
517 :
518 : //***************************************************************************
519 : /// as_const
520 : //***************************************************************************
521 : template <typename T>
522 : typename etl::add_const<T>::type& as_const(T& t)
523 : {
524 : return t;
525 : }
526 :
527 : //***************************************************************************
528 : /// integer_sequence
529 : //***************************************************************************
530 : #if ETL_USING_CPP11
531 : template <typename T, T... Integers>
532 : class integer_sequence
533 : {
534 : public:
535 :
536 : ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral types only");
537 :
538 : typedef T value_type;
539 :
540 : static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
541 : {
542 : return sizeof...(Integers);
543 : }
544 : };
545 :
546 : namespace private_integer_sequence
547 : {
548 : template <size_t Count, typename IndexSeq>
549 : struct make_index_sequence;
550 :
551 : template <size_t Count, size_t... Indices>
552 : struct make_index_sequence<Count, etl::integer_sequence<size_t, Indices...>>
553 : {
554 : using type = typename make_index_sequence<Count - 1, etl::integer_sequence<size_t, Count - 1, Indices...>>::type;
555 : };
556 :
557 : template <size_t... Indices>
558 : struct make_index_sequence<0, etl::integer_sequence<size_t, Indices...>>
559 : {
560 : using type = etl::integer_sequence<size_t, Indices...>;
561 : };
562 : }
563 :
564 : //***********************************
565 : template <size_t Count>
566 : using make_index_sequence = typename private_integer_sequence::make_index_sequence<Count, etl::integer_sequence<size_t>>::type;
567 :
568 : template <typename... TTypes>
569 : using make_index_sequence_for = typename private_integer_sequence::make_index_sequence<sizeof...(TTypes), etl::integer_sequence<size_t>>::type;
570 :
571 : //***********************************
572 : template <size_t... Indices>
573 : using index_sequence = etl::integer_sequence<size_t, Indices...>;
574 :
575 : template <typename... TTypes>
576 : using index_sequence_for = typename etl::make_index_sequence_for<TTypes...>;
577 : #endif
578 :
579 : //***************************************************************************
580 : /// 2D coordinate type.
581 : //***************************************************************************
582 : template <typename T>
583 : struct coordinate_2d
584 : {
585 : coordinate_2d()
586 : : x(T(0))
587 : , y(T(0))
588 : {
589 : }
590 :
591 : coordinate_2d(T x_, T y_)
592 : : x(x_)
593 : , y(y_)
594 : {
595 : }
596 :
597 : friend bool operator ==(const coordinate_2d& lhs, const coordinate_2d& rhs)
598 : {
599 : return (lhs.x == rhs.x) && (lhs.y == rhs.y);
600 : }
601 :
602 : friend bool operator !=(const coordinate_2d& lhs, const coordinate_2d& rhs)
603 : {
604 : return !(lhs == rhs);
605 : }
606 :
607 : T x;
608 : T y;
609 : };
610 :
611 : //***************************************************************************
612 : /// in_place disambiguation tags.
613 : //***************************************************************************
614 :
615 : //*************************
616 : struct in_place_t
617 : {
618 : explicit ETL_CONSTEXPR in_place_t() {}
619 : };
620 :
621 : #if ETL_USING_CPP17
622 : inline constexpr in_place_t in_place{};
623 : #endif
624 :
625 : //*************************
626 : template <typename T> struct in_place_type_t
627 : {
628 : explicit ETL_CONSTEXPR in_place_type_t() {}
629 : };
630 :
631 : #if ETL_USING_CPP17
632 : template <typename T>
633 : inline constexpr in_place_type_t<T> in_place_type{};
634 : #endif
635 :
636 : //*************************
637 : template <size_t Index> struct in_place_index_t
638 : {
639 : explicit ETL_CONSTEXPR in_place_index_t() {}
640 : };
641 :
642 : #if ETL_USING_CPP17
643 : template <size_t Index>
644 : inline constexpr in_place_index_t<Index> in_place_index{};
645 : #endif
646 :
647 : #if ETL_USING_CPP11
648 : //*************************************************************************
649 : // A function wrapper for free/global functions.
650 : // Deprecated.
651 : // See etl::function_ptr_as_functor for a runtime time wrapper option.
652 : // See etl::function_as_functor for a compile time wrapper option.
653 : //*************************************************************************
654 : template <typename TReturn, typename... TParams>
655 : class ETL_DEPRECATED functor
656 : {
657 : public:
658 :
659 : //*********************************
660 : /// Constructor.
661 : //*********************************
662 : constexpr functor(TReturn(*ptr_)(TParams...))
663 : : ptr(ptr_)
664 : {
665 : }
666 :
667 : //*********************************
668 : /// Const function operator.
669 : //*********************************
670 : constexpr TReturn operator()(TParams... args) const
671 : {
672 : return ptr(etl::forward<TParams>(args)...);
673 : }
674 :
675 : private:
676 :
677 : /// The pointer to the function.
678 : TReturn(*ptr)(TParams...);
679 : };
680 :
681 : //*****************************************************************************
682 : // Wrap a member function with a static free function.
683 : // Creates a static member function that calls the specified member function.
684 : // Deprecated
685 : // See etl::member_function_as_static
686 : //*****************************************************************************
687 : template <typename T>
688 : class member_function_wrapper;
689 :
690 : template <typename TReturn, typename... TParams>
691 : class ETL_DEPRECATED member_function_wrapper<TReturn(TParams...)>
692 : {
693 : public:
694 :
695 : template <typename T, T& Instance, TReturn(T::* Method)(TParams...)>
696 : static constexpr TReturn function(TParams... params)
697 : {
698 : return (Instance.*Method)(etl::forward<TParams>(params)...);
699 : }
700 : };
701 :
702 : //*****************************************************************************
703 : // Wrap a functor with a static free function.
704 : // Creates a static member function that calls the specified functor.
705 : // Deprecated
706 : // See etl::functor_as_static
707 : //*****************************************************************************
708 : template <typename T>
709 : class functor_wrapper;
710 :
711 : template <typename TReturn, typename... TParams>
712 : class functor_wrapper<TReturn(TParams...)>
713 : {
714 : public:
715 :
716 : template <typename TFunctor, TFunctor& Instance>
717 : static constexpr TReturn function(TParams... params)
718 : {
719 : return Instance(etl::forward<TParams>(params)...);
720 : }
721 : };
722 : #endif
723 :
724 : #if ETL_USING_CPP17
725 : //*****************************************************************************
726 : // Wraps a functor with a static free function at compile time.
727 : // Creates a static member 'call' that calls the specified functor.
728 : //*****************************************************************************
729 : template <auto& Instance>
730 : struct functor_as_static
731 : {
732 : template <typename... TArgs>
733 : static constexpr auto call(TArgs&&... args)
734 : {
735 : return (Instance.operator())(etl::forward<TArgs>(args)...);
736 : }
737 : };
738 :
739 : //*****************************************************************************
740 : // Wraps a member function with a static free function at compile time.
741 : // Creates a static member 'call' that calls the specified member function.
742 : //*****************************************************************************
743 : template <auto Method, auto& Instance>
744 : struct member_function_as_static
745 : {
746 : template <typename... TArgs>
747 : static constexpr auto call(TArgs&&... args)
748 : {
749 : return (Instance.*Method)(etl::forward<TArgs>(args)...);
750 : }
751 : };
752 :
753 : //*****************************************************************************
754 : // Wraps a member function with a functor at compile time.
755 : // Creates a functor that calls the specified member function.
756 : //*****************************************************************************
757 : template <auto Method, auto& Instance>
758 : class member_function_as_functor
759 : {
760 : public:
761 :
762 : template <typename... TArgs>
763 : constexpr auto operator()(TArgs&&... args) const -> decltype((Instance.*Method)(etl::forward<TArgs>(args)...))
764 : {
765 : return (Instance.*Method)(etl::forward<TArgs>(args)...);
766 : }
767 : };
768 :
769 : //*****************************************************************************
770 : // Wraps a function with a functor at compile time.
771 : // Creates a functor that calls the specified free function.
772 : //*****************************************************************************
773 : template <auto Function>
774 : class function_as_functor
775 : {
776 : public:
777 :
778 : template<typename... TArgs>
779 : constexpr auto operator()(TArgs&&... args) const -> decltype(Function(etl::forward<TArgs>(args)...))
780 : {
781 : return Function(etl::forward<TArgs>(args)...);
782 : }
783 : };
784 : #endif
785 :
786 : #if ETL_USING_CPP11
787 : //*****************************************************************************
788 : // Wraps a function pointer with a functor at run time.
789 : // Creates a functor that calls the specified free function.
790 : //*****************************************************************************
791 : template <typename T>
792 : class function_ptr_as_functor;
793 :
794 : template <typename TReturn, typename... TArgs>
795 : class function_ptr_as_functor<TReturn(TArgs...)>
796 : {
797 : public:
798 :
799 : //*********************************
800 : /// Constructor.
801 : //*********************************
802 : constexpr function_ptr_as_functor(TReturn(*ptr_)(TArgs...))
803 : : ptr(ptr_)
804 : {
805 : }
806 :
807 : //*********************************
808 : /// Const function operator.
809 : //*********************************
810 : constexpr TReturn operator()(TArgs... args) const
811 : {
812 : return ptr(etl::forward<TArgs>(args)...);
813 : }
814 :
815 : private:
816 :
817 : /// The pointer to the function.
818 : TReturn(*ptr)(TArgs...);
819 : };
820 : #endif
821 :
822 : #if ETL_USING_CPP17 && !defined(ETL_FORCE_CPP11_NONTYPE)
823 : //*****************************************************************************
824 : // Wraps a non-type template parameter as a type.
825 : //*****************************************************************************
826 : template <auto Value>
827 : struct nontype_t
828 : {
829 : static constexpr decltype(Value) value = Value;
830 : };
831 : #elif ETL_USING_CPP11
832 : //*****************************************************************************
833 : // Wraps a non-type template parameter as a type.
834 : //*****************************************************************************
835 : template <typename T, T Value>
836 : struct nontype_t
837 : {
838 : static constexpr T value = Value;
839 : };
840 : #endif
841 : }
842 :
843 : #endif
|