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