@@ -85,6 +85,23 @@ template <> struct IsMemberType<const char *> {
85
85
using type = std::string;
86
86
};
87
87
88
+ namespace adl_detail {
89
+ // / Check for existence of user-supplied lexical_cast.
90
+ // /
91
+ // / This struct has to be in a separate namespace so that it doesn't see our lexical_cast overloads in CLI::detail.
92
+ // / Standard says it shouldn't see them if it's defined before the corresponding lexical_cast declarations, but this
93
+ // / requires a working implementation of two-phase lookup, and not all compilers can boast that (msvc, ahem).
94
+ template <typename T, typename S = std::string> class is_lexical_castable {
95
+ template <typename TT, typename SS>
96
+ static auto test (int ) -> decltype(lexical_cast(std::declval<const SS &>(), std::declval<TT &>()), std::true_type());
97
+
98
+ template <typename , typename > static auto test (...) -> std::false_type;
99
+
100
+ public:
101
+ static constexpr bool value = decltype (test<T, S>(0 ))::value;
102
+ };
103
+ } // namespace adl_detail
104
+
88
105
namespace detail {
89
106
90
107
// These are utilities for IsMember and other transforming objects
@@ -1245,13 +1262,24 @@ bool lexical_cast(const std::string &input, T &output) {
1245
1262
1246
1263
// / Non-string parsable by a stream
1247
1264
template <typename T,
1248
- enable_if_t <classify_object<T>::value == object_category::other && !std::is_assignable<T &, int >::value,
1265
+ enable_if_t <classify_object<T>::value == object_category::other && !std::is_assignable<T &, int >::value &&
1266
+ is_istreamable<T>::value,
1249
1267
detail::enabler> = detail::dummy>
1250
1268
bool lexical_cast (const std::string &input, T &output) {
1251
- static_assert (is_istreamable<T>::value,
1269
+ return from_stream (input, output);
1270
+ }
1271
+
1272
+ // / Fallback overload that prints a human-readable error for types that we don't recognize and that don't have a
1273
+ // / user-supplied lexical_cast overload.
1274
+ template <typename T,
1275
+ enable_if_t <classify_object<T>::value == object_category::other && !std::is_assignable<T &, int >::value &&
1276
+ !is_istreamable<T>::value && !adl_detail::is_lexical_castable<T>::value,
1277
+ detail::enabler> = detail::dummy>
1278
+ bool lexical_cast (const std::string & /* input*/ , T & /* output*/ ) {
1279
+ static_assert (!std::is_same<T, T>::value, // Can't just write false here.
1252
1280
" option object type must have a lexical cast overload or streaming input operator(>>) defined, if it "
1253
1281
" is convertible from another type use the add_option<T, XC>(...) with XC being the known type" );
1254
- return from_stream (input, output) ;
1282
+ return false ;
1255
1283
}
1256
1284
1257
1285
// / Assign a value through lexical cast operations
0 commit comments