Refactoring of the arg-traits functionality. The purpose is to make it

easier to make you own classes, and types defined in the standard
library work well with tclap. I'll try to write up some documenation
of how to achieve this as-well.
This commit is contained in:
macbishop 2007-10-09 18:18:51 +00:00
parent a560fc1b62
commit e021e21520
9 changed files with 445 additions and 37 deletions

View File

@ -0,0 +1,19 @@
dnl @synopsis AC_CXX_HAVE_LONG_LONG
dnl
dnl If the C++ implementation have a long long type
dnl
AC_DEFUN([AC_CXX_HAVE_LONG_LONG],
[AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_COMPILE([],[long long x = 1; return 0;],
ac_cv_cxx_have_long_long=yes, ac_cv_cxx_have_long_long=no)
if test "$ac_cv_cxx_have_long_long" = yes; then
AC_DEFINE(HAVE_LONG_LONG, 1,
[define if the C++ implementation have long long])
else
AC_DEFINE(HAVE_LONG_LONG, 0,
[define if the C++ implementation have long long])
fi
AC_LANG_RESTORE
])

View File

@ -6,6 +6,7 @@ AM_INIT_AUTOMAKE(tclap,1.1.0)
AC_PROG_CXX
AC_CXX_HAVE_SSTREAM
AC_CXX_HAVE_STRSTREAM
AC_CXX_HAVE_LONG_LONG
AC_CHECK_PROG(DOT,dot,YES,NO)
AC_PROG_RANLIB
AC_PROG_INSTALL

View File

@ -1,6 +1,6 @@
noinst_PROGRAMS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
test10 test11 test12 test13
test10 test11 test12 test13 test14 test15 test16
test1_SOURCES = test1.cpp
test2_SOURCES = test2.cpp
@ -15,6 +15,9 @@ test10_SOURCES = test10.cpp
test11_SOURCES = test11.cpp
test12_SOURCES = test12.cpp
test13_SOURCES = test13.cpp
test14_SOURCES = test14.cpp
test15_SOURCES = test15.cpp
test16_SOURCES = test16.cpp
INCLUDES = -I$(top_srcdir)/include

56
examples/test14.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "tclap/CmdLine.h"
#include <iterator>
#include <algorithm>
// Define a simple 3D vector type
template<typename T, size_t LEN>
struct Vect : public TCLAP::StringLikeTrait {
//typedef TCLAP::StringLike ValueCategory;
T v[LEN];
// operator= will be used to assign to the vector
Vect& operator=(const std::string &str)
{
std::istringstream iss(str);
for (size_t n = 0; n < LEN; n++) {
if (!(iss >> v[n])) {
std::ostringstream oss;
oss << " is not a vector of size " << LEN;
throw TCLAP::ArgParseException(str + oss.str());
}
}
if (!iss.eof()) {
std::ostringstream oss;
oss << " is not a vector of size " << LEN;
throw TCLAP::ArgParseException(str + oss.str());
}
return *this;
}
std::ostream& print(std::ostream &os) const
{
std::copy(v, v + LEN, std::ostream_iterator<T>(os, " "));
return os;
}
};
int main(int argc, char *argv[])
{
TCLAP::CmdLine cmd("Command description message", ' ', "0.9");
TCLAP::ValueArg< Vect<double, 3> > vec("v", "vect", "vector",
true, Vect<double, 3>(),
"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;
}

56
examples/test15.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "tclap/CmdLine.h"
#include <iterator>
#include <algorithm>
// Define a simple 3D vector type
template<typename T, size_t LEN>
struct Vect {
typedef TCLAP::StringLike ValueCategory;
T v[LEN];
// operator= will be used to assign to the vector
Vect& operator=(const std::string &str)
{
std::istringstream iss(str);
for (size_t n = 0; n < LEN; n++) {
if (!(iss >> v[n])) {
std::ostringstream oss;
oss << " is not a vector of size " << LEN;
throw TCLAP::ArgParseException(str + oss.str());
}
}
if (!iss.eof()) {
std::ostringstream oss;
oss << " is not a vector of size " << LEN;
throw TCLAP::ArgParseException(str + oss.str());
}
return *this;
}
std::ostream& print(std::ostream &os) const
{
std::copy(v, v + LEN, std::ostream_iterator<T>(os, " "));
return os;
}
};
int main(int argc, char *argv[])
{
TCLAP::CmdLine cmd("Command description message", ' ', "0.9");
TCLAP::ValueArg< Vect<double, 3> > vec("v", "vect", "vector",
true, Vect<double, 3>(),
"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;
}

41
examples/test16.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "tclap/CmdLine.h"
#include <iterator>
#include <algorithm>
namespace TCLAP {
template<>
struct ArgTraits< std::vector<double> > {
typedef StringLike ValueCategory;
};
template<>
void SetString< std::vector<double> >(std::vector<double> &v,
const std::string &s)
{
std::istringstream iss(s);
while (iss) {
double tmp;
iss >> tmp;
v.push_back(tmp);
}
}
}
int main(int argc, char *argv[])
{
TCLAP::CmdLine cmd("Command description message", ' ', "0.9");
TCLAP::ValueArg< std::vector<double> > vec("v", "vect", "vector",
true, std::vector<double>(),
"3D vector", cmd);
try {
cmd.parse(argc, argv);
} catch(std::exception &e) {
std::cout << e.what() << std::endl;
return EXIT_FAILURE;
}
const std::vector<double> &v = vec.getValue();
std::copy(v.begin(), v.end(),
std::ostream_iterator<double>(std::cout, "\n"));
std::cout << std::endl;
}

View File

@ -49,6 +49,8 @@ typedef std::istrstream istringstream;
#include <tclap/ArgException.h>
#include <tclap/Visitor.h>
#include <tclap/CmdLineInterface.h>
#include <tclap/ArgTraits.h>
#include <tclap/StandardTraits.h>
namespace TCLAP {
@ -367,41 +369,6 @@ typedef std::vector<Arg*>::iterator ArgVectorIterator;
*/
typedef std::list<Visitor*>::iterator VisitorListIterator;
// We use two empty structs to get compile type specialization
// function to work
/**
* A value like argument value type is a value that can be set using
* operator>>. This is the default value type.
*/
struct ValueLike {};
/**
* A string like argument value type is a value that can be set using
* operator=(string). Usefull if the value type contains spaces which
* will be broken up into individual tokens by operator>>.
*/
struct StringLike {};
/**
* 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 string like and value like.
*/
template<typename T>
struct ArgTraits {
typedef ValueLike ValueCategory;
};
/**
* Strings have string like argument traits.
*/
template<>
struct ArgTraits<std::string> {
typedef StringLike ValueCategory;
};
/*
* Extract a value of type T from it's string representation contained
* in strVal. The ValueLike parameter used to select the correct
@ -445,7 +412,7 @@ template<typename T> void
ExtractValue(T &destVal, const std::string& strVal, StringLike sl)
{
static_cast<void>(sl); // Avoid warning about unused sl
destVal = strVal;
SetString(destVal, strVal);
}
//////////////////////////////////////////////////////////////////////

81
include/tclap/ArgTraits.h Normal file
View File

@ -0,0 +1,81 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/******************************************************************************
*
* file: ArgTraits.h
*
* Copyright (c) 2007, Daniel Aarno, Michael E. Smoot .
* All rights reverved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
// This is an internal tclap file, you should probably not have to
// include this directly
#ifndef TCLAP_ARGTRAITS_H
#define TCLAP_ARGTRAITS_H
namespace TCLAP {
// We use two empty structs to get compile type specialization
// function to work
/**
* A value like argument value type is a value that can be set using
* operator>>. This is the default value type.
*/
struct ValueLike {
typedef ValueLike ValueCategory;
};
/**
* A string like argument value type is a value that can be set using
* operator=(string). Usefull if the value type contains spaces which
* will be broken up into individual tokens by operator>>.
*/
struct StringLike {};
/**
* A class can inherit from this object to make it have string like
* traits. This is a compile time thing and does not add any overhead
* to the inherenting class.
*/
struct StringLikeTrait {
typedef StringLike ValueCategory;
};
/**
* A class can inherit from this object to make it have value like
* traits. This is a compile time thing and does not add any overhead
* to the inherenting class.
*/
struct ValueLikeTrait {
typedef ValueLike ValueCategory;
};
/**
* 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 string like and value like.
*/
template<typename T>
struct ArgTraits {
typedef typename T::ValueCategory ValueCategory;
//typedef ValueLike ValueCategory;
};
#endif
} // namespace

View File

@ -0,0 +1,184 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/******************************************************************************
*
* file: StandardTraits.h
*
* Copyright (c) 2007, Daniel Aarno, Michael E. Smoot .
* All rights reverved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
// This is an internal tclap file, you should probably not have to
// include this directly
#ifndef TCLAP_STANDARD_TRAITS_H
#define TCLAP_STANDARD_TRAITS_H
#ifdef HAVE_CONFIG_H
#include <config.h> // To check for long long
#endif
namespace TCLAP {
// ======================================================================
// Integer types
// ======================================================================
/**
* 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;
};
#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.
*/
template<>
struct ArgTraits<wchar_t> {
typedef ValueLike ValueCategory;
};
/**
* Strings have string like argument traits.
*/
template<>
struct ArgTraits<std::string> {
typedef StringLike ValueCategory;
};
template<typename T>
void SetString(T &dst, const std::string &src)
{
dst = src;
}
} // namespace
#endif