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)
6 * See http://www.boost.org/libs/poly_collection for library home page.
9 #ifndef BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP
10 #define BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP
17 #include <boost/core/lightweight_test.hpp>
18 #include <boost/iterator/iterator_adaptor.hpp>
19 #include <boost/type_traits/has_equal_to.hpp>
22 #include <type_traits>
26 namespace test_utilities{
28 template<typename... Values>
31 template<typename Exception,typename F>
32 void check_throw_case(F f)
38 catch(const Exception&){}
39 catch(...){BOOST_TEST(false);}
42 template<typename Exception,typename... Fs>
43 void check_throw(Fs... f)
45 do_((check_throw_case<Exception>(f),0)...);
48 template<typename F1,typename F2>
54 compose_class(const F1& f1,const F2& f2):f1(f1),f2(f2){}
56 template<typename T,typename... Args>
57 auto operator()(T&& x,Args&&... args)
58 ->decltype(std::declval<F2>()(std::declval<F1>()(
59 std::forward<T>(x)),std::forward<Args>(args)...))
61 return f2(f1(std::forward<T>(x)),std::forward<Args>(args)...);
65 template<typename F1,typename F2>
66 compose_class<F1,F2> compose(F1 f1,F2 f2)
71 template<typename F1,typename F2>
72 struct compose_all_class
77 compose_all_class(const F1& f1,const F2& f2):f1(f1),f2(f2){}
79 template<typename... Args>
80 auto operator()(Args&&... args)
81 ->decltype(std::declval<F2>()(std::declval<F1>()(
82 std::forward<Args>(args))...))
84 return f2(f1(std::forward<Args>(args))...);
88 template<typename F1,typename F2>
89 compose_all_class<F1,F2> compose_all(F1 f1,F2 f2)
94 using std::is_default_constructible;
96 using std::is_copy_constructible;
99 using is_not_copy_constructible=std::integral_constant<
101 !std::is_copy_constructible<T>::value
105 using is_constructible_from_int=std::is_constructible<T,int>;
107 using std::is_copy_assignable;
110 using is_not_copy_assignable=std::integral_constant<
112 !std::is_copy_assignable<T>::value
116 using is_equality_comparable=std::integral_constant<
118 boost::has_equal_to<T,T,bool>::value
122 using is_not_equality_comparable=std::integral_constant<
124 !is_equality_comparable<T>::value
129 typename std::enable_if<is_not_copy_constructible<T>::value>::type* =nullptr
131 typename std::remove_reference<T>::type&& constref_if_copy_constructible(T&& x)
138 typename std::enable_if<is_copy_constructible<T>::value>::type* =nullptr
140 const T& constref_if_copy_constructible(T&& x)
145 template<template<typename> class... Traits>
152 struct apply:std::true_type{};
156 template <typename> class Trait,
157 template <typename> class... Traits
159 struct constraints<Trait,Traits...>
162 struct apply:std::integral_constant<
164 Trait<T>::value&&constraints<Traits...>::template apply<T>::value
168 template<typename... Ts>struct type_list{};
171 typename Constraints,template <typename...> class Template,
175 struct instantiate_with_class;
178 typename Constraints,template <typename...> class Template,
181 struct instantiate_with_class<Constraints,Template,type_list<Us...>>
182 {using type=Template<Us...>;};
185 typename Constraints,template <typename...> class Template,
187 typename T,typename... Ts
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,
202 typename Constraints,template <typename...> class Template,
205 using instantiate_with=typename instantiate_with_class<
206 Constraints,Template,type_list<>,Ts...
210 template <typename...> class Template,typename... Ts
212 using only_eq_comparable=instantiate_with<
213 constraints<is_equality_comparable>,
217 template<typename T> struct identity{using type=T;};
219 template<typename Constraints,typename... Ts>
220 struct first_of_class{};
222 template<typename Constraints,typename T,typename... Ts>
223 struct first_of_class<Constraints,T,Ts...>:std::conditional<
224 Constraints::template apply<T>::value,
226 first_of_class<Constraints,Ts...>
229 template<typename Constraints,typename... Ts>
230 using first_of=typename first_of_class<Constraints,Ts...>::type;
233 typename Constraints,typename... Ts,
234 typename PolyCollection,typename ValueFactory
236 void fill(PolyCollection& p,ValueFactory& v,int n)
238 for(int i=0;i<n;++i){
240 (Constraints::template apply<Ts>::value?
241 (p.insert(v.template make<Ts>()),0):0)...);
245 template<typename PolyCollection>
247 const PolyCollection& p,typename PolyCollection::const_iterator it)
249 return it==p.begin();
252 template<typename PolyCollection,typename Iterator>
253 bool is_first(const PolyCollection& p,const std::type_info& info,Iterator it)
255 return &*it==&*p.begin(info);
258 template<typename PolyCollection,typename Iterator>
259 bool is_last(const PolyCollection& p,const std::type_info& info,Iterator it)
261 return &*it==&*(p.end(info)-1);
264 template<typename T,typename PolyCollection,typename Iterator>
265 bool is_first(const PolyCollection& p,Iterator it)
267 return &*it==&*p.template begin<T>();
270 template<typename T,typename PolyCollection,typename Iterator>
271 bool is_last(const PolyCollection& p,Iterator it)
273 return &*it==&*(p.template end<T>()-1);
276 template<typename Iterator>
277 struct external_iterator_class:
278 public boost::iterator_adaptor<external_iterator_class<Iterator>,Iterator>
280 external_iterator_class(const Iterator& it):
281 external_iterator_class::iterator_adaptor_{it}{}
284 template<typename Iterator>
285 external_iterator_class<Iterator> external_iterator(Iterator it)
290 template<typename Iterator>
291 struct unwrap_iterator_class:public boost::iterator_adaptor<
292 unwrap_iterator_class<Iterator>,
294 typename std::iterator_traits<Iterator>::value_type::type
297 unwrap_iterator_class(const Iterator& it):
298 unwrap_iterator_class::iterator_adaptor_{it}{}
301 template<typename Iterator>
302 unwrap_iterator_class<Iterator> unwrap_iterator(Iterator it)
307 struct auto_increment
310 T make(){return T(n++);}
315 struct jammed_auto_increment
318 T make(){return T(n++/7);}
325 typename Propagate=std::true_type,typename AlwaysEqual=std::true_type
327 struct rooted_allocator:std::allocator<T>
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 */
334 struct rebind{using other=rooted_allocator<U,Propagate,AlwaysEqual>;};
336 rooted_allocator():root{nullptr}{}
337 explicit rooted_allocator(int):root{this}{}
339 rooted_allocator(const rooted_allocator<U,Propagate,AlwaysEqual>& x):
343 bool operator==(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
344 {return AlwaysEqual::value?true:root==x.root;}
346 bool operator!=(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
347 {return AlwaysEqual::value?false:root!=x.root;}
350 bool comes_from(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
354 template<typename,typename,typename> friend struct rooted_allocator;
360 typename PolyCollection,
361 template<typename...> class Allocator,typename... Args
363 struct realloc_poly_collection_class;
366 typename PolyCollection,
367 template<typename...> class Allocator,typename... Args
369 using realloc_poly_collection=typename realloc_poly_collection_class<
370 PolyCollection,Allocator,Args...>::type;
373 template<typename,typename> class PolyCollection,
374 typename T,typename OriginalAllocator,
375 template<typename...> class Allocator,typename... Args
377 struct realloc_poly_collection_class<
378 PolyCollection<T,OriginalAllocator>,Allocator,Args...
381 using value_type=typename PolyCollection<T,OriginalAllocator>::value_type;
382 using type=PolyCollection<T,Allocator<value_type,Args...>>;
385 template<std::size_t N>
388 std::array<const void*,N> datas;
389 std::array<std::size_t,N> sizes;
391 bool operator==(const layout_data& x)const
393 return datas==x.datas&&sizes==x.sizes;
397 template<typename... Types,typename PolyCollection>
398 layout_data<sizeof...(Types)> get_layout_data(const PolyCollection& p)
401 {{(p.template is_registered<Types>()?
402 &*p.template begin<Types>():nullptr)...}},
403 {{(p.template is_registered<Types>()?
404 p.template size<Types>():0)...}}
408 } /* namespace test_utilities */