diff options
Diffstat (limited to 'TCLAP/tclap/ArgTraits.h')
-rw-r--r-- | TCLAP/tclap/ArgTraits.h | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/TCLAP/tclap/ArgTraits.h b/TCLAP/tclap/ArgTraits.h index 7ae85a9..0ccf5e3 100644 --- a/TCLAP/tclap/ArgTraits.h +++ b/TCLAP/tclap/ArgTraits.h @@ -5,6 +5,7 @@ * file: ArgTraits.h * * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * Copyright (c) 2017 Google LLC * All rights reserved. * * See the file COPYING in the top directory of this distribution for @@ -73,13 +74,46 @@ struct ValueLikeTrait { * Arg traits are used to get compile type specialization when parsing * argument values. Using an ArgTraits you can specify the way that * values gets assigned to any particular type during parsing. The two - * supported types are StringLike and ValueLike. + * supported types are StringLike and ValueLike. ValueLike is the + * default and means that operator>> will be used to assign values to + * the type. */ template<typename T> -struct ArgTraits { - typedef typename T::ValueCategory ValueCategory; - virtual ~ArgTraits() {} - //typedef ValueLike ValueCategory; +class ArgTraits { + // This is a bit silly, but what we want to do is: + // 1) If there exists a specialization of ArgTraits for type X, + // use it. + // + // 2) If no specialization exists but X has the typename + // X::ValueCategory, use the specialization for X::ValueCategory. + // + // 3) If neither (1) nor (2) defines the trait, use the default + // which is ValueLike. + + // This is the "how": + // + // test<T>(0) (where 0 is the NULL ptr) will match + // test(typename C::ValueCategory*) iff type T has the + // corresponding typedef. If it does not test(...) will be + // matched. This allows us to determine if T::ValueCategory + // exists by checking the sizeof for the test function (return + // value must have different sizeof). + template<typename C> static short test(typename C::ValueCategory*); + template<typename C> static long test(...); + static const bool hasTrait = sizeof(test<T>(0)) == sizeof(short); + + template <typename C, bool> + struct DefaultArgTrait { + typedef ValueLike ValueCategory; + }; + + template <typename C> + struct DefaultArgTrait<C, true> { + typedef typename C::ValueCategory ValueCategory; + }; + +public: + typedef typename DefaultArgTrait<T, hasTrait>::ValueCategory ValueCategory; }; } // namespace |