summaryrefslogtreecommitdiff
path: root/src/inc/clr_std/utility
blob: fa2267578ed5c2313a16db58dc574188d036cc6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//
// clr_std/utility
//
// Copy of some key Standard Template Library functionality
// See http://msdn.microsoft.com/en-us/library/bb982077.aspx for documentation.
//

#ifdef _MSC_VER
#pragma once
#endif

#ifdef USE_STL
#include <utility>
#else
#ifndef __clr_std_utility_h__
#define __clr_std_utility_h__

#include "clr_std/type_traits"

namespace std
{
    //-----------------------------------------------------------------------------------------
    // TEMPLATE FUNCTION move
    template<class T> inline
    typename remove_reference<T>::type&&
    move(T&& arg)
    {   // forward _Arg as movable
        return ((typename remove_reference<T>::type&&)arg);
    }

    //-----------------------------------------------------------------------------------------
    // TEMPLATE FUNCTION swap (from <algorithm>)
    template<class T> inline
    void swap(T& left, T& right)
    {   // exchange values stored at left and right
        T tmp = std::move(left);
        left = std::move(right);
        right = std::move(tmp);
    }

    //-----------------------------------------------------------------------------------------
    // TEMPLATE FUNCTION forward
    template<class T> inline
    T&&
    forward(typename identity<T>::type& _Arg)
    {   // forward _Arg, given explicitly specified type parameter
        return ((T&&)_Arg);
    }
}

namespace std
{
    //-----------------------------------------------------------------------------------------
    // TEMPLATE STRUCT pair
    template<class _Ty1, class _Ty2>
    struct pair
    {   // store a pair of values
        typedef pair<_Ty1, _Ty2> _Myt;
        typedef _Ty1 first_type;
        typedef _Ty2 second_type;

        pair()
            : first(_Ty1()), second(_Ty2())
        {   // construct from defaults
        }

        pair(const _Ty1& _Val1, const _Ty2& _Val2)
            : first(_Val1.first), second(_Val2.second)
        {   // construct from specified values
        }

        template<class _Other1, class _Other2>
        pair(pair<_Other1, _Other2>& _Right)
            : first(_Right.first), second(_Right.second)
        {   // construct from compatible pair
        }

        template<class _Other1, class _Other2>
        pair(const pair<_Other1, _Other2>& _Right)
            : first(_Right.first), second(_Right.second)
        {   // construct from compatible pair
        }

        void swap(_Myt& _Right)
        {   // exchange contents with _Right
            if (this != &_Right)
            {   // different, worth swapping
                swap(this->first, _Right.first);
                swap(this->second, _Right.second);
            }
        }

        _Myt& operator=(const _Myt& _Right)
        {   // assign from copied pair
            this->first = _Right.first;
            this->second = _Right.second;
            return (*this);
        }

        typedef typename remove_reference<_Ty1>::type _Ty1x;
        typedef typename remove_reference<_Ty2>::type _Ty2x;

        pair(_Ty1x&& _Val1, _Ty2x&& _Val2)
            : first(std::move(_Val1)),
              second(std::move(_Val2))
        {   // construct from specified values
        }

        pair(const _Ty1x& _Val1, _Ty2x&& _Val2)
            : first(_Val1),
              second(std::move(_Val2))
        {   // construct from specified values
        }

        pair(_Ty1x&& _Val1, const _Ty2x& _Val2)
            : first(std::move(_Val1)),
              second(_Val2)
        {   // construct from specified values
        }

        template<class _Other1, class _Other2>
        pair(_Other1&& _Val1, _Other2&& _Val2)
            : first(std::move(_Val1)),
              second(std::move(_Val2))
        {   // construct from moved values
        }

        template<class _Other1, class _Other2>
        pair(pair<_Other1, _Other2>&& _Right)
            : first(std::move(_Right.first)),
              second(std::move(_Right.second))
        {   // construct from moved compatible pair
        }

        pair& operator=(pair<_Ty1, _Ty2>&& _Right)
        {   // assign from moved pair
            this->first = std::move(_Right.first);
            this->second = std::move(_Right.second);
            return (*this);
        }

        void swap(_Myt&& _Right)
        {   // exchange contents with _Right
            if (this != &_Right)
            {   // different, worth swapping
                this->first = std::move(_Right.first);
                this->second = std::move(_Right.second);
            }
        }

        _Ty1 first;     // the first stored value
        _Ty2 second;    // the second stored value
    }; // struct pair

    //-----------------------------------------------------------------------------------------
    // pair TEMPLATE FUNCTIONS

    template<class _Ty1, class _Ty2> inline
    void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right)
    {   // swap _Left and _Right pairs
        _Left.swap(_Right);
    }

    template<class _Ty1, class _Ty2> inline
    void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>&& _Right)
    {   // swap _Left and _Right pairs
        typedef pair<_Ty1, _Ty2> _Myt;
        _Left.swap(std::forward<_Myt>(_Right));
    }

    template<class _Ty1, class _Ty2> inline
    void swap(
        pair<_Ty1, _Ty2>&& _Left,
        pair<_Ty1, _Ty2>& _Right)
    {   // swap _Left and _Right pairs
        typedef pair<_Ty1, _Ty2> _Myt;
        _Right.swap(std::forward<_Myt>(_Left));
    }

    template<class _Ty1, class _Ty2> inline
    bool operator==(
        const pair<_Ty1, _Ty2>& _Left,
        const pair<_Ty1, _Ty2>& _Right)
    {   // test for pair equality
        return (_Left.first == _Right.first && _Left.second == _Right.second);
    }

    template<class _Ty1, class _Ty2> inline
        bool operator!=(
            const pair<_Ty1, _Ty2>& _Left,
            const pair<_Ty1, _Ty2>& _Right)
    {   // test for pair inequality
        return (!(_Left == _Right));
    }

    template<class _Ty1, class _Ty2> inline
    bool operator<(
        const pair<_Ty1, _Ty2>& _Left,
        const pair<_Ty1, _Ty2>& _Right)
    {   // test if _Left < _Right for pairs
        return (_Left.first < _Right.first ||
            (!(_Right.first < _Left.first) && _Left.second < _Right.second));
    }

    template<class _Ty1, class _Ty2> inline
        bool operator>(
            const pair<_Ty1, _Ty2>& _Left,
            const pair<_Ty1, _Ty2>& _Right)
    {   // test if _Left > _Right for pairs
        return (_Right < _Left);
    }

    template<class _Ty1, class _Ty2> inline
    bool operator<=(
        const pair<_Ty1, _Ty2>& _Left,
        const pair<_Ty1, _Ty2>& _Right)
    {   // test if _Left <= _Right for pairs
        return (!(_Right < _Left));
    }

    template<class _Ty1, class _Ty2> inline
    bool operator>=(
        const pair<_Ty1, _Ty2>& _Left,
        const pair<_Ty1, _Ty2>& _Right)
    {   // test if _Left >= _Right for pairs
        return (!(_Left < _Right));
    }

    template<class _InIt> inline
    _InIt begin(
        const pair<_InIt, _InIt>& _Pair)
    {   // return first element of pair
        return (_Pair.first);
    }

    template<class _InIt> inline
    _InIt end(
        const pair<_InIt, _InIt>& _Pair)
    {   // return second element of pair
        return (_Pair.second);
    }

} // namespace std

#endif /* __clr_std_utility_h__ */

#endif // !USE_STL

// Help the VIM editor figure out what kind of file this no-extension file is.
// vim: filetype=cpp