1 // Copyright 2016-2021 Francesco Biscani (bluescarni@gmail.com) 2 // 3 // This file is part of the mp++ library. 4 // 5 // This Source Code Form is subject to the terms of the Mozilla 6 // Public License v. 2.0. If a copy of the MPL was not distributed 7 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 #ifndef MPPP_CONCEPTS_HPP 10 #define MPPP_CONCEPTS_HPP 11 12 #include <mp++/config.hpp> 13 14 #include <complex> 15 #include <cstddef> 16 #include <string> 17 #include <type_traits> 18 19 #if defined(MPPP_HAVE_STRING_VIEW) 20 #include <string_view> 21 #endif 22 23 #include <mp++/detail/type_traits.hpp> 24 25 namespace mppp 26 { 27 28 // Type trait to check if T is a C++ integral type, including possibly __(u)int128_t. 29 // NOTE: mppp::detail::is_integral, for consistency with std::is_integral, will be true also for cv qualified 30 // integral types. is_cpp_integral, however, is used in contexts where the cv qualifications 31 // matter, and we want this type trait not to be satisfied by integral types which are, e.g., 32 // const qualified. 33 template <typename T> 34 using is_cpp_integral = detail::conjunction<detail::is_integral<T>, std::is_same<detail::remove_cv_t<T>, T>>; 35 36 #if defined(MPPP_HAVE_CONCEPTS) 37 38 template <typename T> 39 MPPP_CONCEPT_DECL cpp_integral = is_cpp_integral<T>::value; 40 41 #endif 42 43 template <typename T> 44 using is_cpp_unsigned_integral = detail::conjunction<is_cpp_integral<T>, detail::is_unsigned<T>>; 45 46 #if defined(MPPP_HAVE_CONCEPTS) 47 48 template <typename T> 49 MPPP_CONCEPT_DECL cpp_unsigned_integral = is_cpp_unsigned_integral<T>::value; 50 51 #endif 52 53 template <typename T> 54 using is_cpp_signed_integral = detail::conjunction<is_cpp_integral<T>, detail::is_signed<T>>; 55 56 #if defined(MPPP_HAVE_CONCEPTS) 57 58 template <typename T> 59 MPPP_CONCEPT_DECL cpp_signed_integral = is_cpp_signed_integral<T>::value; 60 61 #endif 62 63 template <typename T> 64 using is_cpp_floating_point = detail::conjunction<std::is_floating_point<T>, std::is_same<detail::remove_cv_t<T>, T>>; 65 66 #if defined(MPPP_HAVE_CONCEPTS) 67 68 template <typename T> 69 MPPP_CONCEPT_DECL cpp_floating_point = is_cpp_floating_point<T>::value; 70 71 #endif 72 73 template <typename T> 74 using is_cpp_arithmetic = detail::disjunction<is_cpp_integral<T>, is_cpp_floating_point<T>>; 75 76 #if defined(MPPP_HAVE_CONCEPTS) 77 78 template <typename T> 79 MPPP_CONCEPT_DECL cpp_arithmetic = is_cpp_arithmetic<T>::value; 80 81 #endif 82 83 template <typename T> 84 using is_cpp_complex = detail::disjunction<std::is_same<T, std::complex<float>>, std::is_same<T, std::complex<double>>, 85 std::is_same<T, std::complex<long double>>>; 86 87 #if defined(MPPP_HAVE_CONCEPTS) 88 89 template <typename T> 90 MPPP_CONCEPT_DECL cpp_complex = is_cpp_complex<T>::value; 91 92 #endif 93 94 namespace detail 95 { 96 97 // NOTE: remove_pointer_t removes the top level qualifiers of the pointer as well: 98 // http://en.cppreference.com/w/cpp/types/remove_pointer 99 // After removal of pointer, we could still have a type which is cv qualified. Thus, 100 // we remove cv qualifications after pointer removal. 101 template <typename T> 102 using is_char_pointer = conjunction<std::is_pointer<T>, std::is_same<remove_cv_t<remove_pointer_t<T>>, char>>; 103 104 } // namespace detail 105 106 template <typename T> 107 using is_string_type 108 = detail::disjunction<std::is_same<detail::remove_cv_t<T>, std::string>, detail::is_char_pointer<T>, 109 // NOTE: detail::remove_cv_t does remove cv qualifiers from arrays. 110 detail::conjunction<std::is_array<detail::remove_cv_t<T>>, 111 std::is_same<detail::remove_extent_t<detail::remove_cv_t<T>>, char>> 112 #if defined(MPPP_HAVE_STRING_VIEW) 113 , 114 std::is_same<detail::remove_cv_t<T>, std::string_view> 115 #endif 116 >; 117 118 #if defined(MPPP_HAVE_CONCEPTS) 119 120 template <typename T> 121 MPPP_CONCEPT_DECL string_type = is_string_type<T>::value; 122 123 #endif 124 125 } // namespace mppp 126 127 #endif 128