|
@@ -13,11 +13,8 @@
|
|
|
#include <string>
|
|
#include <string>
|
|
|
#include <type_traits>
|
|
#include <type_traits>
|
|
|
#include <utility>
|
|
#include <utility>
|
|
|
-
|
|
|
|
|
-#if __has_include(<variant>) && __cplusplus > 201402L
|
|
|
|
|
-#define STRING_UTIL_CAST_STD_VARIANT
|
|
|
|
|
#include <variant>
|
|
#include <variant>
|
|
|
-#endif
|
|
|
|
|
|
|
+#include <vector>
|
|
|
|
|
|
|
|
#include "any_of.h"
|
|
#include "any_of.h"
|
|
|
|
|
|
|
@@ -30,7 +27,6 @@
|
|
|
|
|
|
|
|
namespace string_utils { namespace traits {
|
|
namespace string_utils { namespace traits {
|
|
|
template <typename T, typename = void> struct is_stringy : std::false_type {};
|
|
template <typename T, typename = void> struct is_stringy : std::false_type {};
|
|
|
-#if defined(STRING_UTIL_CAST_STD_VARIANT)
|
|
|
|
|
|
|
|
|
|
template <typename> struct is_variant : std::false_type {};
|
|
template <typename> struct is_variant : std::false_type {};
|
|
|
template <typename... Ts>
|
|
template <typename... Ts>
|
|
@@ -40,21 +36,19 @@ template <typename T>
|
|
|
struct is_stringy<
|
|
struct is_stringy<
|
|
|
T, std::enable_if_t<std::is_constructible<T, std::string const &>{} &&
|
|
T, std::enable_if_t<std::is_constructible<T, std::string const &>{} &&
|
|
|
!is_variant<T>{}>> : std::true_type {};
|
|
!is_variant<T>{}>> : std::true_type {};
|
|
|
-#else
|
|
|
|
|
-template <typename T>
|
|
|
|
|
-struct is_stringy<
|
|
|
|
|
- T, std::enable_if_t<std::is_constructible<T, std::string const &>{}>>
|
|
|
|
|
- : std::true_type {};
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
+
|
|
|
}}
|
|
}}
|
|
|
|
|
|
|
|
namespace string_utils {
|
|
namespace string_utils {
|
|
|
template <typename T> std::pair<T, bool> cast(std::string const & str);
|
|
template <typename T> std::pair<T, bool> cast(std::string const & str);
|
|
|
template <typename T> bool cast(std::string const & str, std::optional<T> & to);
|
|
template <typename T> bool cast(std::string const & str, std::optional<T> & to);
|
|
|
-#if defined(STRING_UTIL_CAST_STD_VARIANT)
|
|
|
|
|
template <typename... Ts>
|
|
template <typename... Ts>
|
|
|
bool cast(std::string const & str, std::variant<Ts...> & to);
|
|
bool cast(std::string const & str, std::variant<Ts...> & to);
|
|
|
-#endif
|
|
|
|
|
|
|
+
|
|
|
|
|
+template <typename... Ts>
|
|
|
|
|
+bool cast(std::vector<std::string> const & str, std::tuple<Ts...> & to);
|
|
|
|
|
+template <typename K, typename V>
|
|
|
|
|
+bool cast(std::vector<std::string> const & str, std::pair<K, V> & to);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
namespace string_utils {
|
|
namespace string_utils {
|
|
@@ -89,42 +83,51 @@ inline bool cast(std::string const & str, bool & to) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#if defined(STRING_UTIL_CAST_STD_VARIANT)
|
|
|
|
|
namespace string_utils::detail {
|
|
namespace string_utils::detail {
|
|
|
-template <size_t I, typename... Ts>
|
|
|
|
|
-bool _cast(std::string const & str, std::variant<Ts...> & to) {
|
|
|
|
|
- auto [rval, found] = cast<std::tuple_element_t<I, std::tuple<Ts...>>>(str);
|
|
|
|
|
|
|
+template <typename T, typename... Ts>
|
|
|
|
|
+bool cast_alternative(std::string const & str, std::variant<Ts...> & to) {
|
|
|
|
|
+ auto [rval, found] = cast<T>(str);
|
|
|
if (found) { to = std::move(rval); }
|
|
if (found) { to = std::move(rval); }
|
|
|
return found;
|
|
return found;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// This is needed due to a compiler bug in Clang that fails to properly compile
|
|
|
|
|
-// fold-expressions.
|
|
|
|
|
-template <size_t I, typename... Ts>
|
|
|
|
|
-bool _cast_chain(std::string const & str, std::variant<Ts...> & to) {
|
|
|
|
|
- if constexpr (I == sizeof...(Ts)) {
|
|
|
|
|
- return false;
|
|
|
|
|
- } else {
|
|
|
|
|
- return _cast<I>(str, to) || _cast_chain<I + 1>(str, to);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+template <typename Tuple, size_t... Is>
|
|
|
|
|
+bool cast_tuple(std::vector<std::string> const & str, Tuple & to,
|
|
|
|
|
+ std::index_sequence<Is...>) {
|
|
|
|
|
+ return ((cast(str[Is], std::get<Is>(to))) && ...);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template <typename Tuple>
|
|
|
|
|
+bool cast_tuple(std::vector<std::string> const & str, Tuple & to) {
|
|
|
|
|
+ constexpr size_t N = std::tuple_size_v<Tuple>;
|
|
|
|
|
+ return str.size() == N && cast_tuple(str, to, std::make_index_sequence<N>{});
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
namespace string_utils {
|
|
namespace string_utils {
|
|
|
|
|
+
|
|
|
template <typename... Ts>
|
|
template <typename... Ts>
|
|
|
bool cast(std::string const & str, std::variant<Ts...> & to) {
|
|
bool cast(std::string const & str, std::variant<Ts...> & to) {
|
|
|
- return detail::_cast_chain<0>(str, to);
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ return (detail::cast_alternative<Ts>(str, to) || ...);
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
-namespace string_utils {
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
|
bool cast(std::string const & str, std::optional<T> & to) {
|
|
bool cast(std::string const & str, std::optional<T> & to) {
|
|
|
auto [value, success] = cast<T>(str);
|
|
auto [value, success] = cast<T>(str);
|
|
|
if (success) { to = std::move(value); }
|
|
if (success) { to = std::move(value); }
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+template <typename... Ts>
|
|
|
|
|
+bool cast(std::vector<std::string> const & str, std::tuple<Ts...> & to) {
|
|
|
|
|
+ return detail::cast_tuple(str, to);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template <typename K, typename V>
|
|
|
|
|
+bool cast(std::vector<std::string> const & str, std::pair<K, V> & to) {
|
|
|
|
|
+ return detail::cast_tuple(str, to);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// This should be placed last in the file
|
|
// This should be placed last in the file
|