소스 검색

refactor: support fluent map key handling

Sam Jaffe 3 년 전
부모
커밋
23c7e406b5
1개의 변경된 파일16개의 추가작업 그리고 6개의 파일을 삭제
  1. 16 6
      include/string_utils/cast.h

+ 16 - 6
include/string_utils/cast.h

@@ -49,6 +49,11 @@ struct is_associative<T, std::void_t<typename T::mapped_type>> : std::true_type
 template <typename, typename = void> struct is_container : std::false_type {};
 template <typename T>
 struct is_container<T, std::void_t<typename T::value_type>> : std::true_type {};
+
+template <typename T> struct decay { using type = std::decay_t<T>; };
+template <template <typename...> class C, typename... Ts>
+struct decay<C<Ts...>> { using type = C<std::decay_t<Ts>...>; };
+template <typename T> using decay_t = typename decay<std::decay_t<T>>::type;
 }
 
 namespace string_utils::detail {
@@ -83,11 +88,9 @@ bool cast(std::vector<S> const &strs, T & to) noexcept {
     return strs.size() == N && detail::cast_tuple(strs, to, std::make_index_sequence<N>{});
   } else if constexpr (detail::is_associative<T>{}) {
     for (S const &elem : strs) {
-      size_t const pos = elem.find('=');
-      auto [key, sk] = cast<typename T::key_type>(elem.substr(0, pos));
-      auto [value, sv] = cast<typename T::key_type>(elem.substr(pos + 1));
-      if (pos == S::npos || !sk || !sv) { return false; }
-      to.insert(std::move(key), std::move(value));
+      auto [tmp, success] = cast<typename T::value_type>(detail::keyval(elem));
+      if (!success) { return false; }
+      to.insert(std::move(tmp));
     }
   } else if constexpr (detail::is_container<T>{}) {
     for (S const &elem : strs) {
@@ -178,16 +181,23 @@ bool cast_number(std::string_view str, T & to, F func) noexcept {
   to = func(str.data(), &counter);
   return counter == str.end();
 }
+
+template <typename S> std::vector<S> keyval(S const &input) {
+  size_t const pos = input.find('=');
+  return pos == S::npos ? std::vector{input}
+                        : std::vector{input.substr(0, pos), input.substr(pos + 1)};
+}
 }
 
 // This should be placed last in the file
 namespace string_utils {
 template <typename T, typename S> std::pair<T, bool> cast(S const & str) noexcept {
   using string_utils::cast;
-  std::pair<std::decay_t<T>, bool> rval;
+  std::pair<detail::decay_t<T>, bool> rval;
   rval.second = cast(str, rval.first);
   return rval;
 }
+
 }
 
 #undef CAST_NUMBER_IMPL