olp-cpp-sdk  1.22.0
try_emplace.h
1 /*
2  * Copyright (C) 2019 HERE Europe B.V.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  * License-Filename: LICENSE
18  */
19 
20 #pragma once
21 
22 #include <map>
23 #include <type_traits>
24 #include <unordered_map>
25 #include <utility>
26 
27 /*
28  * Workaround for not having std::map::try_emplace and
29  * std::unordered_map::try_emplace
30  * until c++17 is available.
31  * Note - std::piecewise_construct and emplace are not supported by gcc 4.7
32  * therefore for this compiler first argument is not deduced as map::key_type
33  * and insert is used
34  * instead of emplace.
35  */
36 
37 namespace olp {
38 namespace porting {
39 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ <= 7) && \
40  defined(__GLIBCXX__) && !defined(__clang__)
41 
42 template <typename MAP_TYPE_CONT, typename FIRST, typename SECOND>
43 inline std::pair<typename MAP_TYPE_CONT::iterator, bool> try_emplace(
44  MAP_TYPE_CONT& map_type_cont, FIRST&& first, SECOND&& second) {
45  return map_type_cont.insert(
46  std::make_pair(std::forward<FIRST>(first), std::forward<SECOND>(second)));
47 }
48 
49 template <typename MAP_TYPE_CONT, typename FIRST, typename SECOND,
50  typename... ARGS>
51 inline std::pair<typename MAP_TYPE_CONT::iterator, bool> try_emplace(
52  MAP_TYPE_CONT& map_type_cont, FIRST&& first, SECOND&& second,
53  ARGS&&... args) {
54  return map_type_cont.insert(std::make_pair(
55  std::forward<FIRST>(first),
56  typename MAP_TYPE_CONT::mapped_type(std::forward<SECOND>(second),
57  std::forward<ARGS>(args)...)));
58 }
59 
60 #else
61 
62 template <class T>
63 struct IsMap : public std::false_type {};
64 
65 template <class... ARGS>
66 struct IsMap<std::map<ARGS...> > : public std::true_type {};
67 
68 template <class T>
69 struct IsUnorderedMap : public std::false_type {};
70 
71 template <class... ARGS>
72 struct IsUnorderedMap<std::unordered_map<ARGS...> > : public std::true_type {};
73 
74 /**** For std::map ****/
75 
76 template <class MAP_TYPE_CONT, class... ARGS>
77 inline typename std::enable_if<
79  std::pair<typename MAP_TYPE_CONT::iterator, bool> >::type
80 try_emplace(MAP_TYPE_CONT& map_type_cont,
81  typename MAP_TYPE_CONT::key_type&& key, ARGS&&... args) {
82  auto it = map_type_cont.lower_bound(key);
83  if (it == map_type_cont.end() || map_type_cont.key_comp()(key, it->first)) {
84  return {map_type_cont.emplace_hint(
85  it, std::piecewise_construct,
86  std::forward_as_tuple(
87  std::forward<typename MAP_TYPE_CONT::key_type>(key)),
88  std::forward_as_tuple(std::forward<ARGS>(args)...)),
89  true};
90  }
91  return {it, false};
92 }
93 
94 template <class MAP_TYPE_CONT, class... ARGS>
95 inline typename std::enable_if<
96  IsMap<MAP_TYPE_CONT>::value,
97  std::pair<typename MAP_TYPE_CONT::iterator, bool> >::type
98 try_emplace(MAP_TYPE_CONT& map_type_cont,
99  const typename MAP_TYPE_CONT::key_type& key, ARGS&&... args) {
100  auto it = map_type_cont.lower_bound(key);
101  if (it == map_type_cont.end() || map_type_cont.key_comp()(key, it->first)) {
102  return {map_type_cont.emplace_hint(
103  it, std::piecewise_construct, std::forward_as_tuple(key),
104  std::forward_as_tuple(std::forward<ARGS>(args)...)),
105  true};
106  }
107  return {it, false};
108 }
109 
110 /**** For std::unordered_map ****/
111 
112 template <class MAP_TYPE_CONT, class... ARGS>
113 inline typename std::enable_if<
114  IsUnorderedMap<MAP_TYPE_CONT>::value,
115  std::pair<typename MAP_TYPE_CONT::iterator, bool> >::type
116 try_emplace(MAP_TYPE_CONT& map_type_cont,
117  typename MAP_TYPE_CONT::key_type&& key, ARGS&&... args) {
118  auto it = map_type_cont.find(key);
119  if (it == map_type_cont.end()) {
120  return map_type_cont.emplace(
121  std::piecewise_construct,
122  std::forward_as_tuple(
123  std::forward<typename MAP_TYPE_CONT::key_type>(key)),
124  std::forward_as_tuple(std::forward<ARGS>(args)...));
125  }
126  return {it, false};
127 }
128 
129 template <class MAP_TYPE_CONT, class... ARGS>
130 inline typename std::enable_if<
131  IsUnorderedMap<MAP_TYPE_CONT>::value,
132  std::pair<typename MAP_TYPE_CONT::iterator, bool> >::type
133 try_emplace(MAP_TYPE_CONT& map_type_cont,
134  const typename MAP_TYPE_CONT::key_type& key, ARGS&&... args) {
135  auto it = map_type_cont.find(key);
136  if (it == map_type_cont.end()) {
137  return map_type_cont.emplace(
138  std::piecewise_construct, std::forward_as_tuple(key),
139  std::forward_as_tuple(std::forward<ARGS>(args)...));
140  }
141  return {it, false};
142 }
143 
144 #endif
145 } // namespace porting
146 } // namespace olp
Rules all the other namespaces.
Definition: AppleSignInProperties.h:24
Definition: try_emplace.h:63
Definition: try_emplace.h:69