1/****************************************************************************
2**
3** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
4** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
5** Copyright (C) 2020 The Qt Company Ltd.
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the QtCore module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#if 0
43#pragma qt_sync_skip_header_check
44#pragma qt_sync_stop_processing
45#endif
46
47#ifndef QCONTAINERTOOLS_IMPL_H
48#define QCONTAINERTOOLS_IMPL_H
49
50#include <QtCore/qglobal.h>
51#include <QtCore/qtypeinfo.h>
52
53#include <cstring>
54#include <iterator>
55#include <memory>
56
57QT_BEGIN_NAMESPACE
58
59namespace QtPrivate
60{
61
62template <typename T, typename N>
63void q_uninitialized_relocate_n(T* first, N n, T* out)
64{
65 if constexpr (QTypeInfo<T>::isRelocatable) {
66 if (n != N(0)) { // even if N == 0, out == nullptr or first == nullptr are UB for memmove()
67 std::memmove(static_cast<void*>(out),
68 static_cast<const void*>(first),
69 n * sizeof(T));
70 }
71 } else {
72 std::uninitialized_move_n(first, n, out);
73 if constexpr (QTypeInfo<T>::isComplex)
74 std::destroy_n(first, n);
75 }
76}
77
78
79template <typename Iterator>
80using IfIsInputIterator = typename std::enable_if<
81 std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category, std::input_iterator_tag>::value,
82 bool>::type;
83
84template <typename Iterator>
85using IfIsForwardIterator = typename std::enable_if<
86 std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>::value,
87 bool>::type;
88
89template <typename Iterator>
90using IfIsNotForwardIterator = typename std::enable_if<
91 !std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>::value,
92 bool>::type;
93
94template <typename Container,
95 typename InputIterator,
96 IfIsNotForwardIterator<InputIterator> = true>
97void reserveIfForwardIterator(Container *, InputIterator, InputIterator)
98{
99}
100
101template <typename Container,
102 typename ForwardIterator,
103 IfIsForwardIterator<ForwardIterator> = true>
104void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l)
105{
106 c->reserve(static_cast<typename Container::size_type>(std::distance(f, l)));
107}
108
109template <typename Iterator, typename = std::void_t<>>
110struct AssociativeIteratorHasKeyAndValue : std::false_type
111{
112};
113
114template <typename Iterator>
115struct AssociativeIteratorHasKeyAndValue<
116 Iterator,
117 std::void_t<decltype(std::declval<Iterator &>().key()),
118 decltype(std::declval<Iterator &>().value())>
119 >
120 : std::true_type
121{
122};
123
124template <typename Iterator, typename = std::void_t<>, typename = std::void_t<>>
125struct AssociativeIteratorHasFirstAndSecond : std::false_type
126{
127};
128
129template <typename Iterator>
130struct AssociativeIteratorHasFirstAndSecond<
131 Iterator,
132 std::void_t<decltype(std::declval<Iterator &>()->first),
133 decltype(std::declval<Iterator &>()->second)>
134 >
135 : std::true_type
136{
137};
138
139template <typename Iterator>
140using IfAssociativeIteratorHasKeyAndValue =
141 typename std::enable_if<AssociativeIteratorHasKeyAndValue<Iterator>::value, bool>::type;
142
143template <typename Iterator>
144using IfAssociativeIteratorHasFirstAndSecond =
145 typename std::enable_if<AssociativeIteratorHasFirstAndSecond<Iterator>::value, bool>::type;
146
147template <typename T, typename U>
148using IfIsNotSame =
149 typename std::enable_if<!std::is_same<T, U>::value, bool>::type;
150} // namespace QtPrivate
151
152QT_END_NAMESPACE
153
154#endif // QCONTAINERTOOLS_IMPL_H
155