// $Id: AnyScalar.h 59 2007-07-17 14:43:23Z tb $
/*
* STX Expression Parser C++ Framework v0.7
* Copyright (C) 2007 Timo Bingmann
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** \file AnyScalar.h
* Definition of a typed scalar value class AnyScalar used by the parser to
* represent values.
*/
#ifndef _STX_AnyScalar_H_
#define _STX_AnyScalar_H_
#include <string>
#include <stdexcept>
#include <functional>
#include <ostream>
#include <assert.h>
namespace stx {
/** AnyScalar constructs objects holding a typed scalar value. It supports
* boolean values, integer values both signed and unsigned, floating point
* values and strings. The class provides operators which will compare scalars
* between other scalars by converting them into a common domain. Furthermore
* arithmetic operator will compose one or two scalars where the calculation is
* done in the "higher" domain. */
class AnyScalar
{
public:
/// Enumeration establishing identifiers for all supported types. All
/// "small" integer types are included, because the class use originally
/// designed for serializing large amounts of data.
enum attrtype_t
{
/// Flag identifier for an uninitialized object.
ATTRTYPE_INVALID = 0x00,
/// A boolean type holding only true and false.
ATTRTYPE_BOOL = 0x01,
/// Character type, not viewed as a letter or digit, but as 8 bit
/// signed integer.
ATTRTYPE_CHAR = 0x10,
/// Short signed integer type, 2 bytes long.
ATTRTYPE_SHORT = 0x11,
/// Medium signed integer type, 4 bytes long.
ATTRTYPE_INTEGER = 0x12,
/// Long (long) signed integer type, 8 bytes long.
ATTRTYPE_LONG = 0x13,
/// Byte type, not viewed as a letter or digit, but as 8 bit unsigned
/// integer.
ATTRTYPE_BYTE = 0x20,
/// Short unsigned integer type, 2 bytes long.
ATTRTYPE_WORD = 0x21,
/// Medium unsigned integer type, 4 bytes long.
ATTRTYPE_DWORD = 0x22,
/// Long (long) unsigned integer type, 8 bytes long.
ATTRTYPE_QWORD = 0x23,
/// Single precision floating point type, 4 bytes long.
ATTRTYPE_FLOAT = 0x30,
/// Double precision floating point type, 8 bytes long.
ATTRTYPE_DOUBLE = 0x31,
/// String type, variable length. Needs much extra care to handle
/// memory allocation.
ATTRTYPE_STRING = 0x40
};
private:
/// The currently set type in the union.
attrtype_t atype;
/// Union type to holding the current value of an AnyScalar.
union value_t
{
/// Used for ATTRTYPE_BOOL, ATTRTYPE_CHAR, ATTRTYPE_SHORT, ATTRTYPE_INTEGER
int _int;
/// Used for ATTRTYPE_BYTE, ATTRTYPE_WORD, ATTRTYPE_DWORD
unsigned int _uint;
/// Used for ATTRTYPE_LONG
long long _long;
/// Used for ATTRTYPE_QWORD
unsigned long long _ulong;
/// Used for ATTRTYPE_FLOAT
float _float;
/// Used for ATTRTYPE_DOUBLE
double _double;
/// Used for ATTRTYPE_STRING, make sure it get delete'ed correctly.
std::string* _string;
};
/// Union holding the current value of set type.
union value_t val;
public:
/// Create a new empty AnyScalar object of given type.
explicit inline AnyScalar(attrtype_t t = ATTRTYPE_INVALID)
: atype(t)
{
if (atype == ATTRTYPE_STRING) {
val._string = new std::string;
}
else {
val._ulong = 0;
}
}
// *** Constructors for the various types
/// Construct a new AnyScalar object of type ATTRTYPE_BOOL and set the given
/// boolean value.
inline AnyScalar(bool b)
: atype(ATTRTYPE_BOOL)
{
val._int = b;
}
#ifndef SWIG // This constructor confuses SWIG into calling it with
// one-character strings
/// Construct a new AnyScalar object of type ATTRTYPE_CHAR and set the given
/// char value.
inline AnyScalar(char c)
: atype(ATTRTYPE_CHAR)
{
val._int = c;
}
#endif
/// Construct a new AnyScalar object of type ATTRTYPE_SHORT and set the given
/// short value.
inline AnyScalar(short s)
: atype(ATTRTYPE_SHORT)
{
val._int = s;
}
/// Construct a new AnyScalar object of type ATTRTYPE_INTEGER and set the
/// given integer value.
inline AnyScalar(int i)
: atype(ATTRTYPE_INTEGER)
{
val._int = i;
}
/// Construct a new AnyScalar object of type ATTRTYPE_INTEGER and set the
/// given integer value.
inline AnyScalar(long i)
: atype(ATTRTYPE_INTEGER)
{
val._int = i;
}
/// Construct a new AnyScalar object of type ATTRTYPE_LONG and set the
/// given long value.
inline AnyScalar(long long l)
: atype(ATTRTYPE_LONG)
{
val._long = l;
}
/// Construct a new AnyScalar object of type ATTRTYPE_BYTE and set the given
/// unsigned value.
inline AnyScalar(unsigned char c)
: atype(ATTRTYPE_BYTE)
{
val._uint = c;
}
/// Construct a new AnyScalar object of type ATTRTYPE_WORD and set the given
/// unsigned value.
inline AnyScalar(unsigned short s)
: atype(ATTRTYPE_WORD)
{
val._uint = s;
}
/// Construct a new AnyScalar object of type ATTRTYPE_DWORD and set the given
/// unsigned value.
inline AnyScalar(unsigned int i)
: atype(ATTRTYPE_DWORD)
{
val._uint = i;
}
/// Construct a new AnyScalar object of type ATTRTYPE_DWORD and set the given
/// unsigned value.
inline AnyScalar(unsigned long i)
: atype(ATTRTYPE_DWORD)
{
val._uint = i;
}
/// Construct a new AnyScalar object of type ATTRTYPE_QWORD and set the given
/// unsigned value.
inline AnyScalar(unsigned long long l)
: atype(ATTRTYPE_QWORD)
{
val._ulong = l;
}
/// Construct a new AnyScalar object of type ATTRTYPE_FLOAT and set the given
/// floating point value.
inline AnyScalar(float f)
: atype(ATTRTYPE_FLOAT)
{
val._float = f;
}
/// Construct a new AnyScalar object of type ATTRTYPE_DOUBLE and set the
/// given floating point value.
inline AnyScalar(double d)
: atype(ATTRTYPE_DOUBLE)
{
val._double = d;
}
/// Construct a new AnyScalar object of type ATTRTYPE_STRING and set the
/// given string value.
inline AnyScalar(const char *s)
: atype(ATTRTYPE_STRING)
{
if (s == NULL)
val._string = new std::string;
else
val._string = new std::string(s);
}
/// Construct a new AnyScalar object of type ATTRTYPE_STRING and set the
/// given string value.
inline AnyScalar(const std::string &s)
: atype(ATTRTYPE_STRING)
{
val._string = new std::string(s);
}
/// Destroy the object: free associated string memory if necessary.
inline ~AnyScalar()
{
if (atype == ATTRTYPE_STRING) {
delete val._string;
val._string = NULL;
}
}
/// Copy-constructor to deal with enclosed strings. Transfers type and
/// value.
inline AnyScalar(const AnyScalar &a)
: atype(a.atype)
{
switch(atype)
{
case ATTRTYPE_INVALID:
break;
case ATTRTYPE_BOOL:
case ATTRTYPE_CHAR:
case ATTRTYPE_SHORT:
case ATTRTYPE_INTEGER:
val._int = a.val._int;
break;
case ATTRTYPE_BYTE:
case ATTRTYPE_WORD:
case ATTRTYPE_DWORD:
val._uint = a.val._uint;
break;
case ATTRTYPE_LONG:
val._long = a.val._long;
break;
case ATTRTYPE_QWORD:
val._ulong = a.val._ulong;
break;
case ATTRTYPE_FLOAT:
val._float = a.val._float;
break;
case ATTRTYPE_DOUBLE:
val._double = a.val._double;
break;
case ATTRTYPE_STRING:
val._string = new std::string(*a.val._string);
break;
}
}
/// Assignment operator to deal with enclosed strings. Transfers type and
/// value.
inline AnyScalar& operator=(const AnyScalar &a)
{
// check if we are to assign ourself
if (this == &a) return *this;
if (atype == ATTRTYPE_STRING) {
delete val._string;
val._string = NULL;
}
atype = a.atype;
switch(atype)
{
case ATTRTYPE_INVALID:
assert(0);
break;
case ATTRTYPE_BOOL:
case ATTRTYPE_CHAR:
case ATTRTYPE_SHORT:
case ATTRTYPE_INTEGER:
val._int = a.val._int;
break;
case ATTRTYPE_BYTE:
case ATTRTYPE_WORD:
case ATTRTYPE_DWORD:
val._uint = a.val._uint;
break;
case ATTRTYPE_LONG:
val._long = a.val._long;
break;
case ATTRTYPE_QWORD:
val._ulong = a.val._ulong;
break;
case ATTRTYPE_FLOAT:
val._float = a.val._float;
break;
case ATTRTYPE_DOUBLE:
val._double = a.val._double;
break;
case ATTRTYPE_STRING:
val._string = new std::string(*a.val._string);
break;
}
return *this;
}
/// Comparison operator. Directly compares type _and_ value. Does NOT
/// attempt to convert the values into a common domain.
bool operator==(const AnyScalar &a) const;
/// Comparison operator: Directly compares type _and_ value. Does NOT
/// attempt to convert the values into a common domain.
inline bool operator!=(const AnyScalar &a) const
{ return !(*this == a); }
/// Return the type identifier of the object.
inline attrtype_t getType() const
{
return atype;
}
/// Returns true if this object contains a boolean value.
inline bool isBooleanType() const
{
return (atype == ATTRTYPE_BOOL);
}
/// Returns true if this object contains one of the integer types.
inline bool isIntegerType() const
{
return (atype == ATTRTYPE_BOOL ||
atype == ATTRTYPE_CHAR || atype == ATTRTYPE_SHORT ||
atype == ATTRTYPE_INTEGER || atype == ATTRTYPE_LONG ||
atype == ATTRTYPE_BYTE || atype == ATTRTYPE_WORD ||
atype == ATTRTYPE_DWORD || atype == ATTRTYPE_QWORD);
}
/// Returns true if this object contains one of the floating point types.
inline bool isFloatingType() const
{
return (atype == ATTRTYPE_FLOAT || atype == ATTRTYPE_DOUBLE);
}
/// Attempts to convert the current type/value into the given type. Returns
/// false if the value could not be represented in the new type, the new
/// type is set nonetheless. See the getXXX below on how the new value is
/// computed from the old type.
bool convertType(attrtype_t t);
/// Changes the current type and resets the contents without attempting to
/// convert the enclosed value.
void resetType(attrtype_t t);
// *** attrtype_t to string and string to attrtype_t functions
/// Returns true if the attrtype_t is a valid type identifier.
static bool isValidAttrtype(attrtype_t at);
/// Returns the attrtype identifier of a string, throws ConversionException
/// if s does not specify a valid type name.
static attrtype_t stringToType(const std::string &s)
{
return stringToType(s.c_str());
}
/// Returns the attrtype identifier a string, throws ConversionException if
/// it does not specify a valid type name.
static attrtype_t stringToType(const char *s);
/// Returns a const char* for each attrtype_t.
static std::string getTypeString(attrtype_t at);
/// Returns a string for this AnyScalar's type.
inline std::string getTypeString() const
{
return getTypeString(atype);
}
// *** Type and Value Length Functions
/// Return the storage length of the type in bytes. Beware that
/// getTypeLength(bool) == 0.
inline int getTypeLength() const
{
return getTypeLength(atype);
}
/// Return the storage length of the type in bytes. Beware that
/// getTypeLength(bool) == 0.
static int getTypeLength(attrtype_t t);
/// Boolean check if this type is of fixed length.
static bool isFixedLength(attrtype_t t)
{
return getTypeLength(t) >= 0;
}
/// Boolean check if this type is of fixed length.
inline bool isFixedLength() const
{
return isFixedLength(atype);
}
/// Return the storage length of this value (mark the different to
/// getTypeLength())
unsigned int getValueLength() const;
// *** Setters
// Sets the value, converting the input to the currently set type if
// necessary. Returns false if the input could not be converted into the
// right type.
/** Change the value of the current object to i. Converting the integer
* to this object's type if necessary.
*
* - boolean: the integer i is cut to 0 or 1.
* - char: cut to -128..127 returns false if out of range.
* - short: cut to -32768..32767 return false if out of range.
* - byte: cut to 0..255 returns false if out of range.
* - word: cut to 0..65536 returns false if out of range.
* - int: no conversion.
* - dword: cut to 0..4294967295 return false if it was negative.
* - long: no cutting necessary.
* - qword: cut to positive number.
* - float: integer stored as floating point
* - double: integer stored as floating point
* - string: integer is stringified.
*/
bool setInteger(int i);
/** Change the value of the current object to l. Converting the long
* long integer to this object's type if necessary. If the long long does
* not fully fit into the current type, then this function returns false.
*
* - boolean: the long i is cut to 0 or 1.
* - char: cut to -128..127 returns false if out of range.
* - short: cut to -32768..32767 return false if out of range.
* - int: cut to -2147483646..2147483647 returns false if out of range.
* - byte: cut to 0..255 returns false if out of range.
* - word: cut to 0..65536 returns false if out of range.
* - dword: cut to 0..4294967295 return false if out of range.
* - long: no conversion
* - qword: cut to positive number.
* - float: long stored as floating point
* - double: long stored as floating point
* - string: long is stringified.
*/
bool setLong(long long l);
/** Change the value of the current object to d. Converting the floating
* point to this object's type if necessary.
*
* - boolean: [0:0.5] is false, (0.5:1] is true. else true and return false.
* - char: truncated to integer ranged -128..127 returns false if out of range.
* - short: truncated to integer ranged -32768..32767 return false if out of range.
* - int: truncated to integer ranged -2147483646..2147483647 returns false if out of range.
* - byte: truncated to integer ranged 0..255 returns false if out of range.
* - word: truncated to integer ranged 0..65536 returns false if out of range.
* - dword: truncated to integer ranged 0..4294967295 return false if out of range.
* - long: truncated to integer ranged -9223372036854775806..9223372036854775807
* - qword: truncated to integer ranged 0..18446744073709551615
* - float: truncated to single-precision
* - double: no conversion
* - string: double is stringified.
*/
bool setDouble(double d);
/** Change the value of the current object to s. Converting the string
* to this object's type if necessary. If this string cannot be converted
* to say an integer, then this function returns false.
*
* - boolean: "0", "f", "false", "n" and "no" are false,
* "1", "t", "true", "y" and "yes" are true. else returns false.
* - char: string read using strtol and truncated to -128..127
returns false if out of range or unparseable.
* - short: string read using strtol and truncated to -32768..32767
returns false if out of range or unparseable.
* - int: string read using strtol returns false if out of range or unparseable.
* - long: string read using strtoll returns false if out of range or unparseable.
* - byte: string read using strtoul and truncated to 0..255
returns false if out of range or unparseable.
* - word: string read using strtoul and truncated to 0..65535
returns false if out of range or unparseable.
* - dword: string read using strtoul returns false if out of range or unparseable.
* - qword: string read using strtoull returns false if out of range or unparseable.
* - float: string read using strtod and converted to single-precision
returns false if unparseable.
* - double: string read using strtod returns false if unparseable.
* - string: no conversion
*/
bool setString(const std::string &s);
/// Change the value of the current object to s. This string s must be
/// quoted: "str". This function resolves escape sequences like \n.
bool setStringQuoted(const std::string &s);
/** Change the type _and_ value of the current object to s. The current
* type is set if the given string can be converted to an integer or a
* floating point number. This was required because e.g. the usual input
* from files or perl are all untyped strings. The following input
* conversions are tested and yield the given types:
*
* - boolean: no boolean strings are matched!
* - int: input was readable by strtoll and is small enough.
* - long: input was readable by strtoll
* - double: input was readble by strtod
* - string: all above failed.
*
* @return reference to this for chaining.
*/
AnyScalar& setAutoString(const std::string &input);
// *** Getters
// Return the enclosed value in different types, converting if
// necessary. If the enclosed value cannot be converted these functions
// throw a ConversionError exception.
/** Return the value converted to a boolean. If the enclosed value could
* not be converted this function throws a ConversionException.
*
* - boolean: no conversion
* - char/short/int/long: test integer != 0
* - byte/word/dword/qword: test integer != 0
* - float/double: test float != 0.0
* - string: "0", "f", "false", "n", "no" are false,
* "1", "t", "true", "y", "yes" are true
* other strings throw ConversionException.
*/
bool getBoolean() const;
/** Return the value converted to an integer. If the enclosed value could
* not be converted this function throws a ConversionException.
*
* - boolean: returns 0 or 1.
* - char/short/int: return the integer
* - byte/word/dword: return the integer (possibly as a negative number)
* - long: cut to -2147483646..2147483647.
* - qword: cut to 0..4294967295
* - float/double: machine-conversion floating point to integer
* - string: Attempt to strtol the string, throws ConversionException if this fails.
*/
int getInteger() const;
/** Return the value converted to an unsigned integer. If the enclosed
* value could not be converted this function throws a ConversionException.
*
* - boolean: returns 0 or 1.
* - char/short/int: return the integer (possibly representing a negative number as positive)
* - byte/word/dword: return the unsigned integer
* - long: cut to 0..4294967295 (also misrepresenting because of machine-conversion)
* - qword: cut to 0..4294967295
* - float/double: machine-conversion floating point to unsigned integer.
* - string: Attempt to strtoul the string, throws ConversionException if this fails.
*/
unsigned int getUnsignedInteger() const;
/// Alias for getInteger()
inline int getInt() const
{
return getInteger();
}
/// Alias for getUnsignedInteger()
inline unsigned int getUInt() const
{
return getUnsignedInteger();
}
/** Return the value converted to a long integer. If the enclosed value
* could not be converted this function throws a ConversionException.
*
* - boolean: returns 0 or 1.
* - char/short/int: return the integer (possibly representing a negative number as positive)
* - byte/word/dword: return the unsigned integer
* - long: no conversion
* - qword: return the integer (possibly converting a large long to a negative)
* - float/double: machine-conversion floating point to long long.
* - string: Attempt to strtoll the string, throws ConversionException if this fails.
*/
long long getLong() const;
/** Return the value converted to an unsigned long integer. If the enclosed
* value could not be converted this function throws a ConversionException.
*
* - boolean: returns 0 or 1.
* - char/short/int: return the integer (possibly representing a negative number as positive)
* - byte/word/dword: return the unsigned integer
* - long: return the long (possibly interpreting a negative long as a large positive)
* - qword: no conversion
* - float/double: machine-conversion floating point to unsigned long long.
* - string: Attempt to strtoull the string, throws ConversionException if this fails.
*/
unsigned long long getUnsignedLong() const;
/// Alias for getUnsignedLong()
unsigned long long getULong() const
{
return getUnsignedLong();
}
/** Return the value converted to a double. If the enclosed value could not
* be converted this function throws a ConversionException.
*
* - boolean: returns 0 or 1.0.
* - char/short/int/long: return the integer as a float
* - byte/word/dword/qword: return the unsigned integer as a float
* - float: cast to double.
* - double: no conversion
* - string: Attempt to strtod the string, throws ConversionException if this fails.
*/
double getDouble() const;
/** Return the value converted to a string. This function never throws
* ConversionException.
*
* - boolean: returns "false" or "true"
* - char/short/int/long: return the integer as a string using boost::lexical_cast
* - byte/word/dword/qword: return the unsigned integer as a string using boost::lexical_cast
* - float/double: return float as a string using boost::lexical_cast
* - string: return the string.
*/
std::string getString() const;
/** Return the value converted to a quoted string. This function never
* throws ConversionException. It calls getString() and adds " and escape
* sequences. */
std::string getStringQuoted() const;
// *** Unary Operators
/** Unary prefix - operator. Attempts to convert the AnyScalar to a numeric
* value.
*
* - bool: invert the boolean value
* - char/short/int/long: switch sign
* - byte/word/dword/qword: negated the number even tho it doesn't make sense.
* - float/double: switch sign
* - string: attempt to convert the string to a double and negate it!
* May throw a ConversionException
*/
AnyScalar operator-() const;
// *** Binary Operators
// These will convert the two operands to the largest common type of the
// same field.
#ifndef SWIG // obviously too strange for SWIG
private:
/** Binary arithmetic template operator. Converts the two AnyScalars into the
* largest type of their common field. If a string cannot be converted to a
* numeric of the same field as the other operand a ConversionException is
* thrown.
* Conversion chart: * signifies the operator
- bool * (any): ConversionException. Don't consider boolean as the field F_2.
- char|short|int * char|short|int: return AnyScalar is an integer.
- byte|word|dword * char|short|int: returned AnyScalar is a signed integer.
- byte|word|dword * byte|word|dword: returned AnyScalar is an unsigned integer.
- long * char|short|int|long|byte|word|dword|qword: returned AnyScalar is a signed long (long).
- qword * char|short|int|long: : returned AnyScalar is a signed long (long).
- qword * byte|word|dword|qword: : returned AnyScalar is an unsigned long (long).
- float|double * char|short|int|long|byte|word|dword|qword: calculate as floating point number
- string * char|short|int: convert string to integer, calculate as signed integer.
- string * byte|word|dword: convert string to unsigned integer, calculate as unsigned integer.
- string * long: convert string to long integer, calculate as long.
- string * qword: convert string to unsigned long integer, calculate as unsigned long.
- string * float|double: convert string to floating point, calculate as floating point.
- string * string: only valid for "+" operator as string concatenation.
*/
template <template <typename Type> class Operator, char OpName>
AnyScalar binary_arith_op(const AnyScalar &b) const;
#endif
public:
/// Instantiation of binary_arith_op for "+" plus.
inline AnyScalar operator+(const AnyScalar &b) const
{
return binary_arith_op<std::plus, '+'>(b);
}
/// Instantiation of binary_arith_op for "-" minus.
inline AnyScalar operator-(const AnyScalar &b) const
{
return binary_arith_op<std::minus, '-'>(b);
}
/// Instantiation of binary_arith_op for "*" multiplication.
inline AnyScalar operator*(const AnyScalar &b) const
{
return binary_arith_op<std::multiplies, '*'>(b);
}
/// Instantiation of binary_arith_op for "/" division.
inline AnyScalar operator/(const AnyScalar &b) const
{
return binary_arith_op<std::divides, '/'>(b);
}
/// Alias for operator+ in script languages
inline AnyScalar add(const AnyScalar &b) const
{
return (*this + b);
}
/// Alias for operator- in script languages
inline AnyScalar subtract(const AnyScalar &b) const
{
return (*this - b);
}
/// Alias for operator* in script languages
inline AnyScalar multiply(const AnyScalar &b) const
{
return (*this * b);
}
/// Alias for operator/ in script languages
inline AnyScalar divide(const AnyScalar &b) const
{
return (*this / b);
}
#ifndef SWIG // obviously too strange for SWIG
private:
/** Binary comparison template operator. Converts the two AnyScalars into the
* largest type of their common field. If a string cannot be converted to a
* numeric of the same field as the other operand a ConversionException is
* thrown. Operator is the STL operator class. OpNum is an identifier for
* the operator name string within the template.
* Conversion chart: * signifies the operator
- bool * bool: usual comparison
- bool * (any): ConversionException. Don't consider boolean as the field F_2.
- char|short|int * char|short|int: compare as signed integers.
- byte|word|dword * char|short|int: compare as signed integers.
- byte|word|dword * byte|word|dword: compare as unsigned integers.
- long * char|short|int|long|byte|word|dword|qword: compare as signed long integer
- qword * char|short|int|long: : compare as signed long integer
- qword * byte|word|dword|qword: : compare an unsigned long (long).
- float|double * char|short|int|long|byte|word|dword|qword: compare as floating point numbers
- string * char|short|int: convert string to integer, compare as signed integer.
- string * byte|word|dword: convert string to unsigned integer, compare as unsigned integer.
- string * long: convert string to long integer, compare as long.
- string * qword: convert string to unsigned long integer, compare as unsigned long.
- string * float|double: convert string to floating point, compare as floating point.
- string * string: usual string comparison operators.
*/
template <template <typename Type> class Operator, int OpNum>
bool binary_comp_op(const AnyScalar &b) const;
#endif
// *** Don't use the operators themselves, because operator== is defined
// *** differently above.
public:
/// Instantiation of binary_comp_op for "==" equality.
inline bool equal_to(const AnyScalar &b) const
{
return binary_comp_op<std::equal_to, 0>(b);
}
/// Instantiation of binary_comp_op for "!=" inequality.
inline bool not_equal_to(const AnyScalar &b) const
{
return binary_comp_op<std::not_equal_to, 1>(b);
}
/// Instantiation of binary_comp_op for "<" less-than.
inline bool less(const AnyScalar &b) const
{
return binary_comp_op<std::less, 2>(b);
}
/// Instantiation of binary_comp_op for ">" greater-than.
inline bool greater(const AnyScalar &b) const
{
return binary_comp_op<std::greater, 3>(b);
}
/// Instantiation of binary_comp_op for "<=" less-or-equal-than.
inline bool less_equal(const AnyScalar &b) const
{
return binary_comp_op<std::less_equal, 4>(b);
}
/// Instantiation of binary_comp_op for ">=" greater-or-equal-than.
inline bool greater_equal(const AnyScalar &b) const
{
return binary_comp_op<std::greater_equal, 5>(b);
}
};
/// Make AnyScalar outputtable to ostream
static inline std::ostream& operator<< (std::ostream &stream, const AnyScalar &as)
{
return stream << as.getString();
}
} // namespace stx
#endif // VGS_AnyScalar_H