variant provides a really convenient way to lexically cast strings and other streamable types to/from each other. More...
#include <variant.hpp>
Public Member Functions | |
variant () throw () | |
Constructs an empty object. | |
~variant () throw () | |
template<typename FromT > | |
variant (const FromT &f) throw () | |
Lexically casts f to a string. | |
variant (const std::string &f) throw () | |
Efficiency overload. | |
variant (const char *str) throw () | |
See operator=(const char *) for a note about why this exists. | |
variant (const variant &rhs) throw () | |
Copies rhs's data to this object. | |
bool | operator< (const variant &rhs) const |
Returns (this-<str() < rhs.str()). | |
bool | operator> (const variant &rhs) const |
Returns (this-<str() > rhs.str()). | |
variant & | operator= (const variant &rhs) throw () |
Copies rhs's data and returns this object. | |
variant & | operator= (const char *rhs) throw () |
This overload exists to keep the compiler/linker from generating a new instantiation of this function for each differently-lengthed (const char *) which is assigned to a variant. | |
template<typename ToType > | |
ToType | cast_to (const ToType &dflt=ToType()) const throw () |
lexically casts str() to a ToType, returning dflt if the cast fails. | |
template<typename ToType > | |
operator ToType () const throw () | |
i used to LOVE C++. | |
operator std::string () const throw () | |
Overload to avoid ambiguity in some cases. | |
operator std::string & () throw () | |
Returns the same as str(). | |
operator const std::string & () const throw () | |
Returns the same as str(). | |
operator const char * () const throw () | |
Overload to avoid ambiguity in some cases. | |
template<typename ToType > | |
variant & | operator= (const ToType &f) throw () |
Sets this object's value and returns this object. | |
std::string & | str () throw () |
Returns a reference to this object's raw string data. | |
const std::string & | str () const throw () |
Returns a const reference to this object's raw string data. | |
bool | empty () const |
Returns true if this object contains no data, else false. | |
template<typename T > | |
bool | operator== (const T &rhs) const |
Casts lhs to a T object and returns true only if that object compares as equal to rhs. | |
template<typename T > | |
bool | operator!= (const T &rhs) const |
bool | operator== (const variant &rhs) const |
Returns lhs.str() == rhs.str(). | |
bool | operator!= (const variant &rhs) const |
bool | operator== (const char *rhs) const |
Avoid an ambiguity. | |
bool | operator== (const std::string &rhs) const |
Avoid an ambiguity. | |
std::ostream & | operator<< (std::ostream &os) const |
Copies this->str() to os. | |
std::istream & | operator>> (std::istream &is) |
Reads from the input stream, appending to this->str() until the stream gives up. |
variant provides a really convenient way to lexically cast strings and other streamable types to/from each other.
All parameterized types used by this type must be:
This type is fairly light-weight, with only one std::string data member, so it should copy quickly and implicitely use std::string's CoW and reference counting features. Adding reference counting to this class would be of no benefit, and would probably hurt performance, considering that std::string's are optimized in these ways, and this type is simply a proxy for a std::string.
For some uses the variant type can replace the requirement for returning a proxy type from a type's operator[](), as discussed in Scott Meyers' More Effective C++, Item 30. This class originally was such a proxy, and then evolved into a generic solution for POD-based types, which inherently also covers most i/ostreamable types. It is less efficient than specialized proxies for, e.g. (char &), but it is also extremely easy to use, as shown here:
s11n::variant lex = 17; int bogo = lex; ulong bogol = bogo * static_cast<long>(lex); lex = "bogus string";
typedef std::map<variant,variant> LMap; LMap map;
map[4] = "one"; map["one"] = 4; map[123] = "eat this"; map['x'] = "marks the spot"; map["fred"] = 94.3 * static_cast<double>( map["one"] ); map["fred"] = 10 * static_cast<double>( map["fred"] ); map["123"] = "this was re-set"; int myint = map["one"];
Finally, Perl-ish type flexibility in C++. :)
It gets better: if we're using s11n, we can now save and load these objects at will:
s11nlite::save( map, "somefile.s11n" ); ...
LMap * map = s11nlite::load_serializable<LMap>( "somefile.s11n" );
Definition at line 240 of file variant.hpp.
s11n::Detail::variant::variant | ( | ) | throw () [inline] |
Constructs an empty object.
Calling cast_to<T>()
on an un-populated variant object will return T().
Definition at line 246 of file variant.hpp.
s11n::Detail::variant::~variant | ( | ) | throw () [inline] |
Definition at line 248 of file variant.hpp.
s11n::Detail::variant::variant | ( | const FromT & | f | ) | throw () [inline] |
Lexically casts f to a string.
Definition at line 254 of file variant.hpp.
References s11n::io::strtool::STPrivate::to_string().
s11n::Detail::variant::variant | ( | const std::string & | f | ) | throw () [inline] |
Efficiency overload.
Definition at line 262 of file variant.hpp.
s11n::Detail::variant::variant | ( | const char * | str | ) | throw () [inline] |
See operator=(const char *) for a note about why this exists.
Definition at line 269 of file variant.hpp.
s11n::Detail::variant::variant | ( | const variant & | rhs | ) | throw () [inline] |
Copies rhs's data to this object.
Definition at line 277 of file variant.hpp.
ToType s11n::Detail::variant::cast_to | ( | const ToType & | dflt = ToType() |
) | const throw () [inline] |
lexically casts str() to a ToType, returning dflt if the cast fails.
When calling this function you may need to use the following syntax to avoid compile errors:
Foo foo = lex.template cast_to<Foo>();
(It's weird, i know, and the first time i saw it, finding the solution to took me days. (Thank you, Nicolai Josuttis!))
However, in normal usage you won't need to use this function, as the generic type conversion operator does the exact same thing:
variant lex = 17; int foo = lex;
Definition at line 343 of file variant.hpp.
References s11n::io::strtool::STPrivate::from_string().
bool s11n::Detail::variant::empty | ( | ) | const [inline] |
Returns true if this object contains no data, else false.
Definition at line 422 of file variant.hpp.
s11n::Detail::variant::operator const char * | ( | ) | const throw () [inline] |
Overload to avoid ambiguity in some cases.
Useful for mixing C and C++ APIs:
variant arg = "USER"; variant user = getenv(arg);
Definition at line 389 of file variant.hpp.
s11n::Detail::variant::operator const std::string & | ( | ) | const throw () [inline] |
Returns the same as str().
Definition at line 377 of file variant.hpp.
s11n::Detail::variant::operator std::string | ( | ) | const throw () [inline] |
Overload to avoid ambiguity in some cases.
Definition at line 365 of file variant.hpp.
References str().
s11n::Detail::variant::operator std::string & | ( | ) | throw () [inline] |
Returns the same as str().
Definition at line 372 of file variant.hpp.
s11n::Detail::variant::operator ToType | ( | ) | const throw () [inline] |
i used to LOVE C++.
.. After writing this function i WORSHIP C++. The grace with which C++ handles this is pure magic, my friends.
16.8.2004 ----- stephan
Definition at line 357 of file variant.hpp.
bool s11n::Detail::variant::operator!= | ( | const variant & | rhs | ) | const [inline] |
Definition at line 444 of file variant.hpp.
References str().
bool s11n::Detail::variant::operator!= | ( | const T & | rhs | ) | const [inline] |
Definition at line 434 of file variant.hpp.
bool s11n::Detail::variant::operator< | ( | const variant & | rhs | ) | const [inline] |
std::ostream& s11n::Detail::variant::operator<< | ( | std::ostream & | os | ) | const [inline] |
Copies this->str() to os.
Definition at line 473 of file variant.hpp.
variant& s11n::Detail::variant::operator= | ( | const ToType & | f | ) | throw () [inline] |
Sets this object's value and returns this object.
Definition at line 400 of file variant.hpp.
References s11n::Detail::Private::to_string().
variant& s11n::Detail::variant::operator= | ( | const char * | rhs | ) | throw () [inline] |
This overload exists to keep the compiler/linker from generating a new instantiation of this function for each differently-lengthed (const char *) which is assigned to a variant.
Definition at line 313 of file variant.hpp.
Copies rhs's data and returns this object.
Definition at line 301 of file variant.hpp.
bool s11n::Detail::variant::operator== | ( | const std::string & | rhs | ) | const [inline] |
bool s11n::Detail::variant::operator== | ( | const char * | rhs | ) | const [inline] |
Avoid an ambiguity.
..
If rhs == 0 then this function returns true if lhs.empty().
Definition at line 455 of file variant.hpp.
bool s11n::Detail::variant::operator== | ( | const variant & | rhs | ) | const [inline] |
bool s11n::Detail::variant::operator== | ( | const T & | rhs | ) | const [inline] |
Casts lhs to a T object and returns true only if that object compares as equal to rhs.
Definition at line 429 of file variant.hpp.
bool s11n::Detail::variant::operator> | ( | const variant & | rhs | ) | const [inline] |
std::istream& s11n::Detail::variant::operator>> | ( | std::istream & | is | ) | [inline] |
Reads from the input stream, appending to this->str() until the stream gives up.
If the implementation of this function seems "wrong" to you, please read the justification in this paper:
http://s11n.net/papers/lexical_casting.html
i believe there to be no satisfying, truly generic implementation for this function :(.
Definition at line 488 of file variant.hpp.
const std::string& s11n::Detail::variant::str | ( | ) | const throw () [inline] |
Returns a const reference to this object's raw string data.
Definition at line 417 of file variant.hpp.
std::string& s11n::Detail::variant::str | ( | ) | throw () [inline] |
Returns a reference to this object's raw string data.
Definition at line 410 of file variant.hpp.
Referenced by operator std::string(), operator!=(), operator<(), operator==(), and operator>().