-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathtinyvariant.cc
More file actions
104 lines (84 loc) · 3.22 KB
/
tinyvariant.cc
File metadata and controls
104 lines (84 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Tiny variant class. rlyeh, public domain | wtrmrkrlyeh
#include <string>
#include <functional>
struct var {
int type;
union {
int integer;
double real;
std::string *string;
std::function<void()> *callback;
};
var() : type(0), integer(0)
{}
var( const int &i ) : type(0), integer(i)
{}
var( const double &r ) : type(1), real(r)
{}
var( const std::string &r ) : type(2), string( new std::string(r) )
{}
template<unsigned N>
var( const char (&s)[N]) : type(2), string( new std::string(s) )
{}
template<typename T>
var( const T &fn ) : type(3), callback( new std::function<void()>(fn) )
{}
var( const var &other ) {
operator=( other );
}
~var() {
cleanup();
}
void cleanup() {
/**/ if( type == 3 ) delete callback, callback = 0;
else if( type == 2 ) delete string, string = 0;
type = 0;
}
var &operator=( const var &other ) {
if( &other != this ) {
cleanup();
type = other.type;
/**/ if( type == 0 ) integer = other.integer;
else if( type == 1 ) real = other.real;
else if( type == 2 ) string = new std::string( *other.string );
else if( type == 3 ) callback = new std::function<void()>( *other.callback );
}
return *this;
}
void operator()() const {
if( type == 3 ) if( *callback ) (*callback)();
}
template<typename ostream>
inline friend ostream &operator <<( ostream &os, const var &self ) {
/**/ if( self.type == 0 ) return os << self.integer, os;
else if( self.type == 1 ) return os << self.real, os;
else if( self.type == 2 ) return os << *self.string, os;
else if( self.type == 3 ) return os << '[' << self.callback << ']', os;
return os;
}
};
template<typename T> inline bool is(const var &v) { return false; }
template<> inline bool is<int>(const var &v) { return v.type == 0; }
template<> inline bool is<double>(const var &v) { return v.type == 1; }
template<> inline bool is<std::string>(const var &v) { return v.type == 2; }
template<> inline bool is<std::function<void()>>(const var &v) { return v.type == 3; }
template<typename T> inline const T& cast(const var &v) { static T t; return t = T(); }
template<> inline const int& cast<int>(const var &v) { return v.integer; }
template<> inline const double& cast<double>(const var &v) { return v.real; }
template<> inline const std::string& cast<std::string>(const var &v) { return *v.string; }
template<> inline const std::function<void()>& cast<std::function<void()>>(const var &v) { return *v.callback; }
/*
#include <iostream>
#include <assert.h>
int main() {
std::cout << "sizeof(var)=" << sizeof(var) << std::endl;
var digit = 42, other = "hello world";
std::cout << digit << std::endl; assert( is<int>(digit) );
std::cout << other << std::endl; assert( is<std::string>(other) );
other = digit;
std::cout << other << std::endl; assert( is<int>(other) );
other = []{ std::cout << "callback!" << std::endl; };
std::cout << other << std::endl;
other();
}
*/