File: cpp11_shenanigans.hpp

package info (click to toggle)
trompeloeil-cpp 47-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,476 kB
  • sloc: cpp: 17,573; sh: 126; makefile: 5
file content (370 lines) | stat: -rw-r--r-- 14,059 bytes parent folder | download
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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
/*
 * Trompeloeil C++ mocking framework
 *
 * Copyright (C) Björn Fahller
 * Copyright (C) Andrew Paxie
 *
 *  Use, modification and distribution is subject to the
 *  Boost Software License, Version 1.0. (See accompanying
 *  file LICENSE_1_0.txt or copy atl
 *  http://www.boost.org/LICENSE_1_0.txt)
 *
 * Project home: https://github.com/rollbear/trompeloeil
 */

#ifndef TROMPELOEIL_CPP11_SHENANIGANS_HPP
#define TROMPELOEIL_CPP11_SHENANIGANS_HPP

namespace trompeloeil {
namespace detail
{
template <typename T>
struct unwrap_type
{
  using type = T;
};
template <typename T>
struct unwrap_type<std::reference_wrapper<T>>
{
using type = T&;
};

/* Implement C++14 features using only C++11 entities. */

/* <memory> */

/* Implementation of make_unique is from
 *
 * Stephan T. Lavavej, "make_unique (Revision 1),"
 * ISO/IEC JTC1 SC22 WG21 N3656, 18 April 2013.
 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm
 * Accessed: 14 June 2017
 *
 * Renamed types to avoid the use of reserved identifiers.
 */
template <class T>
struct unique_if
{
  typedef std::unique_ptr<T> single_object;
};

template <class T>
struct unique_if<T[]>
{
  typedef std::unique_ptr<T[]> unknown_bound;
};

template <class T, size_t N>
struct unique_if<T[N]>
{
  typedef void known_bound;
};

template <class T, class... Args>
typename unique_if<T>::single_object
make_unique(Args&&... args)
{
  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <class T>
typename unique_if<T>::unknown_bound
make_unique(size_t n)
{
  typedef typename std::remove_extent<T>::type U;
  return std::unique_ptr<T>(new U[n]());
}

template <class T, class... Args>
typename unique_if<T>::known_bound
make_unique(Args&&...) = delete;

/* <type_traits> */

/* The implementation of these is from
 *
 * Walter E. Brown, "TransformationTraits Redux, v2,"
 * ISO/IEC JTC1 SC22 WG21 N3655, 18 April 2013.
 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3655.pdf
 * Accessed: 2 November 2017
 *
 * Minor changes to capitalize template parameter `bool B` has been made.
 *
 * See also:
 * http://en.cppreference.com/w/cpp/types/conditional
 * http://en.cppreference.com/w/cpp/types/decay
 * http://en.cppreference.com/w/cpp/types/enable_if
 * http://en.cppreference.com/w/cpp/types/remove_pointer
 * http://en.cppreference.com/w/cpp/types/remove_reference
 * Accessed: 17 May 2017
 */
template <bool B, typename T, typename F>
using conditional_t = typename std::conditional<B, T, F>::type;

template <typename T>
using decay_t = typename std::decay<T>::type;

template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

template <typename T>
using remove_pointer_t = typename std::remove_pointer<T>::type;

template <typename T>
using remove_reference_t = typename std::remove_reference<T>::type;

/* <utility> */

/* This implementation of exchange is from
 *
 * Jeffrey Yasskin, "exchange() utility function, revision 3,"
 * ISO/IEC JTC1 SC22 WG21 N3688, 19 April 2013.
 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3668.html
 * Accessed: 2 November 2017
 *
 * See also:
 * http://en.cppreference.com/w/cpp/utility/exchange
 * Accessed: 17 May 2017
 */
template<class T, class U = T>
inline
T
exchange(
  T& obj,
  U&& new_value)
{
  T old_value = std::move(obj);
  obj = std::forward<U>(new_value);
  return old_value;
}

/* integer_sequence and index_sequence implementations are from
 *
 * Jonathan Wakely, "Compile-time integer sequences,"
 * ISO/IEC JTC1 SC22 WG21 N3658, 18 April 2013.
 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
 * Accessed: 2 November 2017
 *
 * See also:
 * http://en.cppreference.com/w/cpp/utility/integer_sequence
 * Accessed: 17 May 2017
 */
template <typename T, T... I>
struct integer_sequence
{
  // Replaces a typedef used in the definition found in N3658.
  using value_type = T;

  static constexpr size_t size() noexcept
  {
    return sizeof...(I);
  }
};

template <size_t... I>
using index_sequence = integer_sequence<size_t, I...>;

/* This implementation of make_integer_sequence is from boost/mp11,
 *
 * Copyright 2015, 2017 Peter Dimov
 *
 * Distributed under the Boost Software License, Version 1.0.
 *
 * Implemented here:
 *
 * https://github.com/pdimov/mp11/blob/master/include/boost/
 *   integer_sequence.hpp
 * Accessed: 17 May 2017
 *
 * (now missing) and here:
 *
 * https://github.com/boostorg/mp11/blob/develop/include/boost/
 *   mp11/integer_sequence.hpp
 * Accessed: 13 August 2017
 */
namespace impl
{
// iseq_if_c
template <bool C, class T, class E>
struct iseq_if_c_impl;

template <class T, class E>
struct iseq_if_c_impl<true, T, E>
{
  using type = T;
};

template <class T, class E>
struct iseq_if_c_impl<false, T, E>
{
  using type = E;
};

template <bool C, class T, class E>
using iseq_if_c = typename iseq_if_c_impl<C, T, E>::type;

// iseq_identity
template <class T>
struct iseq_identity
{
  using type = T;
};

template <class S1, class S2>
struct append_integer_sequence;

template <class T, T... I, T... J>
struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
{
  using type = integer_sequence<T, I..., ( J + sizeof...(I) )...>;
};

template <class T, T N>
struct make_integer_sequence_impl;

template <class T, T N>
struct make_integer_sequence_impl_
{
private:

  static_assert( N >= 0, "make_integer_sequence<T, N>: N must not be negative" );

  static T const M = N / 2;
  static T const R = N % 2;

  using S1 = typename make_integer_sequence_impl<T, M>::type;
  using S2 = typename append_integer_sequence<S1, S1>::type;
  using S3 = typename make_integer_sequence_impl<T, R>::type;
  using S4 = typename append_integer_sequence<S2, S3>::type;

public:

  using type = S4;
};

template <class T, T N>
struct make_integer_sequence_impl:
  iseq_if_c<N == 0,
    iseq_identity<integer_sequence<T>>,
    iseq_if_c<N == 1,
      iseq_identity<integer_sequence<T, 0>>,
      make_integer_sequence_impl_<T, N>>>
{
};
}

template<class T, T N>
using make_integer_sequence = typename impl::make_integer_sequence_impl<T, N>::type;

template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;

template <typename... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;

} /* namespace detail */

}

#define TROMPELOEIL_WITH_(capture, arg_s, ...)                                 \
  template action<trompeloeil::with>(                                          \
    arg_s,                                                                     \
    [capture]                                                                  \
    (typename trompeloeil_e_t::trompeloeil_call_params_type_t const& trompeloeil_x)\
    {                                                                          \
      auto&& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x);                      \
      auto&& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x);                      \
      auto&& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x);                      \
      auto&& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x);                      \
      auto&& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x);                      \
      auto&& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x);                      \
      auto&& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x);                      \
      auto&& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x);                      \
      auto&& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x);                      \
      auto&&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x);                     \
      auto&&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x);                     \
      auto&&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x);                     \
      auto&&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x);                     \
      auto&&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x);                     \
      auto&&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x);                     \
      ::trompeloeil::ignore(                                                   \
        _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15);                   \
      return __VA_ARGS__;                                                      \
    })

#define TROMPELOEIL_SIDE_EFFECT_(capture, ...)                                 \
  template action<trompeloeil::sideeffect>(                                    \
    [capture]                                                                  \
    (typename trompeloeil_e_t::trompeloeil_call_params_type_t& trompeloeil_x)  \
    {                                                                          \
      auto&& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x);                      \
      auto&& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x);                      \
      auto&& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x);                      \
      auto&& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x);                      \
      auto&& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x);                      \
      auto&& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x);                      \
      auto&& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x);                      \
      auto&& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x);                      \
      auto&& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x);                      \
      auto&&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x);                     \
      auto&&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x);                     \
      auto&&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x);                     \
      auto&&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x);                     \
      auto&&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x);                     \
      auto&&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x);                     \
      ::trompeloeil::ignore(                                                   \
        _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15);                   \
      __VA_ARGS__;                                                             \
    })

#define TROMPELOEIL_RETURN_(capture, ...)                                      \
  template action<trompeloeil::handle_return>(                                 \
    [capture]                                                                  \
    (typename trompeloeil_e_t::trompeloeil_call_params_type_t& trompeloeil_x)  \
      -> typename trompeloeil_e_t::trompeloeil_return_of_t                     \
    {                                                                          \
      auto&& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x);                      \
      auto&& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x);                      \
      auto&& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x);                      \
      auto&& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x);                      \
      auto&& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x);                      \
      auto&& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x);                      \
      auto&& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x);                      \
      auto&& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x);                      \
      auto&& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x);                      \
      auto&&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x);                     \
      auto&&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x);                     \
      auto&&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x);                     \
      auto&&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x);                     \
      auto&&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x);                     \
      auto&&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x);                     \
      ::trompeloeil::ignore(                                                   \
        _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15);                   \
      return ::trompeloeil::decay_return_type(__VA_ARGS__);                    \
    })
#define TROMPELOEIL_THROW_(capture, ...)                                       \
  template action<trompeloeil::handle_throw>(                                  \
    [capture]                                                                  \
    (typename trompeloeil_e_t::trompeloeil_call_params_type_t& trompeloeil_x)  \
    {                                                                          \
      auto&& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x);                      \
      auto&& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x);                      \
      auto&& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x);                      \
      auto&& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x);                      \
      auto&& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x);                      \
      auto&& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x);                      \
      auto&& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x);                      \
      auto&& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x);                      \
      auto&& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x);                      \
      auto&&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x);                     \
      auto&&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x);                     \
      auto&&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x);                     \
      auto&&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x);                     \
      auto&&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x);                     \
      auto&&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x);                     \
      ::trompeloeil::ignore(                                                   \
        _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15);                   \
      throw __VA_ARGS__;                                                       \
    })

#endif //TROMPELOEIL_CPP11_SHENANIGANS_HPP