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 \
|
noinst_PROGRAMS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
|
||||||
test10 test11 test12 test13 test14 test15 test16 \
|
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
|
test1_SOURCES = test1.cpp
|
||||||
test2_SOURCES = test2.cpp
|
test2_SOURCES = test2.cpp
|
||||||
@ -26,6 +27,7 @@ test20_SOURCES = test20.cpp
|
|||||||
test21_SOURCES = test21.cpp
|
test21_SOURCES = test21.cpp
|
||||||
test22_SOURCES = test22.cpp
|
test22_SOURCES = test22.cpp
|
||||||
test23_SOURCES = test23.cpp
|
test23_SOURCES = test23.cpp
|
||||||
|
test24_SOURCES = test24.cpp
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
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
|
* Arg traits are used to get compile type specialization when parsing
|
||||||
* argument values. Using an ArgTraits you can specify the way that
|
* argument values. Using an ArgTraits you can specify the way that
|
||||||
* values gets assigned to any particular type during parsing. The two
|
* 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>
|
template<typename T>
|
||||||
struct ArgTraits {
|
class ArgTraits {
|
||||||
typedef typename T::ValueCategory ValueCategory;
|
// This is a bit silly, but what we want to do is:
|
||||||
virtual ~ArgTraits() {}
|
// 1) If there exists a specialization of ArgTraits for type X,
|
||||||
//typedef ValueLike ValueCategory;
|
// 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
|
#endif
|
||||||
|
@ -41,156 +41,10 @@
|
|||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP {
|
||||||
|
|
||||||
// ======================================================================
|
// Integer types (signed, unsigned and bool) and floating point types all
|
||||||
// Integer types
|
// have value-like semantics.
|
||||||
// ======================================================================
|
|
||||||
|
|
||||||
/**
|
// Strings have string like argument traits.
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<std::string> {
|
struct ArgTraits<std::string> {
|
||||||
typedef StringLike ValueCategory;
|
typedef StringLike ValueCategory;
|
||||||
|
@ -81,7 +81,8 @@ TESTS = test1.sh \
|
|||||||
test79.sh \
|
test79.sh \
|
||||||
test80.sh \
|
test80.sh \
|
||||||
test81.sh \
|
test81.sh \
|
||||||
test82.sh
|
test82.sh \
|
||||||
|
test83.sh
|
||||||
|
|
||||||
EXTRA_DIST = $(TESTS) \
|
EXTRA_DIST = $(TESTS) \
|
||||||
test1.out \
|
test1.out \
|
||||||
@ -165,6 +166,7 @@ EXTRA_DIST = $(TESTS) \
|
|||||||
test79.out \
|
test79.out \
|
||||||
test80.out \
|
test80.out \
|
||||||
test81.out \
|
test81.out \
|
||||||
test82.out
|
test82.out \
|
||||||
|
test83.out
|
||||||
|
|
||||||
CLEANFILES = tmp.out
|
CLEANFILES = tmp.out
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
let "suc = 0"
|
let "suc = 0"
|
||||||
let "fail = 0"
|
let "fail = 0"
|
||||||
NUMTEST=82
|
NUMTEST=83
|
||||||
|
|
||||||
for (( tno = 1 ; $tno <= $NUMTEST ; tno = $tno + 1 )); do
|
for (( tno = 1 ; $tno <= $NUMTEST ; tno = $tno + 1 )); do
|
||||||
./testCheck.sh $tno
|
./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