mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
90 lines
2.9 KiB
C++
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);
|
|
|
|
///
|
|
};
|