8
8
9
9
#include < functional>
10
10
#include < iostream>
11
+ #include < memory>
11
12
#include < string>
12
13
13
14
// C standard library
@@ -264,11 +265,16 @@ class Range : public Validator {
264
265
template <typename T> explicit Range (T max) : Range(static_cast <T>(0 ), max) {}
265
266
};
266
267
267
- // / This can be specialized to override the type deduction for IsMember.
268
- template <typename T> struct IsMemberType { using type = T; };
268
+ namespace detail {
269
+ template <typename T, enable_if_t <is_copyable_ptr<T>::value, detail::enabler> = detail::dummy>
270
+ auto smart_deref (T value) -> decltype(*value) {
271
+ return *value;
272
+ }
269
273
270
- // / The main custom type needed here is const char * should be a string.
271
- template <> struct IsMemberType <const char *> { using type = std::string; };
274
+ template <typename T, enable_if_t <!is_copyable_ptr<T>::value, detail::enabler> = detail::dummy> T smart_deref (T value) {
275
+ return value;
276
+ }
277
+ } // namespace detail
272
278
273
279
// / Verify items are in a set
274
280
class IsMember : public Validator {
@@ -280,26 +286,18 @@ class IsMember : public Validator {
280
286
explicit IsMember (std::initializer_list<T> values, Args &&... args)
281
287
: IsMember(std::vector<T>(values), std::forward<Args>(args)...) {}
282
288
283
- // / This checks to see if an item is in a set: pointer version. (Empty function)
284
- template <typename T, enable_if_t <is_copyable_ptr<T>::value, detail::enabler> = detail::dummy>
285
- explicit IsMember (T set)
286
- : IsMember(std::move(set),
287
- std::function<typename IsMemberType<typename std::pointer_traits<T>::element_type::value_type>::type(
288
- typename IsMemberType<typename std::pointer_traits<T>::element_type::value_type>::type)>{}) {}
289
-
290
- // / This checks to see if an item is in a set: copy version. (Empty function)
291
- template <typename T, enable_if_t <!is_copyable_ptr<T>::value, detail::enabler> = detail::dummy>
289
+ // / This checks to see if an item is in a set (empty function)
290
+ template <typename T>
292
291
explicit IsMember (T set)
293
292
: IsMember(std::move(set),
294
- std::function<typename IsMemberType<typename T::value_type >::type(
295
- typename IsMemberType<typename T::value_type >::type)>()) {}
293
+ std::function<typename IsMemberType<typename element_value_type<T>::type >::type(
294
+ typename IsMemberType<typename element_value_type<T>::type >::type)>()) {}
296
295
297
- // / This checks to see if an item is in a set: pointer version. You can pass in a function that will filter
296
+ // / This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter
298
297
// / both sides of the comparison before computing the comparison.
299
- template <typename T, typename F, enable_if_t <is_copyable_ptr<T>::value, detail::enabler> = detail::dummy>
300
- explicit IsMember (T set, F filter_function) {
298
+ template <typename T, typename F> explicit IsMember (T set, F filter_function) {
301
299
// Get the type of the contained item - requires a container have ::value_type
302
- using item_t = typename std::pointer_traits <T>::element_type::value_type ;
300
+ using item_t = typename element_value_type <T>::type ;
303
301
using local_item_t = typename IsMemberType<item_t >::type;
304
302
305
303
// Make a local copy of the filter function, using a std::function if not one already
@@ -308,62 +306,14 @@ class IsMember : public Validator {
308
306
// This is the type name for help, it will take the current version of the set contents
309
307
tname_function = [set]() {
310
308
std::stringstream out;
311
- out << detail::type_name<item_t >() << " in {" << detail::join (* set, " ," ) << " }" ;
309
+ out << detail::type_name<item_t >() << " in {" << detail::join (detail::smart_deref ( set) , " ," ) << " }" ;
312
310
return out.str ();
313
311
};
314
312
315
313
// This is the function that validates
316
314
// It stores a copy of the set pointer-like, so shared_ptr will stay alive
317
315
func = [set, filter_fn](std::string &input) {
318
- for (const item_t &v : *set) {
319
- local_item_t a = v;
320
- local_item_t b;
321
- if (!detail::lexical_cast (input, b))
322
- throw ValidationError (input); // name is added later
323
-
324
- // The filter function might be empty, so don't filter if it is.
325
- if (filter_fn) {
326
- a = filter_fn (a);
327
- b = filter_fn (b);
328
- }
329
-
330
- if (a == b) {
331
- // Make sure the version in the input string is identical to the one in the set
332
- // Requires std::stringstream << be supported on T.
333
- if (filter_fn) {
334
- std::stringstream out;
335
- out << v;
336
- input = out.str ();
337
- }
338
-
339
- // Return empty error string (success)
340
- return std::string ();
341
- }
342
- }
343
-
344
- // If you reach this point, the result was not found
345
- return input + " not in {" + detail::join (*set, " ," ) + " }" ;
346
- };
347
- }
348
-
349
- // / This checks to see if an item is in a set: copy version.
350
- template <typename T, typename F, enable_if_t <!is_copyable_ptr<T>::value, detail::enabler> = detail::dummy>
351
- explicit IsMember (T set, F filter_function) {
352
- // Get the type of the contained item - requires a container have ::value_type
353
- using item_t = typename T::value_type;
354
- using local_item_t = typename IsMemberType<item_t >::type;
355
-
356
- // Make a local copy of the filter function, using a std::function if not one already
357
- std::function<local_item_t (local_item_t )> filter_fn = filter_function;
358
-
359
- // This is the type name for help, since the set contents can't change, we just capture this
360
- std::stringstream out;
361
- out << detail::type_name<item_t >() << " in {" << detail::join (set, " ," ) << " }" ;
362
- tname = out.str ();
363
-
364
- // This is the function that validates
365
- func = [set, filter_fn](std::string &input) {
366
- for (const item_t &v : set) {
316
+ for (const item_t &v : detail::smart_deref (set)) {
367
317
local_item_t a = v;
368
318
local_item_t b;
369
319
if (!detail::lexical_cast (input, b))
@@ -390,7 +340,7 @@ class IsMember : public Validator {
390
340
}
391
341
392
342
// If you reach this point, the result was not found
393
- return input + " not in {" + detail::join (set, " ," ) + " }" ;
343
+ return input + " not in {" + detail::join (detail::smart_deref ( set) , " ," ) + " }" ;
394
344
};
395
345
}
396
346
0 commit comments