Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced lexical_cast_internal #1

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions include/CLI/TypeTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -947,19 +947,22 @@ inline std::int64_t to_flag_value(std::string val) {
return ret;
}

template <typename T>
bool lexical_cast(const std::string &input, T &output);

/// Integer conversion
template <typename T,
enable_if_t<classify_object<T>::value == object_category::integral_value ||
classify_object<T>::value == object_category::unsigned_integral,
detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
return integral_conversion(input, output);
}

/// char values
template <typename T,
enable_if_t<classify_object<T>::value == object_category::char_value, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
if(input.size() == 1) {
output = static_cast<T>(input[0]);
return true;
Expand All @@ -970,7 +973,7 @@ bool lexical_cast(const std::string &input, T &output) {
/// Boolean values
template <typename T,
enable_if_t<classify_object<T>::value == object_category::boolean_value, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
try {
auto out = to_flag_value(input);
output = (out > 0);
Expand All @@ -988,7 +991,7 @@ bool lexical_cast(const std::string &input, T &output) {
/// Floats
template <typename T,
enable_if_t<classify_object<T>::value == object_category::floating_point, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
if(input.empty()) {
return false;
}
Expand All @@ -1001,7 +1004,7 @@ bool lexical_cast(const std::string &input, T &output) {
/// complex
template <typename T,
enable_if_t<classify_object<T>::value == object_category::complex_number, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
using XC = typename wrapped_type<T, double>::type;
XC x{0.0}, y{0.0};
auto str1 = input;
Expand Down Expand Up @@ -1033,7 +1036,7 @@ bool lexical_cast(const std::string &input, T &output) {
/// String and similar direct assignment
template <typename T,
enable_if_t<classify_object<T>::value == object_category::string_assignable, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
output = input;
return true;
}
Expand All @@ -1042,7 +1045,7 @@ bool lexical_cast(const std::string &input, T &output) {
template <
typename T,
enable_if_t<classify_object<T>::value == object_category::string_constructible, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
output = T(input);
return true;
}
Expand All @@ -1051,23 +1054,23 @@ bool lexical_cast(const std::string &input, T &output) {
template <
typename T,
enable_if_t<classify_object<T>::value == object_category::wstring_assignable, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
output = widen(input);
return true;
}

template <
typename T,
enable_if_t<classify_object<T>::value == object_category::wstring_constructible, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
output = T{widen(input)};
return true;
}

/// Enumerations
template <typename T,
enable_if_t<classify_object<T>::value == object_category::enumeration, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
typename std::underlying_type<T>::type val;
if(!integral_conversion(input, val)) {
return false;
Expand All @@ -1081,7 +1084,7 @@ template <typename T,
enable_if_t<classify_object<T>::value == object_category::wrapper_value &&
std::is_assignable<T &, typename T::value_type>::value,
detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
typename T::value_type val;
if(lexical_cast(input, val)) {
output = val;
Expand All @@ -1094,7 +1097,7 @@ template <typename T,
enable_if_t<classify_object<T>::value == object_category::wrapper_value &&
!std::is_assignable<T &, typename T::value_type>::value && std::is_assignable<T &, T>::value,
detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
typename T::value_type val;
if(lexical_cast(input, val)) {
output = T{val};
Expand All @@ -1107,7 +1110,7 @@ bool lexical_cast(const std::string &input, T &output) {
template <
typename T,
enable_if_t<classify_object<T>::value == object_category::number_constructible, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
int val = 0;
if(integral_conversion(input, val)) {
output = T(val);
Expand All @@ -1127,7 +1130,7 @@ bool lexical_cast(const std::string &input, T &output) {
template <
typename T,
enable_if_t<classify_object<T>::value == object_category::integer_constructible, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
int val = 0;
if(integral_conversion(input, val)) {
output = T(val);
Expand All @@ -1140,7 +1143,7 @@ bool lexical_cast(const std::string &input, T &output) {
template <
typename T,
enable_if_t<classify_object<T>::value == object_category::double_constructible, detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
double val = 0.0;
if(lexical_cast(input, val)) {
output = T{val};
Expand All @@ -1153,7 +1156,7 @@ bool lexical_cast(const std::string &input, T &output) {
template <typename T,
enable_if_t<classify_object<T>::value == object_category::other && std::is_assignable<T &, int>::value,
detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
int val = 0;
if(integral_conversion(input, val)) {
#ifdef _MSC_VER
Expand All @@ -1179,13 +1182,19 @@ bool lexical_cast(const std::string &input, T &output) {
template <typename T,
enable_if_t<classify_object<T>::value == object_category::other && !std::is_assignable<T &, int>::value,
detail::enabler> = detail::dummy>
bool lexical_cast(const std::string &input, T &output) {
bool lexical_cast_internal(const std::string &input, T &output) {
static_assert(is_istreamable<T>::value,
"option object type must have a lexical cast overload or streaming input operator(>>) defined, if it "
"is convertible from another type use the add_option<T, XC>(...) with XC being the known type");
return from_stream(input, output);
}

template <typename T>
bool lexical_cast(const std::string &input, T &output) {
return lexical_cast_internal(input, output);
}


/// Assign a value through lexical cast operations
/// Strings can be empty so we need to do a little different
template <typename AssignTo,
Expand Down