-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphone_book_ch18.ixx
146 lines (123 loc) · 4.26 KB
/
phone_book_ch18.ixx
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
export module phone_book_ch18;
import std;
using namespace std;
export class Person
{
public:
// Two-parameter constructor automatically creates initials.
//
// Warning: delegating to the 3-parameter constructor as follows doesn't work:
// Person(std::string firstName, std::string lastName)
// : Person{ std::move(firstName), std::move(lastName),
// std::format("{}{}", firstName[0], lastName[0]) }
// because then firstName and lastName could already have been moved into
// temporary std::strings before firstName[O] and lastName[O] are used in
// the call to std::format().
explicit Person(std::string firstName, std::string lastName)
: m_firstName{ std::move(firstName) }
, m_lastName{ std::move(lastName) }
{
m_initials = std::format("{}{}", m_firstName[0], m_lastName[0]);
}
Person() = default;
explicit Person(std::string firstName, std::string lastName, std::string initials)
: m_firstName{ std::move(firstName) }
, m_lastName{ std::move(lastName) }
, m_initials{ std::move(initials) }
{
}
const std::string& getFirstName() const { return m_firstName; }
void setFirstName(std::string firstName) { m_firstName = std::move(firstName); }
const std::string& getLastName() const { return m_lastName; }
void setLastName(std::string lastName) { m_lastName = std::move(lastName); }
const std::string& getInitials() const { return m_initials; }
void setInitials(std::string initials) { m_initials = std::move(initials); }
void output(std::ostream& output) const
{
std::println(output, "{} {} ({})", getFirstName(), getLastName(), getInitials());
}
// Only this single line of code is needed to add support
// for all six comparison operators.
[[nodiscard]] auto operator<=>(const Person&) const = default;
operator std::string() const
{
return std::format("{} {}", getFirstName(), getLastName());
}
private:
std::string m_firstName;
std::string m_lastName;
std::string m_initials;
};
export std::ostream& operator<<(std::ostream& os, const Person& person)
{
os << std::quoted(person.getFirstName())
<< std::quoted(person.getLastName())
<< std::quoted(person.getInitials());
return os;
}
export std::istream& operator>>(std::istream& is, Person& person)
{
std::string firstName, lastName, initials;
is >> std::quoted(firstName)
>> std::quoted(lastName)
>> std::quoted(initials);
person.setFirstName(std::move(firstName));
person.setLastName(std::move(lastName));
person.setInitials(std::move(initials));
return is;
}
export Person operator ""_p(const char* s, std::size_t)
{
std::istringstream input{ s };
std::string firstName, lastName;
// The following extraction operator will stop at the first whitespace,
// which is exactly what we need to extract the first name, because the
// first name is not allowed to contain any whitespace.
input >> firstName;
// After the first name, there is at least one whitespace in the name.
// The following statement consumes all whitespace at the current
// position in the stream.
input >> std::ws;
// Finally, extract the last name by simply reading everything remaining
// in the input stream.
getline(input, lastName);
return Person{ std::move(firstName), std::move(lastName) };
}
export class PhoneBook final{
using PhoneNumber = string;
public:
bool numberExist(const Person& person, string_view phonenum) {
auto [begin, end] {m_phonebook.equal_range(person)};
for (auto iter{ begin }; iter != end; ++iter) {
if (iter->second == phonenum) {
return true;
}
}
return false;
}
void addNumber(const Person& person, string_view phonenum) {
if (!numberExist(person, phonenum)) {
m_phonebook.emplace( person, phonenum);
}
}
void removeNumber(const Person& person, string_view phonenum) {
auto [begin, end] {m_phonebook.equal_range(person)};
for (auto iter{ begin }; iter != end; ++iter) {
if (iter->second == phonenum) {
m_phonebook.erase(iter);
break;
}
}
}
vector<PhoneNumber> getAllPhoneNumber(const Person& person) const {
auto [begin, end] {m_phonebook.equal_range(person)};
/*vector<PhoneNumber> vphone;
for (auto iter{ begin }; iter != end; ++iter) {
vphone.push_back(iter->second);
}
return vphone;*/
return ranges::subrange{ begin,end}| views::values | ranges::to<vector>();
}
private:
multimap<Person, PhoneNumber> m_phonebook;
};