6 #include "StringTools.hpp" 10 #include <type_traits> 21 enum class enabler {};
24 constexpr enabler dummy = {};
32 template <
bool B,
class T =
void>
using enable_if_t =
typename std::enable_if<B, T>::type;
35 template <
typename... Ts>
struct make_void {
using type = void; };
38 template <
typename... Ts>
using void_t =
typename make_void<Ts...>::type;
41 template <
bool B,
class T,
class F>
using conditional_t =
typename std::conditional<B, T, F>::type;
44 template <
typename T>
struct is_vector : std::false_type {};
47 template <
class T,
class A>
struct is_vector<std::vector<T, A>> : std::true_type {};
50 template <
typename T>
struct is_bool : std::false_type {};
53 template <>
struct is_bool<bool> : std::true_type {};
59 template <
typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
62 template <
typename T>
struct is_shared_ptr<const std::shared_ptr<T>> : std::true_type {};
73 template <>
struct IsMemberType<const char *> {
using type = std::string; };
83 typename std::conditional<is_copyable_ptr<T>::value,
typename std::pointer_traits<T>::element_type, T>::type;
91 template <
typename T,
typename _ =
void>
struct pair_adaptor : std::false_type {
92 using value_type =
typename T::value_type;
93 using first_type =
typename std::remove_const<value_type>::type;
94 using second_type =
typename std::remove_const<value_type>::type;
97 template <
typename Q>
static auto first(Q &&pair_value) -> decltype(std::forward<Q>(pair_value)) {
98 return std::forward<Q>(pair_value);
101 template <
typename Q>
static auto second(Q &&pair_value) -> decltype(std::forward<Q>(pair_value)) {
102 return std::forward<Q>(pair_value);
108 template <
typename T>
111 conditional_t<false, void_t<typename T::value_type::first_type, typename T::value_type::second_type>, void>>
113 using value_type =
typename T::value_type;
114 using first_type =
typename std::remove_const<typename value_type::first_type>::type;
115 using second_type =
typename std::remove_const<typename value_type::second_type>::type;
118 template <
typename Q>
static auto first(Q &&pair_value) -> decltype(std::get<0>(std::forward<Q>(pair_value))) {
119 return std::get<0>(std::forward<Q>(pair_value));
122 template <
typename Q>
static auto second(Q &&pair_value) -> decltype(std::get<1>(std::forward<Q>(pair_value))) {
123 return std::get<1>(std::forward<Q>(pair_value));
131 template <
typename SS,
typename TT>
132 static auto test(
int) -> decltype(std::declval<SS &>() << std::declval<TT>(), std::true_type());
134 template <
typename,
typename>
static auto test(...) -> std::false_type;
137 static const bool value = decltype(test<S, T>(0))::value;
141 template <typename T, enable_if_t<std::is_constructible<std::string, T>::value, detail::enabler> = detail::dummy>
142 auto to_string(T &&value) -> decltype(std::forward<T>(value)) {
143 return std::forward<T>(value);
147 template <
typename T,
148 enable_if_t<!std::is_constructible<std::string, T>::value && is_streamable<std::stringstream, T>::value,
149 detail::enabler> = detail::dummy>
150 std::string to_string(T &&value) {
151 std::stringstream stream;
157 template <
typename T,
158 enable_if_t<!std::is_constructible<std::string, T>::value && !is_streamable<std::stringstream, T>::value,
159 detail::enabler> = detail::dummy>
160 std::string to_string(T &&) {
161 return std::string{};
170 template <
typename T,
171 enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, detail::enabler> = detail::dummy>
172 constexpr
const char *type_name() {
176 template <
typename T,
177 enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
178 constexpr
const char *type_name() {
182 template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
183 constexpr
const char *type_name() {
188 template <typename T, enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
189 constexpr
const char *type_name() {
193 template <typename T, enable_if_t<std::is_enum<T>::value, detail::enabler> = detail::dummy>
194 constexpr
const char *type_name() {
199 template <
typename T,
200 enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !is_vector<T>::value &&
201 !std::is_enum<T>::value,
202 detail::enabler> = detail::dummy>
203 constexpr
const char *type_name() {
210 inline int64_t to_flag_value(std::string val) {
211 static const std::string trueString(
"true");
212 static const std::string falseString(
"false");
213 if(val == trueString) {
216 if(val == falseString) {
219 val = detail::to_lower(val);
221 if(val.size() == 1) {
246 throw std::invalid_argument(
"unrecognized character");
250 if(val == trueString || val ==
"on" || val ==
"yes" || val ==
"enable") {
252 }
else if(val == falseString || val ==
"off" || val ==
"no" || val ==
"disable") {
255 ret = std::stoll(val);
263 enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value && !is_bool<T>::value && !std::is_enum<T>::value,
264 detail::enabler> = detail::dummy>
265 bool lexical_cast(std::string input, T &output) {
268 long long output_ll = std::stoll(input, &n, 0);
269 output = static_cast<T>(output_ll);
270 return n == input.size() && static_cast<long long>(output) == output_ll;
271 }
catch(
const std::invalid_argument &) {
273 }
catch(
const std::out_of_range &) {
279 template <
typename T,
280 enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value && !is_bool<T>::value, detail::enabler> =
282 bool lexical_cast(std::string input, T &output) {
283 if(!input.empty() && input.front() ==
'-')
288 unsigned long long output_ll = std::stoull(input, &n, 0);
289 output = static_cast<T>(output_ll);
290 return n == input.size() && static_cast<unsigned long long>(output) == output_ll;
291 }
catch(
const std::invalid_argument &) {
293 }
catch(
const std::out_of_range &) {
299 template <typename T, enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy>
300 bool lexical_cast(std::string input, T &output) {
302 auto out = to_flag_value(input);
305 }
catch(
const std::invalid_argument &) {
311 template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
312 bool lexical_cast(std::string input, T &output) {
315 output = static_cast<T>(std::stold(input, &n));
316 return n == input.size();
317 }
catch(
const std::invalid_argument &) {
319 }
catch(
const std::out_of_range &) {
325 template <
typename T,
326 enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
327 std::is_assignable<T &, std::string>::value,
328 detail::enabler> = detail::dummy>
329 bool lexical_cast(std::string input, T &output) {
335 template <typename T, enable_if_t<std::is_enum<T>::value, detail::enabler> = detail::dummy>
336 bool lexical_cast(std::string input, T &output) {
337 typename std::underlying_type<T>::type val;
338 bool retval = detail::lexical_cast(input, val);
342 output = static_cast<T>(val);
347 template <
typename T,
348 enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
349 !std::is_assignable<T &, std::string>::value && !std::is_enum<T>::value,
350 detail::enabler> = detail::dummy>
351 bool lexical_cast(std::string input, T &output) {
352 std::istringstream is;
356 return !is.fail() && !is.rdbuf()->in_avail();
363 template <
typename T,
364 enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
365 void sum_flag_vector(
const std::vector<std::string> &flags, T &output) {
367 for(
auto &flag : flags) {
368 count += detail::to_flag_value(flag);
370 output = (count > 0) ? static_cast<T>(count) : T{0};
377 template <
typename T,
378 enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, detail::enabler> = detail::dummy>
379 void sum_flag_vector(
const std::vector<std::string> &flags, T &output) {
381 for(
auto &flag : flags) {
382 count += detail::to_flag_value(flag);
384 output = static_cast<T>(count);
static auto second(Q &&pair_value) -> decltype(std::get< 1 >(std::forward< Q >(pair_value)))
Get the second value (really just the underlying value)
Definition: TypeTools.hpp:122
Definition: TypeTools.hpp:81
Check to see if something is a vector (fail check by default)
Definition: TypeTools.hpp:44
Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost ...
Definition: TypeTools.hpp:91
Definition: TypeTools.hpp:88
Check to see if something is copyable pointer.
Definition: TypeTools.hpp:65
Definition: TypeTools.hpp:130
Check to see if something is a shared pointer.
Definition: TypeTools.hpp:56
A copy of std::void_t from C++17 (helper for C++11 and C++14)
Definition: TypeTools.hpp:35
Check to see if something is bool (fail check by default)
Definition: TypeTools.hpp:50
This can be specialized to override the type deduction for IsMember.
Definition: TypeTools.hpp:70
static auto first(Q &&pair_value) -> decltype(std::forward< Q >(pair_value))
Get the first value (really just the underlying value)
Definition: TypeTools.hpp:97
static auto first(Q &&pair_value) -> decltype(std::get< 0 >(std::forward< Q >(pair_value)))
Get the first value (really just the underlying value)
Definition: TypeTools.hpp:118
static auto second(Q &&pair_value) -> decltype(std::forward< Q >(pair_value))
Get the second value (really just the underlying value)
Definition: TypeTools.hpp:101