]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | #ifndef BOOST_MP11_MAP_HPP_INCLUDED |
2 | #define BOOST_MP11_MAP_HPP_INCLUDED | |
3 | ||
4 | // Copyright 2015-2017 Peter Dimov. | |
5 | // | |
6 | // Distributed under the Boost Software License, Version 1.0. | |
7 | // | |
8 | // See accompanying file LICENSE_1_0.txt or copy at | |
9 | // http://www.boost.org/LICENSE_1_0.txt | |
10 | ||
11 | #include <boost/mp11/detail/mp_map_find.hpp> | |
12 | #include <boost/mp11/list.hpp> | |
13 | #include <boost/mp11/integral.hpp> | |
14 | #include <boost/mp11/utility.hpp> | |
15 | #include <boost/mp11/algorithm.hpp> | |
16 | #include <boost/mp11/function.hpp> | |
17 | #include <boost/mp11/set.hpp> | |
18 | #include <type_traits> | |
19 | ||
20 | namespace boost | |
21 | { | |
22 | namespace mp11 | |
23 | { | |
24 | ||
25 | // mp_map_contains<M, K> | |
26 | template<class M, class K> using mp_map_contains = mp_not<std::is_same<mp_map_find<M, K>, void>>; | |
27 | ||
28 | // mp_map_insert<M, T> | |
29 | template<class M, class T> using mp_map_insert = mp_if< mp_map_contains<M, mp_first<T>>, M, mp_push_back<M, T> >; | |
30 | ||
31 | // mp_map_replace<M, T> | |
32 | namespace detail | |
33 | { | |
34 | ||
35 | template<class M, class T> struct mp_map_replace_impl; | |
36 | ||
37 | template<template<class...> class M, class... U, class T> struct mp_map_replace_impl<M<U...>, T> | |
38 | { | |
39 | using K = mp_first<T>; | |
40 | ||
41 | // mp_replace_if is inlined here using a struct _f because of msvc-14.0 | |
42 | ||
43 | template<class V> struct _f { using type = mp_if< std::is_same<mp_first<V>, K>, T, V >; }; | |
44 | ||
45 | using type = mp_if< mp_map_contains<M<U...>, K>, M<typename _f<U>::type...>, M<U..., T> >; | |
46 | }; | |
47 | ||
48 | } // namespace detail | |
49 | ||
50 | template<class M, class T> using mp_map_replace = typename detail::mp_map_replace_impl<M, T>::type; | |
51 | ||
52 | // mp_map_update<M, T, F> | |
53 | namespace detail | |
54 | { | |
55 | ||
56 | template<class M, class T, template<class...> class F> struct mp_map_update_impl | |
57 | { | |
58 | template<class U> using _f = std::is_same<mp_first<T>, mp_first<U>>; | |
59 | ||
60 | // _f3<L<X, Y...>> -> L<X, F<X, Y...>> | |
92f5a8d4 | 61 | template<class L> using _f3 = mp_assign<L, mp_list<mp_first<L>, mp_rename<L, F> > >; |
b32b8144 FG |
62 | |
63 | using type = mp_if< mp_map_contains<M, mp_first<T>>, mp_transform_if<_f, _f3, M>, mp_push_back<M, T> >; | |
64 | }; | |
65 | ||
66 | } // namespace detail | |
67 | ||
68 | template<class M, class T, template<class...> class F> using mp_map_update = typename detail::mp_map_update_impl<M, T, F>::type; | |
69 | template<class M, class T, class Q> using mp_map_update_q = mp_map_update<M, T, Q::template fn>; | |
70 | ||
71 | // mp_map_erase<M, K> | |
72 | namespace detail | |
73 | { | |
74 | ||
75 | template<class M, class K> struct mp_map_erase_impl | |
76 | { | |
77 | template<class T> using _f = std::is_same<mp_first<T>, K>; | |
78 | using type = mp_remove_if<M, _f>; | |
79 | }; | |
80 | ||
81 | } // namespace detail | |
82 | ||
83 | template<class M, class K> using mp_map_erase = typename detail::mp_map_erase_impl<M, K>::type; | |
84 | ||
85 | // mp_map_keys<M> | |
86 | template<class M> using mp_map_keys = mp_transform<mp_first, M>; | |
87 | ||
88 | // mp_is_map<M> | |
89 | namespace detail | |
90 | { | |
91 | ||
92 | template<class L> struct mp_is_map_element: mp_false | |
93 | { | |
94 | }; | |
95 | ||
96 | template<template<class...> class L, class T1, class... T> struct mp_is_map_element<L<T1, T...>>: mp_true | |
97 | { | |
98 | }; | |
99 | ||
100 | template<class M> using mp_keys_are_set = mp_is_set<mp_map_keys<M>>; | |
101 | ||
102 | template<class M> struct mp_is_map_impl | |
103 | { | |
104 | using type = mp_false; | |
105 | }; | |
106 | ||
107 | template<template<class...> class M, class... T> struct mp_is_map_impl<M<T...>> | |
108 | { | |
109 | using type = mp_eval_if<mp_not<mp_all<mp_is_map_element<T>...>>, mp_false, mp_keys_are_set, M<T...>>; | |
110 | }; | |
111 | ||
112 | } // namespace detail | |
113 | ||
114 | template<class M> using mp_is_map = typename detail::mp_is_map_impl<M>::type; | |
115 | ||
116 | } // namespace mp11 | |
117 | } // namespace boost | |
118 | ||
119 | #endif // #ifndef BOOST_MP11_MAP_HPP_INCLUDED |