mirror of
https://github.com/cuberite/TCLAP.git
synced 2025-09-12 13:46:02 -04:00
Make all types have ValueLike traits by default.
This allows new types to be added without any fuzz (no need to specify the traits) if it has operator>>. It also removes the need to manually specify the ArgTrait for all built in types (such as long, bool, char, float etc). ArgTraits now works in the following way: 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 commit is contained in:
parent
f41dcb5ce3
commit
5d4ffbf2db
@ -1,7 +1,8 @@
|
||||
|
||||
noinst_PROGRAMS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
|
||||
test10 test11 test12 test13 test14 test15 test16 \
|
||||
test17 test18 test19 test20 test21 test22 test23
|
||||
test17 test18 test19 test20 test21 test22 test23 \
|
||||
test24
|
||||
|
||||
test1_SOURCES = test1.cpp
|
||||
test2_SOURCES = test2.cpp
|
||||
@ -26,6 +27,7 @@ test20_SOURCES = test20.cpp
|
||||
test21_SOURCES = test21.cpp
|
||||
test22_SOURCES = test22.cpp
|
||||
test23_SOURCES = test23.cpp
|
||||
test24_SOURCES = test24.cpp
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
|
43
examples/test24.cpp
Normal file
43
examples/test24.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "tclap/CmdLine.h"
|
||||
#include <iterator>
|
||||
|
||||
using namespace TCLAP;
|
||||
|
||||
// Define a simple 3D vector type
|
||||
struct Vect3D {
|
||||
double v[3];
|
||||
|
||||
std::ostream& print(std::ostream &os) const
|
||||
{
|
||||
std::copy(v, v + 3, std::ostream_iterator<double>(os, " "));
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
// operator>> will be used to assign to the vector since the default
|
||||
// is that all types are ValueLike.
|
||||
std::istream &operator>>(std::istream &is, Vect3D &v)
|
||||
{
|
||||
if (!(is >> v.v[0] >> v.v[1] >> v.v[2]))
|
||||
throw TCLAP::ArgParseException(" Argument is not a 3D vector");
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
CmdLine cmd("Command description message", ' ', "0.9");
|
||||
ValueArg<Vect3D> vec("v", "vect", "vector",
|
||||
true, Vect3D(), "3D vector", cmd);
|
||||
|
||||
try {
|
||||
cmd.parse(argc, argv);
|
||||
} catch(std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
vec.getValue().print(std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
@ -73,13 +73,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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -41,156 +41,10 @@
|
||||
|
||||
namespace TCLAP {
|
||||
|
||||
// ======================================================================
|
||||
// Integer types
|
||||
// ======================================================================
|
||||
// Integer types (signed, unsigned and bool) and floating point types all
|
||||
// have value-like semantics.
|
||||
|
||||
/**
|
||||
* longs have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<long> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* ints have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<int> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* shorts have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<short> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* chars have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<char> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
/**
|
||||
* long longs have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<long long> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
// Unsigned integer types
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* unsigned longs have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<unsigned long> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* unsigned ints have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<unsigned int> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* unsigned shorts have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<unsigned short> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* unsigned chars have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<unsigned char> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
// Microsoft implements size_t awkwardly.
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
/**
|
||||
* size_ts have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<size_t> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
/**
|
||||
* unsigned long longs have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<unsigned long long> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
// Float types
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* floats have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<float> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
/**
|
||||
* doubles have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<double> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// Other types
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* bools have value-like semantics.
|
||||
*/
|
||||
template<>
|
||||
struct ArgTraits<bool> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* wchar_ts have value-like semantics.
|
||||
*/
|
||||
#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS
|
||||
template<>
|
||||
struct ArgTraits<wchar_t> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Strings have string like argument traits.
|
||||
*/
|
||||
// Strings have string like argument traits.
|
||||
template<>
|
||||
struct ArgTraits<std::string> {
|
||||
typedef StringLike ValueCategory;
|
||||
|
@ -81,7 +81,8 @@ TESTS = test1.sh \
|
||||
test79.sh \
|
||||
test80.sh \
|
||||
test81.sh \
|
||||
test82.sh
|
||||
test82.sh \
|
||||
test83.sh
|
||||
|
||||
EXTRA_DIST = $(TESTS) \
|
||||
test1.out \
|
||||
@ -165,6 +166,7 @@ EXTRA_DIST = $(TESTS) \
|
||||
test79.out \
|
||||
test80.out \
|
||||
test81.out \
|
||||
test82.out
|
||||
test82.out \
|
||||
test83.out
|
||||
|
||||
CLEANFILES = tmp.out
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
let "suc = 0"
|
||||
let "fail = 0"
|
||||
NUMTEST=82
|
||||
NUMTEST=83
|
||||
|
||||
for (( tno = 1 ; $tno <= $NUMTEST ; tno = $tno + 1 )); do
|
||||
./testCheck.sh $tno
|
||||
|
1
tests/test83.out
Normal file
1
tests/test83.out
Normal file
@ -0,0 +1 @@
|
||||
1 2 3
|
13
tests/test83.sh
Executable file
13
tests/test83.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this tests whether all required args are listed as
|
||||
# missing when no arguments are specified
|
||||
# failure
|
||||
../examples/test24 -v "1 2 3" > tmp.out 2>&1
|
||||
|
||||
if cmp -s tmp.out $srcdir/test84.out; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
Loading…
x
Reference in New Issue
Block a user