• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016-2018 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See http://www.boost.org/libs/poly_collection for library home page.
7  */
8 
9 #ifndef BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP
10 #define BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <array>
17 #include <boost/core/lightweight_test.hpp>
18 #include <boost/iterator/iterator_adaptor.hpp>
19 #include <boost/type_traits/has_equal_to.hpp>
20 #include <iterator>
21 #include <memory>
22 #include <type_traits>
23 #include <typeinfo>
24 #include <utility>
25 
26 namespace test_utilities{
27 
28 template<typename... Values>
do_(Values...)29 void do_(Values...){}
30 
31 template<typename Exception,typename F>
check_throw_case(F f)32 void check_throw_case(F f)
33 {
34   try{
35     (void)f();
36     BOOST_TEST(false);
37   }
38   catch(const Exception&){}
39   catch(...){BOOST_TEST(false);}
40 }
41 
42 template<typename Exception,typename... Fs>
check_throw(Fs...f)43 void check_throw(Fs... f)
44 {
45   do_((check_throw_case<Exception>(f),0)...);
46 }
47 
48 template<typename F1,typename F2>
49 struct compose_class
50 {
51   F1 f1;
52   F2 f2;
53 
compose_classtest_utilities::compose_class54   compose_class(const F1& f1,const F2& f2):f1(f1),f2(f2){}
55 
56   template<typename T,typename... Args>
operator ()test_utilities::compose_class57   auto operator()(T&& x,Args&&... args)
58     ->decltype(std::declval<F2>()(std::declval<F1>()(
59       std::forward<T>(x)),std::forward<Args>(args)...))
60   {
61     return f2(f1(std::forward<T>(x)),std::forward<Args>(args)...);
62   }
63 };
64 
65 template<typename F1,typename F2>
compose(F1 f1,F2 f2)66 compose_class<F1,F2> compose(F1 f1,F2 f2)
67 {
68   return {f1,f2};
69 }
70 
71 template<typename F1,typename F2>
72 struct compose_all_class
73 {
74   F1 f1;
75   F2 f2;
76 
compose_all_classtest_utilities::compose_all_class77   compose_all_class(const F1& f1,const F2& f2):f1(f1),f2(f2){}
78 
79   template<typename... Args>
operator ()test_utilities::compose_all_class80   auto operator()(Args&&... args)
81     ->decltype(std::declval<F2>()(std::declval<F1>()(
82       std::forward<Args>(args))...))
83   {
84     return f2(f1(std::forward<Args>(args))...);
85   }
86 };
87 
88 template<typename F1,typename F2>
compose_all(F1 f1,F2 f2)89 compose_all_class<F1,F2> compose_all(F1 f1,F2 f2)
90 {
91   return {f1,f2};
92 }
93 
94 using std::is_default_constructible;
95 
96 using std::is_copy_constructible;
97 
98 template<typename T>
99 using is_not_copy_constructible=std::integral_constant<
100   bool,
101   !std::is_copy_constructible<T>::value
102 >;
103 
104 template<typename T>
105 using is_constructible_from_int=std::is_constructible<T,int>;
106 
107 using std::is_copy_assignable;
108 
109 template<typename T>
110 using is_not_copy_assignable=std::integral_constant<
111   bool,
112   !std::is_copy_assignable<T>::value
113 >;
114 
115 template<typename T>
116 using is_equality_comparable=std::integral_constant<
117   bool,
118   boost::has_equal_to<T,T,bool>::value
119 >;
120 
121 template<typename T>
122 using is_not_equality_comparable=std::integral_constant<
123   bool,
124   !is_equality_comparable<T>::value
125 >;
126 
127 template<
128   typename T,
129   typename std::enable_if<is_not_copy_constructible<T>::value>::type* =nullptr
130 >
constref_if_copy_constructible(T && x)131 typename std::remove_reference<T>::type&& constref_if_copy_constructible(T&& x)
132 {
133   return std::move(x);
134 }
135 
136 template<
137   typename T,
138   typename std::enable_if<is_copy_constructible<T>::value>::type* =nullptr
139 >
constref_if_copy_constructible(T && x)140 const T& constref_if_copy_constructible(T&& x)
141 {
142   return x;
143 }
144 
145 template<template<typename> class... Traits>
146 struct constraints;
147 
148 template<>
149 struct constraints<>
150 {
151   template<typename T>
152   struct apply:std::true_type{};
153 };
154 
155 template<
156   template <typename> class Trait,
157   template <typename> class... Traits
158 >
159 struct constraints<Trait,Traits...>
160 {
161   template<typename T>
162   struct apply:std::integral_constant<
163     bool,
164     Trait<T>::value&&constraints<Traits...>::template apply<T>::value
165   >{};
166 };
167 
168 template<typename... Ts>struct type_list{};
169 
170 template<
171   typename Constraints,template <typename...> class Template,
172   typename TypeList,
173   typename... Ts
174 >
175 struct instantiate_with_class;
176 
177 template<
178   typename Constraints,template <typename...> class Template,
179   typename... Us
180 >
181 struct instantiate_with_class<Constraints,Template,type_list<Us...>>
182 {using type=Template<Us...>;};
183 
184 template<
185   typename Constraints,template <typename...> class Template,
186   typename... Us,
187   typename T,typename... Ts
188 >
189 struct instantiate_with_class<
190   Constraints,Template,type_list<Us...>,T,Ts...
191 >:instantiate_with_class<
192   Constraints,Template,
193   typename std::conditional<
194     Constraints::template apply<T>::value,
195     type_list<Us...,T>,
196     type_list<Us...>
197   >::type,
198   Ts...
199 >{};
200 
201 template<
202   typename Constraints,template <typename...> class Template,
203   typename... Ts
204 >
205 using instantiate_with=typename instantiate_with_class<
206   Constraints,Template,type_list<>,Ts...
207 >::type;
208 
209 template<
210   template <typename...> class Template,typename... Ts
211 >
212 using only_eq_comparable=instantiate_with<
213   constraints<is_equality_comparable>,
214   Template, Ts...
215 >;
216 
217 template<typename T> struct identity{using type=T;};
218 
219 template<typename Constraints,typename... Ts>
220 struct first_of_class{};
221 
222 template<typename Constraints,typename T,typename... Ts>
223 struct first_of_class<Constraints,T,Ts...>:std::conditional<
224   Constraints::template apply<T>::value,
225   identity<T>,
226   first_of_class<Constraints,Ts...>
227 >::type{};
228 
229 template<typename Constraints,typename... Ts>
230 using first_of=typename first_of_class<Constraints,Ts...>::type;
231 
232 template<
233   typename Constraints,typename... Ts,
234   typename PolyCollection,typename ValueFactory
235 >
fill(PolyCollection & p,ValueFactory & v,int n)236 void fill(PolyCollection& p,ValueFactory& v,int n)
237 {
238   for(int i=0;i<n;++i){
239     do_(
240     (Constraints::template apply<Ts>::value?
241       (p.insert(v.template make<Ts>()),0):0)...);
242   }
243 }
244 
245 template<typename PolyCollection>
is_first(const PolyCollection & p,typename PolyCollection::const_iterator it)246 bool is_first(
247   const PolyCollection& p,typename PolyCollection::const_iterator it)
248 {
249   return it==p.begin();
250 }
251 
252 template<typename PolyCollection,typename Iterator>
is_first(const PolyCollection & p,const std::type_info & info,Iterator it)253 bool is_first(const PolyCollection& p,const std::type_info& info,Iterator it)
254 {
255   return &*it==&*p.begin(info);
256 }
257 
258 template<typename PolyCollection,typename Iterator>
is_last(const PolyCollection & p,const std::type_info & info,Iterator it)259 bool is_last(const PolyCollection& p,const std::type_info& info,Iterator it)
260 {
261   return &*it==&*(p.end(info)-1);
262 }
263 
264 template<typename T,typename PolyCollection,typename Iterator>
is_first(const PolyCollection & p,Iterator it)265 bool is_first(const PolyCollection& p,Iterator it)
266 {
267   return &*it==&*p.template begin<T>();
268 }
269 
270 template<typename T,typename PolyCollection,typename Iterator>
is_last(const PolyCollection & p,Iterator it)271 bool is_last(const PolyCollection& p,Iterator it)
272 {
273   return &*it==&*(p.template end<T>()-1);
274 }
275 
276 template<typename Iterator>
277 struct external_iterator_class:
278   public boost::iterator_adaptor<external_iterator_class<Iterator>,Iterator>
279 {
external_iterator_classtest_utilities::external_iterator_class280   external_iterator_class(const Iterator& it):
281     external_iterator_class::iterator_adaptor_{it}{}
282 };
283 
284 template<typename Iterator>
external_iterator(Iterator it)285 external_iterator_class<Iterator> external_iterator(Iterator it)
286 {
287   return it;
288 }
289 
290 template<typename Iterator>
291 struct unwrap_iterator_class:public boost::iterator_adaptor<
292   unwrap_iterator_class<Iterator>,
293   Iterator,
294   typename std::iterator_traits<Iterator>::value_type::type
295 >
296 {
unwrap_iterator_classtest_utilities::unwrap_iterator_class297   unwrap_iterator_class(const Iterator& it):
298     unwrap_iterator_class::iterator_adaptor_{it}{}
299 };
300 
301 template<typename Iterator>
unwrap_iterator(Iterator it)302 unwrap_iterator_class<Iterator> unwrap_iterator(Iterator it)
303 {
304   return it;
305 }
306 
307 struct auto_increment
308 {
309   template<typename T>
maketest_utilities::auto_increment310   T make(){return T(n++);}
311 
312   int n=0;
313 };
314 
315 struct jammed_auto_increment
316 {
317   template<typename T>
maketest_utilities::jammed_auto_increment318   T make(){return T(n++/7);}
319 
320   int n=0;
321 };
322 
323 template<
324   typename T,
325   typename Propagate=std::true_type,typename AlwaysEqual=std::true_type
326 >
327 struct rooted_allocator:std::allocator<T>
328 {
329   using propagate_on_container_copy_assignment=Propagate;
330   using propagate_on_container_move_assignment=Propagate;
331   using propagate_on_container_swap=Propagate;
332   using is_always_equal=AlwaysEqual; /* for C++17 forward compatibility */
333   template<typename U>
334   struct rebind{using other=rooted_allocator<U,Propagate,AlwaysEqual>;};
335 
rooted_allocatortest_utilities::rooted_allocator336   rooted_allocator():root{nullptr}{}
rooted_allocatortest_utilities::rooted_allocator337   explicit rooted_allocator(int):root{this}{}
338   template<typename U>
rooted_allocatortest_utilities::rooted_allocator339   rooted_allocator(const rooted_allocator<U,Propagate,AlwaysEqual>& x):
340     root{x.root}{}
341 
342   template<typename U>
operator ==test_utilities::rooted_allocator343   bool operator==(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
344     {return AlwaysEqual::value?true:root==x.root;}
345   template<typename U>
operator !=test_utilities::rooted_allocator346   bool operator!=(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
347     {return AlwaysEqual::value?false:root!=x.root;}
348 
349   template<typename U>
comes_fromtest_utilities::rooted_allocator350   bool comes_from(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
351     {return root==&x;}
352 
353 private:
354   template<typename,typename,typename> friend struct rooted_allocator;
355 
356   const void* root;
357 };
358 
359 template<
360   typename PolyCollection,
361   template<typename...> class Allocator,typename... Args
362 >
363 struct realloc_poly_collection_class;
364 
365 template<
366   typename PolyCollection,
367   template<typename...> class Allocator,typename... Args
368 >
369 using realloc_poly_collection=typename realloc_poly_collection_class<
370   PolyCollection,Allocator,Args...>::type;
371 
372 template<
373   template<typename,typename> class PolyCollection,
374   typename T,typename OriginalAllocator,
375   template<typename...> class Allocator,typename... Args
376 >
377 struct realloc_poly_collection_class<
378   PolyCollection<T,OriginalAllocator>,Allocator,Args...
379 >
380 {
381   using value_type=typename PolyCollection<T,OriginalAllocator>::value_type;
382   using type=PolyCollection<T,Allocator<value_type,Args...>>;
383 };
384 
385 template<std::size_t N>
386 struct layout_data
387 {
388   std::array<const void*,N> datas;
389   std::array<std::size_t,N> sizes;
390 
operator ==test_utilities::layout_data391   bool operator==(const layout_data& x)const
392   {
393     return datas==x.datas&&sizes==x.sizes;
394   }
395 };
396 
397 template<typename... Types,typename PolyCollection>
get_layout_data(const PolyCollection & p)398 layout_data<sizeof...(Types)> get_layout_data(const PolyCollection& p)
399 {
400   return{
401     {{(p.template is_registered<Types>()?
402       &*p.template begin<Types>():nullptr)...}},
403     {{(p.template is_registered<Types>()?
404       p.template size<Types>():0)...}}
405   };
406 }
407 
408 } /* namespace test_utilities */
409 
410 #endif
411