1 /* Boost.Flyweight basic example.
2 *
3 * Copyright 2006-2020 Joaquin M Lopez Munoz.
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 * See http://www.boost.org/libs/flyweight for library home page.
9 */
10
11 #include <boost/bind/bind.hpp>
12 #include <boost/flyweight.hpp>
13 #include <algorithm>
14 #include <iostream>
15 #include <iterator>
16 #include <sstream>
17 #include <string>
18 #include <vector>
19
20 using namespace boost::flyweights;
21 using namespace boost::placeholders;
22
23 /* Information associated to a given user of some massive system.
24 * first_name and last_name are turned into flyweights to leverage the
25 * implicit redundancy of names within the user community.
26 */
27
28 struct user_entry
29 {
30 flyweight<std::string> first_name;
31 flyweight<std::string> last_name;
32 int age;
33
34 user_entry();
35 user_entry(const char* first_name,const char* last_name,int age);
36 user_entry(const user_entry& x);
37 };
38
39 /* flyweight<std::string> default ctor simply calls the default ctor of
40 * std::string.
41 */
42
user_entry()43 user_entry::user_entry()
44 {}
45
46 /* flyweight<std::string> is constructible from a const char* much as
47 * a std::string is.
48 */
49
user_entry(const char * f,const char * l,int a)50 user_entry::user_entry(const char* f,const char* l,int a):
51 first_name(f),
52 last_name(l),
53 age(a)
54 {}
55
56 /* flyweight's are copyable and assignable --unlike std::string,
57 * copy and assignment of flyweight<std::string>s do not ever throw.
58 */
59
user_entry(const user_entry & x)60 user_entry::user_entry(const user_entry& x):
61 first_name(x.first_name),
62 last_name(x.last_name),
63 age(x.age)
64 {}
65
66 /* flyweight<std::string> has operator==,!=,<,>,<=,>= with the same
67 * semantics as those of std::string.
68 */
69
same_name(const user_entry & user1,const user_entry & user2)70 bool same_name(const user_entry& user1,const user_entry& user2)
71 {
72 bool b=user1.first_name==user2.first_name &&
73 user1.last_name==user2.last_name;
74 return b;
75 }
76
77 /* operator<< forwards to the std::string overload */
78
operator <<(std::ostream & os,const user_entry & user)79 std::ostream& operator<<(std::ostream& os,const user_entry& user)
80 {
81 return os<<user.first_name<<" "<<user.last_name<<" "<<user.age;
82 }
83
84 /* operator>> internally uses std::string's operator>> */
85
operator >>(std::istream & is,user_entry & user)86 std::istream& operator>>(std::istream& is,user_entry& user)
87 {
88 return is>>user.first_name>>user.last_name>>user.age;
89 }
90
full_name(const user_entry & user)91 std::string full_name(const user_entry& user)
92 {
93 std::string full;
94
95 /* get() returns the underlying const std::string& */
96
97 full.reserve(
98 user.first_name.get().size()+user.last_name.get().size()+1);
99
100 /* here, on the other hand, implicit conversion is used */
101
102 full+=user.first_name;
103 full+=" ";
104 full+=user.last_name;
105
106 return full;
107 }
108
109 /* flyweight<std::string> value is immutable, but a flyweight object can
110 * be assigned a different value.
111 */
112
change_name(user_entry & user,const std::string & f,const std::string & l)113 void change_name(user_entry& user,const std::string& f,const std::string& l)
114 {
115 user.first_name=f;
116 user.last_name=l;
117 }
118
main()119 int main()
120 {
121 /* play a little with a vector of user_entry's */
122
123 std::string users_txt=
124 "olegh smith 31\n"
125 "john brown 28\n"
126 "anna jones 45\n"
127 "maria garcia 30\n"
128 "john fox 56\n"
129 "anna brown 19\n"
130 "thomas smith 46\n"
131 "andrew martin 28";
132
133 std::vector<user_entry> users;
134 std::istringstream iss(users_txt);
135 while(iss){
136 user_entry u;
137 if(iss>>u)users.push_back(u);
138 }
139
140 change_name(users[0],"oleg","smith");
141
142 user_entry anna("anna","jones",20);
143 std::replace_if(
144 users.begin(),users.end(),
145 boost::bind(same_name,_1,anna),
146 anna);
147
148 std::copy(
149 users.begin(),users.end(),
150 std::ostream_iterator<user_entry>(std::cout,"\n"));
151
152 return 0;
153 }
154