1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #pragma once
27 
28 #include "predicates.h"
29 #include "optional.h"
30 
31 #include <qcompilerdetection.h> // for Q_REQUIRED_RESULT
32 
33 #include <algorithm>
34 #include <map>
35 #include <memory>
36 #include <set>
37 #include <tuple>
38 #include <unordered_map>
39 #include <unordered_set>
40 
41 #include <QObject>
42 #include <QStringList>
43 
44 #include <memory>
45 
46 namespace Utils
47 {
48 
49 //////////////////
50 // anyOf
51 /////////////////
52 template<typename T, typename F>
anyOf(const T & container,F predicate)53 bool anyOf(const T &container, F predicate)
54 {
55     return std::any_of(std::begin(container), std::end(container), predicate);
56 }
57 
58 // anyOf taking a member function pointer
59 template<typename T, typename R, typename S>
anyOf(const T & container,R (S::* predicate)()const)60 bool anyOf(const T &container, R (S::*predicate)() const)
61 {
62     return std::any_of(std::begin(container), std::end(container), std::mem_fn(predicate));
63 }
64 
65 // anyOf taking a member pointer
66 template<typename T, typename R, typename S>
anyOf(const T & container,R S::* member)67 bool anyOf(const T &container, R S::*member)
68 {
69     return std::any_of(std::begin(container), std::end(container), std::mem_fn(member));
70 }
71 
72 
73 //////////////////
74 // count
75 /////////////////
76 template<typename T, typename F>
count(const T & container,F predicate)77 int count(const T &container, F predicate)
78 {
79     return std::count_if(std::begin(container), std::end(container), predicate);
80 }
81 
82 //////////////////
83 // allOf
84 /////////////////
85 template<typename T, typename F>
allOf(const T & container,F predicate)86 bool allOf(const T &container, F predicate)
87 {
88     return std::all_of(std::begin(container), std::end(container), predicate);
89 }
90 
91 //////////////////
92 // erase
93 /////////////////
94 template<typename T, typename F>
erase(T & container,F predicate)95 void erase(T &container, F predicate)
96 {
97     container.erase(std::remove_if(std::begin(container), std::end(container), predicate),
98                     std::end(container));
99 }
100 
101 
102 //////////////////
103 // contains
104 /////////////////
105 template<typename T, typename F>
contains(const T & container,F function)106 bool contains(const T &container, F function)
107 {
108     return anyOf(container, function);
109 }
110 
111 template<typename T, typename R, typename S>
contains(const T & container,R (S::* function)()const)112 bool contains(const T &container, R (S::*function)() const)
113 {
114     return anyOf(container, function);
115 }
116 
117 template<typename C, typename R, typename S>
contains(const C & container,R S::* member)118 bool contains(const C &container, R S::*member)
119 {
120     return anyOf(container, std::mem_fn(member));
121 }
122 
123 //////////////////
124 // findOr
125 /////////////////
126 template<typename C, typename F>
127 Q_REQUIRED_RESULT
findOr(const C & container,typename C::value_type other,F function)128 typename C::value_type findOr(const C &container, typename C::value_type other, F function)
129 {
130     typename C::const_iterator begin = std::begin(container);
131     typename C::const_iterator end = std::end(container);
132 
133     typename C::const_iterator it = std::find_if(begin, end, function);
134     return it == end ? other : *it;
135 }
136 
137 template<typename T, typename R, typename S>
138 Q_REQUIRED_RESULT
findOr(const T & container,typename T::value_type other,R (S::* function)()const)139 typename T::value_type findOr(const T &container, typename T::value_type other, R (S::*function)() const)
140 {
141     return findOr(container, other, std::mem_fn(function));
142 }
143 
144 template<typename T, typename R, typename S>
145 Q_REQUIRED_RESULT
findOr(const T & container,typename T::value_type other,R S::* member)146 typename T::value_type findOr(const T &container, typename T::value_type other, R S::*member)
147 {
148     return findOr(container, other, std::mem_fn(member));
149 }
150 
151 //////////////////
152 // findOrDefault
153 //////////////////
154 // Default implementation:
155 template<typename C, typename F>
156 Q_REQUIRED_RESULT
157 typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value, typename C::value_type>
findOrDefault(const C & container,F function)158 findOrDefault(const C &container, F function)
159 {
160     return findOr(container, typename C::value_type(), function);
161 }
162 
163 template<typename C, typename R, typename S>
164 Q_REQUIRED_RESULT
165 typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value, typename C::value_type>
findOrDefault(const C & container,R (S::* function)()const)166 findOrDefault(const C &container, R (S::*function)() const)
167 {
168     return findOr(container, typename C::value_type(), std::mem_fn(function));
169 }
170 
171 template<typename C, typename R, typename S>
172 Q_REQUIRED_RESULT
173 typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value, typename C::value_type>
findOrDefault(const C & container,R S::* member)174 findOrDefault(const C &container, R S::*member)
175 {
176     return findOr(container, typename C::value_type(), std::mem_fn(member));
177 }
178 
179 //////////////////
180 // index of:
181 //////////////////
182 
183 template<typename C, typename F>
184 Q_REQUIRED_RESULT
indexOf(const C & container,F function)185 int indexOf(const C& container, F function)
186 {
187     typename C::const_iterator begin = std::begin(container);
188     typename C::const_iterator end = std::end(container);
189 
190     typename C::const_iterator it = std::find_if(begin, end, function);
191     return it == end ? -1 : std::distance(begin, it);
192 }
193 
194 
195 //////////////////
196 // max element
197 //////////////////
198 
199 template<typename T>
maxElementOr(const T & container,typename T::value_type other)200 typename T::value_type maxElementOr(const T &container, typename T::value_type other)
201 {
202     typename T::const_iterator begin = std::begin(container);
203     typename T::const_iterator end = std::end(container);
204 
205     typename T::const_iterator it = std::max_element(begin, end);
206     if (it == end)
207         return other;
208     return *it;
209 }
210 
211 
212 //////////////////
213 // transform
214 /////////////////
215 
216 namespace {
217 /////////////////
218 // helper code for transform to use back_inserter and thus push_back for everything
219 // and insert for QSet<>
220 //
221 
222 // SetInsertIterator, straight from the standard for insert_iterator
223 // just without the additional parameter to insert
224 template <class Container>
225   class SetInsertIterator :
226     public std::iterator<std::output_iterator_tag,void,void,void,void>
227 {
228 protected:
229   Container *container;
230 
231 public:
232   typedef Container container_type;
SetInsertIterator(Container & x)233   explicit SetInsertIterator (Container &x)
234     : container(&x) {}
235   SetInsertIterator<Container> &operator=(const typename Container::value_type &value)
236     { container->insert(value); return *this; }
237   SetInsertIterator<Container> &operator= (typename Container::value_type &&value)
238     { container->insert(std::move(value)); return *this; }
239   SetInsertIterator<Container >&operator*()
240     { return *this; }
241   SetInsertIterator<Container> &operator++()
242     { return *this; }
243   SetInsertIterator<Container> operator++(int)
244     { return *this; }
245 };
246 
247 // for QMap / QHash, inserting a std::pair / QPair
248 template <class Container>
249     class MapInsertIterator :
250       public std::iterator<std::output_iterator_tag,void,void,void,void>
251   {
252   protected:
253     Container *container;
254 
255   public:
256     typedef Container container_type;
MapInsertIterator(Container & x)257     explicit MapInsertIterator (Container &x)
258       : container(&x) {}
259     MapInsertIterator<Container> &operator=(const std::pair<const typename Container::key_type, typename Container::mapped_type> &value)
260       { container->insert(value.first, value.second); return *this; }
261     MapInsertIterator<Container> &operator=(const QPair<typename Container::key_type, typename Container::mapped_type> &value)
262       { container->insert(value.first, value.second); return *this; }
263     MapInsertIterator<Container >&operator*()
264       { return *this; }
265     MapInsertIterator<Container> &operator++()
266       { return *this; }
267     MapInsertIterator<Container> operator++(int)
268       { return *this; }
269   };
270 
271 // inserter helper function, returns a std::back_inserter for most containers
272 // and is overloaded for QSet<> and other containers without push_back, returning custom inserters
273 template<typename C>
274 inline std::back_insert_iterator<C>
inserter(C & container)275 inserter(C &container)
276 {
277     return std::back_inserter(container);
278 }
279 
280 template<typename X>
281 inline SetInsertIterator<QSet<X>>
inserter(QSet<X> & container)282 inserter(QSet<X> &container)
283 {
284     return SetInsertIterator<QSet<X>>(container);
285 }
286 
287 template<typename K, typename C, typename A>
288 inline SetInsertIterator<std::set<K, C, A>>
inserter(std::set<K,C,A> & container)289 inserter(std::set<K, C, A> &container)
290 {
291     return SetInsertIterator<std::set<K, C, A>>(container);
292 }
293 
294 template<typename K, typename H, typename C, typename A>
295 inline SetInsertIterator<std::unordered_set<K, H, C, A>>
inserter(std::unordered_set<K,H,C,A> & container)296 inserter(std::unordered_set<K, H, C, A> &container)
297 {
298     return SetInsertIterator<std::unordered_set<K, H, C, A>>(container);
299 }
300 
301 template<typename K, typename V, typename C, typename A>
302 inline SetInsertIterator<std::map<K, V, C, A>>
inserter(std::map<K,V,C,A> & container)303 inserter(std::map<K, V, C, A> &container)
304 {
305     return SetInsertIterator<std::map<K, V, C, A>>(container);
306 }
307 
308 template<typename K, typename V, typename H, typename C, typename A>
309 inline SetInsertIterator<std::unordered_map<K, V, H, C, A>>
inserter(std::unordered_map<K,V,H,C,A> & container)310 inserter(std::unordered_map<K, V, H, C, A> &container)
311 {
312     return SetInsertIterator<std::unordered_map<K, V, H, C, A>>(container);
313 }
314 
315 template<typename K, typename V>
316 inline MapInsertIterator<QMap<K, V>>
inserter(QMap<K,V> & container)317 inserter(QMap<K, V> &container)
318 {
319     return MapInsertIterator<QMap<K, V>>(container);
320 }
321 
322 template<typename K, typename V>
323 inline MapInsertIterator<QHash<K, V>>
inserter(QHash<K,V> & container)324 inserter(QHash<K, V> &container)
325 {
326     return MapInsertIterator<QHash<K, V>>(container);
327 }
328 
329 // Helper code for container.reserve that makes it possible to effectively disable it for
330 // specific cases
331 
332 // default: do reserve
333 // Template arguments are more specific than the second version below, so this is tried first
334 template<template<typename...> class C, typename... CArgs,
335          typename = decltype(&C<CArgs...>::reserve)>
reserve(C<CArgs...> & c,typename C<CArgs...>::size_type s)336 void reserve(C<CArgs...> &c, typename C<CArgs...>::size_type s)
337 {
338     c.reserve(s);
339 }
340 
341 // containers that don't have reserve()
342 template<typename C>
reserve(C &,typename C::size_type)343 void reserve(C &, typename C::size_type) { }
344 
345 } // anonymous
346 
347 // --------------------------------------------------------------------
348 // Different containers for input and output:
349 // --------------------------------------------------------------------
350 
351 // different container types for input and output, e.g. transforming a QList into a QSet
352 
353 // function without result type deduction:
354 template<typename ResultContainer, // complete result container type
355          typename SC, // input container type
356          typename F> // function type
357 Q_REQUIRED_RESULT
decltype(auto)358 decltype(auto) transform(SC &&container, F function)
359 {
360     ResultContainer result;
361     reserve(result, typename ResultContainer::size_type(container.size()));
362     std::transform(std::begin(container), std::end(container), inserter(result), function);
363     return result;
364 }
365 
366 // function with result type deduction:
367 template<template<typename> class C, // result container type
368          typename SC, // input container type
369          typename F, // function type
370          typename Value = typename std::decay_t<SC>::value_type,
371          typename Result = std::decay_t<std::result_of_t<F(Value&)>>,
372          typename ResultContainer = C<Result>>
373 Q_REQUIRED_RESULT
decltype(auto)374 decltype(auto) transform(SC &&container, F function)
375 {
376     return transform<ResultContainer>(std::forward<SC>(container), function);
377 }
378 
379 template<template<typename, typename> class C, // result container type
380          typename SC, // input container type
381          typename F, // function type
382          typename Value = typename std::decay_t<SC>::value_type,
383          typename Result = std::decay_t<std::result_of_t<F(Value&)>>,
384          typename ResultContainer = C<Result, std::allocator<Result>>>
385 Q_REQUIRED_RESULT
decltype(auto)386 decltype(auto) transform(SC &&container, F function)
387 {
388     return transform<ResultContainer>(std::forward<SC>(container), function);
389 }
390 
391 // member function without result type deduction:
392 template<template<typename...> class C, // result container type
393          typename SC, // input container type
394          typename R,
395          typename S>
396 Q_REQUIRED_RESULT
decltype(auto)397 decltype(auto) transform(SC &&container, R (S::*p)() const)
398 {
399     return transform<C>(std::forward<SC>(container), std::mem_fn(p));
400 }
401 
402 // member function with result type deduction:
403 template<typename ResultContainer, // complete result container type
404          typename SC, // input container type
405          typename R,
406          typename S>
407 Q_REQUIRED_RESULT
decltype(auto)408 decltype(auto) transform(SC &&container, R (S::*p)() const)
409 {
410     return transform<ResultContainer>(std::forward<SC>(container), std::mem_fn(p));
411 }
412 
413 // member without result type deduction:
414 template<typename ResultContainer, // complete result container type
415          typename SC, // input container
416          typename R,
417          typename S>
418 Q_REQUIRED_RESULT
decltype(auto)419 decltype(auto) transform(SC &&container, R S::*p)
420 {
421     return transform<ResultContainer>(std::forward<SC>(container), std::mem_fn(p));
422 }
423 
424 // member with result type deduction:
425 template<template<typename...> class C, // result container
426          typename SC, // input container
427          typename R,
428          typename S>
429 Q_REQUIRED_RESULT
decltype(auto)430 decltype(auto) transform(SC &&container, R S::*p)
431 {
432     return transform<C>(std::forward<SC>(container), std::mem_fn(p));
433 }
434 
435 // same container types for input and output, const input
436 
437 // function:
438 template<template<typename...> class C, // container type
439          typename F, // function type
440          typename... CArgs> // Arguments to SC
441 Q_REQUIRED_RESULT
decltype(auto)442 decltype(auto) transform(const C<CArgs...> &container, F function)
443 {
444     return transform<C, const C<CArgs...> &>(container, function);
445 }
446 
447 // member function:
448 template<template<typename...> class C, // container type
449          typename R,
450          typename S,
451          typename... CArgs> // Arguments to SC
452 Q_REQUIRED_RESULT
decltype(auto)453 decltype(auto) transform(const C<CArgs...> &container, R (S::*p)() const)
454 {
455     return transform<C, const C<CArgs...> &>(container, std::mem_fn(p));
456 }
457 
458 // members:
459 template<template<typename...> class C, // container
460          typename R,
461          typename S,
462          typename... CArgs> // Arguments to SC
463 Q_REQUIRED_RESULT
decltype(auto)464 decltype(auto) transform(const C<CArgs...> &container, R S::*p)
465 {
466     return transform<C, const C<CArgs...> &>(container, std::mem_fn(p));
467 }
468 
469 // same container types for input and output, non-const input
470 
471 // function:
472 template<template<typename...> class C, // container type
473          typename F, // function type
474          typename... CArgs> // Arguments to SC
475 Q_REQUIRED_RESULT
decltype(auto)476 decltype(auto) transform(C<CArgs...> &container, F function)
477 {
478     return transform<C, C<CArgs...> &>(container, function);
479 }
480 
481 // member function:
482 template<template<typename...> class C, // container type
483          typename R,
484          typename S,
485          typename... CArgs> // Arguments to SC
486 Q_REQUIRED_RESULT
decltype(auto)487 decltype(auto) transform(C<CArgs...> &container, R (S::*p)() const)
488 {
489     return transform<C, C<CArgs...> &>(container, std::mem_fn(p));
490 }
491 
492 // members:
493 template<template<typename...> class C, // container
494          typename R,
495          typename S,
496          typename... CArgs> // Arguments to SC
497 Q_REQUIRED_RESULT
decltype(auto)498 decltype(auto) transform(C<CArgs...> &container, R S::*p)
499 {
500     return transform<C, C<CArgs...> &>(container, std::mem_fn(p));
501 }
502 
503 // Specialization for QStringList:
504 
505 template<template<typename...> class C = QList, // result container
506          typename F> // Arguments to C
507 Q_REQUIRED_RESULT
decltype(auto)508 decltype(auto) transform(const QStringList &container, F function)
509 {
510     return transform<C, const QList<QString> &>(static_cast<QList<QString>>(container), function);
511 }
512 
513 // member function:
514 template<template<typename...> class C = QList, // result container type
515          typename R,
516          typename S>
517 Q_REQUIRED_RESULT
decltype(auto)518 decltype(auto) transform(const QStringList &container, R (S::*p)() const)
519 {
520     return transform<C, const QList<QString> &>(static_cast<QList<QString>>(container), std::mem_fn(p));
521 }
522 
523 // members:
524 template<template<typename...> class C = QList, // result container
525          typename R,
526          typename S>
527 Q_REQUIRED_RESULT
decltype(auto)528 decltype(auto) transform(const QStringList &container, R S::*p)
529 {
530     return transform<C, const QList<QString> &>(static_cast<QList<QString>>(container), std::mem_fn(p));
531 }
532 
533 //////////////////
534 // filtered
535 /////////////////
536 template<typename C, typename F>
537 Q_REQUIRED_RESULT
filtered(const C & container,F predicate)538 C filtered(const C &container, F predicate)
539 {
540     C out;
541     std::copy_if(std::begin(container), std::end(container),
542                  inserter(out), predicate);
543     return out;
544 }
545 
546 template<typename C, typename R, typename S>
547 Q_REQUIRED_RESULT
filtered(const C & container,R (S::* predicate)()const)548 C filtered(const C &container, R (S::*predicate)() const)
549 {
550     C out;
551     std::copy_if(std::begin(container), std::end(container),
552                  inserter(out), std::mem_fn(predicate));
553     return out;
554 }
555 
556 //////////////////
557 // partition
558 /////////////////
559 
560 // Recommended usage:
561 // C hit;
562 // C miss;
563 // std::tie(hit, miss) = Utils::partition(container, predicate);
564 
565 template<typename C, typename F>
566 Q_REQUIRED_RESULT
partition(const C & container,F predicate)567 std::tuple<C, C> partition(const C &container, F predicate)
568 {
569     C hit;
570     C miss;
571     auto hitIns = inserter(hit);
572     auto missIns = inserter(miss);
573     for (auto i : container) {
574         if (predicate(i))
575             hitIns = i;
576         else
577             missIns = i;
578     }
579     return std::make_tuple(hit, miss);
580 }
581 
582 template<typename C, typename R, typename S>
583 Q_REQUIRED_RESULT
partition(const C & container,R (S::* predicate)()const)584 std::tuple<C, C> partition(const C &container, R (S::*predicate)() const)
585 {
586     return partition(container, std::mem_fn(predicate));
587 }
588 
589 //////////////////
590 // filteredUnique
591 /////////////////
592 
593 template<typename C>
594 Q_REQUIRED_RESULT
filteredUnique(const C & container)595 C filteredUnique(const C &container)
596 {
597     C result;
598     auto ins = inserter(result);
599 
600     QSet<typename C::value_type> seen;
601     int setSize = 0;
602 
603     auto endIt = std::end(container);
604     for (auto it = std::begin(container); it != endIt; ++it) {
605         seen.insert(*it);
606         if (setSize == seen.size()) // unchanged size => was already seen
607             continue;
608         ++setSize;
609         ins = *it;
610     }
611     return result;
612 }
613 
614 //////////////////
615 // qobject_container_cast
616 /////////////////
617 template <class T, template<typename> class Container, typename Base>
qobject_container_cast(const Container<Base> & container)618 Container<T> qobject_container_cast(const Container<Base> &container)
619 {
620     Container<T> result;
621     auto ins = inserter(result);
622     for (Base val : container) {
623         if (T target = qobject_cast<T>(val))
624             ins = target;
625     }
626     return result;
627 }
628 
629 //////////////////
630 // sort
631 /////////////////
632 template <typename Container>
sort(Container & container)633 inline void sort(Container &container)
634 {
635     std::sort(std::begin(container), std::end(container));
636 }
637 
638 template <typename Container, typename Predicate>
sort(Container & container,Predicate p)639 inline void sort(Container &container, Predicate p)
640 {
641     std::sort(std::begin(container), std::end(container), p);
642 }
643 
644 // pointer to member
645 template <typename Container, typename R, typename S>
sort(Container & container,R S::* member)646 inline void sort(Container &container, R S::*member)
647 {
648     auto f = std::mem_fn(member);
649     using const_ref = typename Container::const_reference;
650     std::sort(std::begin(container), std::end(container),
651               [&f](const_ref a, const_ref b) {
652         return f(a) < f(b);
653     });
654 }
655 
656 // pointer to member function
657 template <typename Container, typename R, typename S>
sort(Container & container,R (S::* function)()const)658 inline void sort(Container &container, R (S::*function)() const)
659 {
660     auto f = std::mem_fn(function);
661     using const_ref = typename Container::const_reference;
662     std::sort(std::begin(container), std::end(container),
663               [&f](const_ref a, const_ref b) {
664         return f(a) < f(b);
665     });
666 }
667 
668 //////////////////
669 // reverseForeach
670 /////////////////
671 template <typename Container, typename Op>
reverseForeach(const Container & c,const Op & operation)672 inline void reverseForeach(const Container &c, const Op &operation)
673 {
674     auto rend = c.rend();
675     for (auto it = c.rbegin(); it != rend; ++it)
676         operation(*it);
677 }
678 
679 //////////////////
680 // toReferences
681 /////////////////
682 template <template<typename...> class ResultContainer,
683           typename SourceContainer>
toReferences(SourceContainer & sources)684 auto toReferences(SourceContainer &sources)
685 {
686     return transform<ResultContainer>(sources, [] (auto &value) { return std::ref(value); });
687 }
688 
689 template <typename SourceContainer>
toReferences(SourceContainer & sources)690 auto toReferences(SourceContainer &sources)
691 {
692     return transform(sources, [] (auto &value) { return std::ref(value); });
693 }
694 
695 //////////////////
696 // toConstReferences
697 /////////////////
698 template <template<typename...> class ResultContainer,
699           typename SourceContainer>
toConstReferences(const SourceContainer & sources)700 auto toConstReferences(const SourceContainer &sources)
701 {
702     return transform<ResultContainer>(sources, [] (const auto &value) { return std::cref(value); });
703 }
704 
705 template <typename SourceContainer>
toConstReferences(const SourceContainer & sources)706 auto toConstReferences(const SourceContainer &sources)
707 {
708     return transform(sources, [] (const auto &value) { return std::cref(value); });
709 }
710 
711 //////////////////
712 // take:
713 /////////////////
714 
715 template<class C, typename P>
take(C & container,P predicate)716 Q_REQUIRED_RESULT Utils::optional<typename C::value_type> take(C &container, P predicate)
717 {
718     const auto end = std::end(container);
719 
720     const auto it = std::find_if(std::begin(container), end, predicate);
721     if (it == end)
722         return Utils::nullopt;
723 
724     Utils::optional<typename C::value_type> result = Utils::make_optional(std::move(*it));
725     container.erase(it);
726     return result;
727 }
728 
729 // pointer to member
730 template <typename C, typename R, typename S>
decltype(auto)731 Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member)
732 {
733     return take(container, std::mem_fn(member));
734 }
735 
736 // pointer to member function
737 template <typename C, typename R, typename S>
decltype(auto)738 Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const)
739 {
740     return take(container, std::mem_fn(function));
741 }
742 
743 } // namespace Utils
744