| // -*- C++ -*- |
| // typelist for the C++ library testsuite. |
| // |
| // Copyright (C) 2005-2022 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| // |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| // |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| // |
| |
| #ifndef _TESTSUITE_COMMON_TYPES_H |
| #define _TESTSUITE_COMMON_TYPES_H 1 |
| |
| #include <ext/typelist.h> |
| |
| #include <ext/new_allocator.h> |
| #include <ext/malloc_allocator.h> |
| #include <ext/mt_allocator.h> |
| #include <ext/bitmap_allocator.h> |
| #include <ext/pool_allocator.h> |
| |
| #include <algorithm> |
| |
| #include <vector> |
| #include <list> |
| #include <deque> |
| #include <string> |
| #include <limits> |
| |
| #include <map> |
| #include <set> |
| |
| #if __cplusplus >= 201103L |
| #include <atomic> |
| #include <type_traits> |
| #include <unordered_map> |
| #include <unordered_set> |
| namespace unord = std; |
| #else |
| #include <tr1/unordered_map> |
| #include <tr1/unordered_set> |
| namespace unord = std::tr1; |
| #endif |
| |
| namespace __gnu_test |
| { |
| using __gnu_cxx::typelist::null_type; |
| using __gnu_cxx::typelist::node; |
| using __gnu_cxx::typelist::transform; |
| using __gnu_cxx::typelist::append; |
| |
| // All the allocators to test. |
| template<typename Tp, bool Thread> |
| struct allocator_policies |
| { |
| typedef Tp value_type; |
| typedef __gnu_cxx::new_allocator<Tp> a1; |
| typedef __gnu_cxx::malloc_allocator<Tp> a2; |
| typedef __gnu_cxx::__common_pool_policy<__gnu_cxx::__pool, Thread> pool_policy; |
| typedef __gnu_cxx::__mt_alloc<Tp, pool_policy> a3; |
| typedef __gnu_cxx::bitmap_allocator<Tp> a4; |
| typedef __gnu_cxx::__pool_alloc<Tp> a5; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN5(a1, a2, a3, a4, a5)> type; |
| }; |
| |
| // Typelists for vector, string, list, deque. |
| // XXX should just use template templates |
| template<typename Tp, bool Thread> |
| struct vectors |
| { |
| typedef Tp value_type; |
| |
| template<typename Tl> |
| struct vector_shell |
| { |
| typedef Tl allocator_type; |
| typedef std::vector<value_type, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<value_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, vector_shell>::type type; |
| }; |
| |
| template<typename Tp, bool Thread> |
| struct lists |
| { |
| typedef Tp value_type; |
| |
| template<typename Tl> |
| struct list_shell |
| { |
| typedef Tl allocator_type; |
| typedef std::list<value_type, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<value_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, list_shell>::type type; |
| }; |
| |
| template<typename Tp, bool Thread> |
| struct deques |
| { |
| typedef Tp value_type; |
| |
| template<typename Tl> |
| struct deque_shell |
| { |
| typedef Tl allocator_type; |
| typedef std::deque<value_type, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<value_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, deque_shell>::type type; |
| }; |
| |
| template<typename Tp, bool Thread> |
| struct strings |
| { |
| typedef Tp value_type; |
| |
| template<typename Tl> |
| struct string_shell |
| { |
| typedef Tl allocator_type; |
| typedef std::char_traits<value_type> traits_type; |
| typedef std::basic_string<value_type, traits_type, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<value_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, string_shell>::type type; |
| }; |
| |
| // A typelist of vector, list, deque, and string all instantiated |
| // with each of the allocator policies. |
| template<typename Tp, bool Thread> |
| struct sequence_containers |
| { |
| typedef Tp value_type; |
| |
| typedef typename vectors<value_type, Thread>::type vector_typelist; |
| typedef typename lists<value_type, Thread>::type list_typelist; |
| typedef typename deques<value_type, Thread>::type deque_typelist; |
| typedef typename strings<value_type, Thread>::type string_typelist; |
| |
| typedef typename append<vector_typelist, list_typelist>::type a1; |
| typedef typename append<deque_typelist, string_typelist>::type a2; |
| typedef typename append<a1, a2>::type type; |
| }; |
| |
| // Typelists for map, set, unordered_set, unordered_map. |
| template<typename Tp, bool Thread> |
| struct maps |
| { |
| typedef Tp value_type; |
| typedef Tp key_type; |
| typedef std::pair<const key_type, value_type> pair_type; |
| typedef std::less<key_type> compare_function; |
| |
| template<typename Tl> |
| struct container |
| { |
| typedef Tl allocator_type; |
| typedef std::map<key_type, value_type, compare_function, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<pair_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, container>::type type; |
| }; |
| |
| template<typename Tp, bool Thread> |
| struct unordered_maps |
| { |
| typedef Tp value_type; |
| typedef Tp key_type; |
| typedef std::pair<const key_type, value_type> pair_type; |
| typedef unord::hash<key_type> hash_function; |
| typedef std::equal_to<key_type> equality_function; |
| |
| template<typename Tl> |
| struct container |
| { |
| typedef Tl allocator_type; |
| typedef unord::unordered_map<key_type, value_type, hash_function, equality_function, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<pair_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, container>::type type; |
| }; |
| |
| template<typename Tp, bool Thread> |
| struct sets |
| { |
| typedef Tp value_type; |
| typedef Tp key_type; |
| typedef std::less<key_type> compare_function; |
| |
| template<typename Tl> |
| struct container |
| { |
| typedef Tl allocator_type; |
| typedef std::set<key_type, compare_function, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<key_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, container>::type type; |
| }; |
| |
| template<typename Tp, bool Thread> |
| struct unordered_sets |
| { |
| typedef Tp value_type; |
| typedef Tp key_type; |
| typedef unord::hash<key_type> hash_function; |
| typedef std::equal_to<key_type> equality_function; |
| |
| template<typename Tl> |
| struct container |
| { |
| typedef Tl allocator_type; |
| typedef unord::unordered_set<key_type, hash_function, equality_function, allocator_type> type; |
| }; |
| |
| typedef allocator_policies<key_type, Thread> allocator_types; |
| typedef typename allocator_types::type allocator_typelist; |
| typedef typename transform<allocator_typelist, container>::type type; |
| }; |
| |
| |
| // A typelist of all associated container types, with each of the |
| // allocator policies. |
| template<typename Tp, bool Thread> |
| struct associative_containers |
| { |
| typedef Tp value_type; |
| |
| typedef typename maps<value_type, Thread>::type map_typelist; |
| typedef typename sets<value_type, Thread>::type set_typelist; |
| typedef typename unordered_maps<value_type, Thread>::type unordered_map_typelist; |
| typedef typename unordered_sets<value_type, Thread>::type unordered_set_typelist; |
| |
| typedef typename append<map_typelist, unordered_map_typelist>::type a1; |
| typedef typename append<set_typelist, unordered_set_typelist>::type a2; |
| typedef typename append<a1, a2>::type type; |
| }; |
| |
| // A typelist of all standard integral types. |
| struct integral_types |
| { |
| typedef bool a1; |
| typedef char a2; |
| typedef signed char a3; |
| typedef unsigned char a4; |
| typedef short a5; |
| typedef unsigned short a6; |
| typedef int a7; |
| typedef unsigned int a8; |
| typedef long a9; |
| typedef unsigned long a10; |
| typedef long long a11; |
| typedef unsigned long long a12; |
| typedef wchar_t a13; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN13(a1, a2, a3, a4, a5, a6, a7, a8, a9, |
| a10, a11, a12, a13)> basic_typelist; |
| #if __cplusplus >= 201103L |
| typedef char16_t a14; |
| typedef char32_t a15; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN2(a14, a15)> cxx11_typelist; |
| #else |
| typedef node<null_type> cxx11_typelist; |
| #endif |
| #ifdef _GLIBCXX_USE_CHAR8_T |
| typedef char8_t a16; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN1(a16)> char8_typelist; |
| #else |
| typedef node<null_type> char8_typelist; |
| #endif |
| typedef typename append<basic_typelist, cxx11_typelist>::type tl1; |
| typedef typename append<tl1, char8_typelist>::type type; |
| }; |
| |
| // A typelist of all standard integral types + the GNU 128-bit types. |
| struct integral_types_gnu |
| { |
| typedef bool a1; |
| typedef char a2; |
| typedef signed char a3; |
| typedef unsigned char a4; |
| typedef short a5; |
| typedef unsigned short a6; |
| typedef int a7; |
| typedef unsigned int a8; |
| typedef long a9; |
| typedef unsigned long a10; |
| typedef long long a11; |
| typedef unsigned long long a12; |
| typedef wchar_t a13; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN13(a1, a2, a3, a4, a5, a6, a7, a8, a9, |
| a10, a11, a12, a13)> basic_typelist; |
| #if __cplusplus >= 201103L |
| typedef char16_t a14; |
| typedef char32_t a15; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN2(a14, a15)> cxx11_typelist; |
| #else |
| typedef node<null_type> cxx11_typelist; |
| #endif |
| #ifdef _GLIBCXX_USE_CHAR8_T |
| typedef char8_t a16; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN1(a16)> char8_typelist; |
| #else |
| typedef node<null_type> char8_typelist; |
| #endif |
| # if !defined(__STRICT_ANSI__) && defined(__SIZEOF_INT128__) |
| __extension__ typedef __int128 a17; |
| __extension__ typedef unsigned __int128 a18; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN2(a17, a18)> int128_typelist; |
| #else |
| typedef node<null_type> int128_typelist; |
| #endif |
| typedef typename append<basic_typelist, cxx11_typelist>::type tl1; |
| typedef typename append<tl1, char8_typelist>::type tl2; |
| typedef typename append<tl2, int128_typelist>::type type; |
| }; |
| |
| #if __cplusplus >= 201103L |
| struct atomic_integrals_no_bool |
| { |
| typedef std::atomic_char a2; |
| typedef std::atomic_schar a3; |
| typedef std::atomic_uchar a4; |
| typedef std::atomic_short a5; |
| typedef std::atomic_ushort a6; |
| typedef std::atomic_int a7; |
| typedef std::atomic_uint a8; |
| typedef std::atomic_long a9; |
| typedef std::atomic_ulong a10; |
| typedef std::atomic_llong a11; |
| typedef std::atomic_ullong a12; |
| typedef std::atomic_wchar_t a13; |
| typedef std::atomic_char16_t a14; |
| typedef std::atomic_char32_t a15; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN14(a2, a3, a4, a5, a6, a7, a8, a9, a10, |
| a11, a12, a13, a14, a15)> basic_typelist; |
| #ifdef _GLIBCXX_USE_CHAR8_T |
| typedef std::atomic_char8_t a16; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN1(a16)> char8_typelist; |
| #else |
| typedef node<null_type> char8_typelist; |
| #endif |
| typedef typename append<basic_typelist, char8_typelist>::type type; |
| }; |
| |
| struct atomic_integrals |
| { |
| typedef std::atomic_bool a1; |
| typedef std::atomic_char a2; |
| typedef std::atomic_schar a3; |
| typedef std::atomic_uchar a4; |
| typedef std::atomic_short a5; |
| typedef std::atomic_ushort a6; |
| typedef std::atomic_int a7; |
| typedef std::atomic_uint a8; |
| typedef std::atomic_long a9; |
| typedef std::atomic_ulong a10; |
| typedef std::atomic_llong a11; |
| typedef std::atomic_ullong a12; |
| typedef std::atomic_wchar_t a13; |
| typedef std::atomic_char16_t a14; |
| typedef std::atomic_char32_t a15; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN15(a1, a2, a3, a4, a5, a6, a7, a8, a9, |
| a10, a11, a12, a13, a14, a15)> basic_typelist; |
| #ifdef _GLIBCXX_USE_CHAR8_T |
| typedef std::atomic_char8_t a16; |
| typedef node<_GLIBCXX_TYPELIST_CHAIN1(a16)> char8_typelist; |
| #else |
| typedef node<null_type> char8_typelist; |
| #endif |
| typedef typename append<basic_typelist, char8_typelist>::type type; |
| }; |
| |
| |
| template<typename Tp> |
| struct atomics |
| { |
| typedef Tp value_type; |
| typedef std::atomic<value_type> type; |
| }; |
| |
| typedef transform<integral_types::type, atomics>::type atomics_tl; |
| #endif |
| |
| template<typename Tp> |
| struct numeric_limits |
| { |
| typedef Tp value_type; |
| typedef std::numeric_limits<value_type> type; |
| }; |
| |
| typedef transform<integral_types_gnu::type, numeric_limits>::type limits_tl; |
| |
| struct has_increment_operators |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| _Tp a; |
| ++a; // prefix |
| a++; // postfix |
| a += a; |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| struct has_decrement_operators |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| _Tp a; |
| --a; // prefix |
| a--; // postfix |
| a -= a; |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| #if __cplusplus >= 201103L |
| template<typename _Tp> |
| void |
| constexpr_bitwise_operators() |
| { |
| constexpr _Tp a = _Tp(); |
| constexpr _Tp b = _Tp(); |
| constexpr _Tp c1 __attribute__((unused)) = a | b; |
| constexpr _Tp c2 __attribute__((unused)) = a & b; |
| constexpr _Tp c3 __attribute__((unused)) = a ^ b; |
| constexpr _Tp c4 __attribute__((unused)) = ~b; |
| } |
| #endif |
| |
| template<typename _Tp> |
| void |
| bitwise_operators() |
| { |
| _Tp a = _Tp(); |
| _Tp b = _Tp(); |
| a | b; |
| a & b; |
| a ^ b; |
| ~b; |
| } |
| |
| template<typename _Tp> |
| void |
| bitwise_assignment_operators() |
| { |
| #if __cplusplus >= 201103L |
| _Tp a{}; |
| _Tp b{}; |
| #else |
| _Tp a = _Tp(); |
| _Tp b = _Tp(); |
| #endif |
| a |= b; // set |
| a &= ~b; // clear |
| a ^= b; |
| } |
| |
| // 17.3.2.1.2 - Bitmask types [lib.bitmask.types] |
| // bitmask_operators |
| template<typename _BitmTp> |
| void |
| bitmask_operators() |
| { |
| bitwise_operators<_BitmTp>(); |
| bitwise_assignment_operators<_BitmTp>(); |
| } |
| |
| struct has_bitwise_operators |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| a |= b; // set |
| a &= ~b; // clear |
| a ^= b; |
| } |
| _Tp a; |
| _Tp b; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| #if __cplusplus >= 201103L |
| |
| struct constexpr_comparison_eq_ne |
| { |
| template<typename _Tp1, typename _Tp2 = _Tp1> |
| void |
| operator()() |
| { |
| static_assert(_Tp1() == _Tp2(), "eq"); |
| static_assert(!(_Tp1() != _Tp2()), "ne"); |
| } |
| }; |
| |
| struct constexpr_comparison_operators |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| static_assert(!(_Tp() < _Tp()), "less"); |
| static_assert(_Tp() <= _Tp(), "leq"); |
| static_assert(!(_Tp() > _Tp()), "more"); |
| static_assert(_Tp() >= _Tp(), "meq"); |
| static_assert(_Tp() == _Tp(), "eq"); |
| static_assert(!(_Tp() != _Tp()), "ne"); |
| } |
| }; |
| |
| struct has_trivial_cons_dtor |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| typedef std::is_trivially_default_constructible<_Tp> ctor_p; |
| static_assert(ctor_p::value, "default constructor not trivial"); |
| |
| typedef std::is_trivially_destructible<_Tp> dtor_p; |
| static_assert(dtor_p::value, "destructor not trivial"); |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| struct has_trivial_dtor |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| typedef std::is_trivially_destructible<_Tp> dtor_p; |
| static_assert(dtor_p::value, "destructor not trivial"); |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test standard layout |
| struct standard_layout |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| typedef std::is_standard_layout<_Tp> standard_layout_p; |
| static_assert(standard_layout_p::value, "not standard_layout"); |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| #endif |
| |
| // Generator to test base class |
| struct has_required_base_class |
| { |
| template<typename _TBase, typename _TDerived> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| const _TDerived& obj = __a; |
| const _TBase* base __attribute__((unused)) = &obj; |
| } |
| |
| _TDerived __a; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test assignment operator. |
| struct assignable |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { __v1 = __v2; } |
| |
| _Tp __v1; |
| _Tp __v2; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test default constructor. |
| struct default_constructible |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { _Tp __v __attribute__((unused)); } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test copy constructor. |
| struct copy_constructible |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { _Tp __v2(__v1); } |
| |
| _Tp __v1; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test direct initialization, single value constructor. |
| struct single_value_constructible |
| { |
| template<typename _Ttype, typename _Tvalue> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { _Ttype __v(__a); } |
| |
| _Tvalue __a; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| #if __cplusplus >= 201103L |
| // Generator to test non-explicit default constructor. |
| struct implicitly_default_constructible |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| struct Aggregate { _Tp v; }; |
| |
| void __constraint() |
| { Aggregate __v __attribute__((unused)) = { }; } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test default constructor. |
| struct constexpr_default_constructible |
| { |
| template<typename _Tp, bool _IsLitp = __is_literal_type(_Tp)> |
| struct _Concept; |
| |
| // NB: _Tp must be a literal type. |
| // Have to have user-defined default ctor for this to work, |
| // or implicit default ctor must initialize all members. |
| template<typename _Tp> |
| struct _Concept<_Tp, true> |
| { |
| void __constraint() |
| { constexpr _Tp __obj; } |
| }; |
| |
| // Non-literal type, declare local static and verify no |
| // constructors generated for _Tp within the translation unit. |
| template<typename _Tp> |
| struct _Concept<_Tp, false> |
| { |
| void __constraint() |
| { static _Tp __obj; } |
| }; |
| |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| _Concept<_Tp> c; |
| c.__constraint(); |
| } |
| }; |
| |
| // Generator to test defaulted default constructor. |
| struct constexpr_defaulted_default_constructible |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { constexpr _Tp __v __attribute__((unused)) { }; } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| struct constexpr_single_value_constructible |
| { |
| template<typename _Ttesttype, typename _Tvaluetype, |
| bool _IsLitp = __is_literal_type(_Ttesttype)> |
| struct _Concept; |
| |
| // NB: _Tvaluetype and _Ttesttype must be literal types. |
| // Additional constraint on _Tvaluetype needed. Either assume |
| // user-defined default ctor as per |
| // constexpr_default_constructible and provide no initializer, |
| // provide an initializer, or assume empty-list init-able. Choose |
| // the latter. |
| template<typename _Ttesttype, typename _Tvaluetype> |
| struct _Concept<_Ttesttype, _Tvaluetype, true> |
| { |
| void __constraint() |
| { |
| constexpr _Tvaluetype __v { }; |
| constexpr _Ttesttype __obj(__v); |
| } |
| }; |
| |
| template<typename _Ttesttype, typename _Tvaluetype> |
| struct _Concept<_Ttesttype, _Tvaluetype, false> |
| { |
| void __constraint() |
| { |
| const _Tvaluetype __v { }; |
| static _Ttesttype __obj(__v); |
| } |
| }; |
| |
| template<typename _Ttesttype, typename _Tvaluetype> |
| void |
| operator()() |
| { |
| _Concept<_Ttesttype, _Tvaluetype> c; |
| c.__constraint(); |
| } |
| }; |
| #endif |
| |
| // Generator to test direct list initialization |
| #if __cplusplus >= 201103L |
| struct direct_list_initializable |
| { |
| template<typename _Ttype, typename _Tvalue> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| _Ttype __v1 { }; // default ctor |
| _Ttype __v2 { __a }; // single-argument ctor |
| } |
| |
| _Tvalue __a; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| #endif |
| |
| // Generator to test copy list initialization, aggregate initialization |
| struct copy_list_initializable |
| { |
| template<typename _Ttype, typename _Tvalue> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { _Ttype __v __attribute__((unused)) = {__a}; } |
| |
| _Tvalue __a; |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test integral conversion operator |
| struct integral_convertable |
| { |
| template<typename _Ttype, typename _Tvalue> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| _Tvalue __v0(0); |
| _Tvalue __v1(1); |
| _Ttype __a(__v1); |
| __v0 = __a; |
| |
| VERIFY( __v1 == __v0 ); |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| // Generator to test integral assignment operator |
| struct integral_assignable |
| { |
| template<typename _Ttype, typename _Tvalue> |
| void |
| operator()() |
| { |
| struct _Concept |
| { |
| void __constraint() |
| { |
| _Tvalue __v0(0); |
| _Tvalue __v1(1); |
| _Ttype __a(__v0); |
| __a = __v1; |
| _Tvalue __vr = __a; |
| |
| VERIFY( __v1 == __vr ); |
| } |
| }; |
| |
| void (_Concept::*__x)() __attribute__((unused)) |
| = &_Concept::__constraint; |
| } |
| }; |
| |
| #if __cplusplus >= 201103L |
| // Generator to test lowering requirements for compare-and-exchange. |
| template<std::memory_order _Torder> |
| struct compare_exchange_order_lowering |
| { |
| template<typename _Tp> |
| void |
| operator()() |
| { |
| std::atomic<_Tp> __x; |
| _Tp __expected = 0; |
| __x.compare_exchange_strong(__expected, 1, _Torder); |
| __x.compare_exchange_weak(__expected, 1, _Torder); |
| } |
| }; |
| #endif |
| |
| #if __cplusplus >= 201402L |
| // Check that bitmask type T supports all the required operators, |
| // with the required semantics. Check that each bitmask element |
| // has a distinct, nonzero value, and that each bitmask constant |
| // has no bits set which do not correspond to a bitmask element. |
| template<typename T> |
| constexpr bool |
| test_bitmask_values(std::initializer_list<T> elements, |
| std::initializer_list<T> constants = {}) |
| { |
| const T t0{}; |
| |
| if (!(t0 == t0)) |
| return false; |
| if (t0 != t0) |
| return false; |
| |
| if (t0 & t0) |
| return false; |
| if (t0 | t0) |
| return false; |
| if (t0 ^ t0) |
| return false; |
| |
| T all = t0; |
| |
| for (auto t : elements) |
| { |
| // Each bitmask element has a distinct value. |
| if (t & all) |
| return false; |
| |
| // Each bitmask element has a nonzero value. |
| if (!bool(t)) |
| return false; |
| |
| // Check operators |
| |
| if (!(t == t)) |
| return false; |
| if (t != t) |
| return false; |
| if (t == t0) |
| return false; |
| if (t == all) |
| return false; |
| |
| if (t & t0) |
| return false; |
| if ((t | t0) != t) |
| return false; |
| if ((t ^ t0) != t) |
| return false; |
| |
| if ((t & t) != t) |
| return false; |
| if ((t | t) != t) |
| return false; |
| if (t ^ t) |
| return false; |
| |
| T t1 = t; |
| if ((t1 &= t) != t) |
| return false; |
| if ((t1 |= t) != t) |
| return false; |
| if (t1 ^= t) |
| return false; |
| |
| t1 = all; |
| if ((t1 &= t) != (all & t)) |
| return false; |
| t1 = all; |
| if ((t1 |= t) != (all | t)) |
| return false; |
| t1 = all; |
| if ((t1 ^= t) != (all ^ t)) |
| return false; |
| |
| all |= t; |
| if (!(all & t)) |
| return false; |
| } |
| |
| for (auto t : constants) |
| { |
| // Check that bitmask constants are composed of the bitmask elements. |
| if ((t & all) != t) |
| return false; |
| if ((t | all) != all) |
| return false; |
| } |
| |
| return true; |
| } |
| #endif // C++14 |
| |
| |
| } // namespace __gnu_test |
| #endif |