qxLib
concepts.h
Go to the documentation of this file.
1 /**
2 
3  @file concepts.h
4  @author Khrapov
5  @date 2.11.2021
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <type_traits>
12 #include <utility>
13 
14 namespace qx
15 {
16 
17 template<class T>
18 concept is_enumeration = std::is_enum_v<T>;
19 
20 template<class T>
21 concept enumeration_c = is_enumeration<T>;
22 
23 template<class T>
24 concept is_iterator = requires(T) { typename T::iterator_category; };
25 
26 template<class T>
27 concept is_random_access_iterator =
28  is_iterator<T> && std::derived_from<typename T::iterator_category, std::random_access_iterator_tag>;
29 
30 template<class T, class return_t, class... args_t>
31 concept callable_c = requires(T t, args_t&&... args) {
32  { t(std::forward<args_t>(args)...) } -> std::convertible_to<return_t>;
33 };
34 
35 // won't work for base_args_t containing template template or type template parameters
36 template<class derived_t, template<class... base_args_t> class base_t, class... partial_specialization_args_t>
37 concept derived_from_template_c = requires(const derived_t& derived) {
38  []<class... base_args_t>(const base_t<partial_specialization_args_t..., base_args_t...>&)
39  {
40  }(derived);
41 };
42 
43 namespace details
44 {
45 
46 template<class range_t, class T>
47 concept is_iterator_arrow_operator_of_t_type = requires(range_t t) {
48  { t.begin().operator->() } -> std::convertible_to<const T*>;
49  { t.end().operator->() } -> std::convertible_to<const T*>;
50 };
51 
52 template<class range_t, class T>
53 concept is_iterator_t_pointer = requires(range_t t) {
54  { t.begin() } -> std::convertible_to<const T*>;
55  { t.end() } -> std::convertible_to<const T*>;
56 };
57 
58 } // namespace details
59 
60 template<class range_t, class T>
61 concept range_of_t_c =
62  details::is_iterator_arrow_operator_of_t_type<range_t, T> || details::is_iterator_t_pointer<range_t, T>;
63 
64 } // namespace qx