ultimatepp/tutorial/CoreTutorial/Value2.cpp
cxl 2fa5bd86a1 New Core Tutorial
git-svn-id: svn://ultimatepp.org/upp/trunk@10538 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-12-12 10:08:40 +00:00

90 lines
2.9 KiB
C++

#include "Tutorial.h"
void Value2Tutorial()
{
/// .Client types and `Value`, `RawValue`, `RichValue`
/// There are two Value compatibility levels. The simple one, `RawValue`, has little
/// requirements for the type used - only copy constructor and assignment operator are
/// required (and there are even forms of `RawValue` that work for types missing these):
struct RawFoo {
String x;
// default copy constructor and assignment operator are provided by compiler
};
/// To convert such type to `Value`, use `RawToValue`:
RawFoo h;
h.x = "hello";
Value q = RawToValue(h);
DUMP(q.Is<RawFoo>());
/// To convert it back, us 'To' templated member function of `Value`, it returns a constant
/// reference to the value:
DUMP(q.To<RawFoo>().x);
/// `RichValue` level `Value`s provide more operations for `Value` - equality test,
/// `IsNull` test, hashing, conversion to text, serialization (possibly to XML and Json),
/// comparison. In order to make serialization work, type must also have assigned an
/// integer id (client types should use ids in range 10000..20000). Type can provide the
/// support for these operations via template function specializations or (perhaps more
/// convenient) using defined methods and inheriting from `ValueType` base class template:
struct Foo : ValueType<Foo, 10010> {
int x;
Foo(const Nuller&) { x = Null; }
Foo(int x) : x(x) {}
Foo() {}
// We provide these methods to allow automatic conversion of Foo to/from Value
operator Value() const { return RichToValue(*this); }
Foo(const Value& v) { *this = v.Get<Foo>(); }
String ToString() const { return AsString(x); }
unsigned GetHashValue() const { return x; }
void Serialize(Stream& s) { s % x; }
bool operator==(const Foo& b) const { return x == b.x; }
bool IsNullInstance() const { return IsNull(x); }
int Compare(const Foo& b) const { return SgnCompare(x, b.x); }
// This type does not define XML nor Json serialization
};
#if 0
INITBLOCK { // This has to be at file level scope
#endif
Value::Register<Foo>(); // need to register value type integer id to allow serialization
#if 0
}
#endif
Value a = Foo(54321); // uses Foo::operator Value
Value b = Foo(54321);
Value c = Foo(600);
DUMP(a); // uses Foo::ToString
DUMP(a == b); // uses Foo::operator==
DUMP(a == c);
DUMP(c < a); // uses Foo::Compare
DUMP(IsNull(a)); // uses Foo::IsNullInstance
Foo foo = c; // Uses Foo::Foo(const Value&)
DUMP(foo);
///
String s = StoreAsString(a); // Uses Foo::Serialize
Value loaded;
// Using registered (Value::Registered) integer id creates the correct type, then uses
// Foo::Serialize to load the data from the stream
LoadFromString(loaded, s);
DUMP(loaded);
///
};