-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathAnyString1.h
executable file
·121 lines (105 loc) · 3.72 KB
/
AnyString1.h
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Source code for the implementation of AnyString in the
// slides with corrected move semantics thanks to guidance
// from Rob Stewart.
#include <string>
class AnyString {
typedef std::string string;
typedef std::u16string u16string;
typedef std::u32string u32string;
public:
enum Contains { t_none, t_s08, t_s16, t_s32 };
private:
Contains t_;
union { // Anonymous union
string s08_;
u16string s16_;
u32string s32_;
};
// Private helpers. Note placement new.
void Assign() // Default
{ t_ = t_none;}
void Assign(const string& s08) // Copy
{new (&s08_) string(s08); t_ = t_s08; }
void Assign(string&& s08) // Move
{new (&s08_) string(std::move(s08)); t_ = t_s08; }
void Assign(const u16string& s16) // Copy
{new (&s16_) u16string(s16); t_ = t_s16; }
void Assign(u16string&& s16) // Move
{new (&s16_) u16string(std::move(s16)); t_ = t_s16; }
void Assign(const u32string& s32) // Copy
{new (&s32_) u32string(s32); t_ = t_s32; }
void Assign(u32string&& s32) // Move
{new (&s32_) u32string(std::move(s32)); t_ = t_s32; }
void Assign(const AnyString& anyStr) // Copy assign
{
switch (anyStr.t_) {
case t_none: Assign(); break;
case t_s08: Assign(anyStr.s08_); break;
case t_s16: Assign(anyStr.s16_); break;
case t_s32: Assign(anyStr.s32_); break;
}
}
void Assign(AnyString&& anyStr) // Move assign
{
Contains anyStr_t = anyStr.t_;
anyStr.t_ = t_none;
switch (anyStr_t) {
case t_none: Assign(); ; break;
case t_s08: Assign(std::move(anyStr.s08_)); break;
case t_s16: Assign(std::move(anyStr.s16_)); break;
case t_s32: Assign(std::move(anyStr.s32_)); break;
}
}
// Assign from string literals uses move semantics
void Assign(const char* cptr)
{ Assign( string(cptr)); }
void Assign(const char16_t* cptr)
{ Assign(u16string(cptr)); }
void Assign(const char32_t* cptr)
{ Assign(u32string(cptr)); }
void Destroy() noexcept {
switch (t_) {
case t_none: break;
case t_s08: s08_.~string(); break;
case t_s16: s16_.~u16string(); break;
case t_s32: s32_.~u32string(); break;
}
t_ = t_none;
};
public:
// Implicitly deleted constructors
AnyString()
{ Assign(); }
AnyString(const AnyString& str)
{ Assign(str); }
AnyString(AnyString&& str)
{ Assign(std::move(str)); }
// Perfect forwarding constructor
template <typename T> AnyString(T&& str)
{ Assign(std::forward<T>(str)); }
// Implicitly deleted assignment from const reference
AnyString& operator=(const AnyString& str)
{
if (this != &str) { // Assignment to self?
Destroy(); // Explicit destroy
Assign(str); // Placement new
}
return *this;
}
// Perfect forwarding assignment
template <typename T>
AnyString& operator=(T&& str)
{
if (this !=
reinterpret_cast<volatile const void*>(&str))
{
Destroy();
Assign(std::forward<T>(str));
}
return *this;
}
~AnyString() noexcept
{
Destroy();
}
};