• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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