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 147 148 149 150 151 152 153 154 155 156
|
/* Boost.Flyweight basic example.
*
* Copyright 2006-2023 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#include <boost/bind/bind.hpp>
#include <boost/flyweight.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
using namespace boost::flyweights;
using namespace boost::placeholders;
/* Information associated to a given user of some massive system.
* first_name and last_name are turned into flyweights to leverage the
* implicit redundancy of names within the user community.
*/
struct user_entry
{
flyweight<std::string> first_name;
flyweight<std::string> last_name;
int age;
user_entry();
user_entry(const char* first_name,const char* last_name,int age);
user_entry(const user_entry& x);
};
/* flyweight<std::string> default ctor simply calls the default ctor of
* std::string.
*/
user_entry::user_entry()
{}
/* flyweight<std::string> is constructible from a const char* much as
* a std::string is.
*/
user_entry::user_entry(const char* f,const char* l,int a):
first_name(f),
last_name(l),
age(a)
{}
/* flyweight's are copyable and assignable --unlike std::string,
* copy and assignment of flyweight<std::string>s do not ever throw.
*/
user_entry::user_entry(const user_entry& x):
first_name(x.first_name),
last_name(x.last_name),
age(x.age)
{}
/* flyweight<std::string> has operator==,!=,<,>,<=,>= with the same
* semantics as those of std::string.
*/
bool same_name(const user_entry& user1,const user_entry& user2)
{
bool b=user1.first_name==user2.first_name &&
user1.last_name==user2.last_name;
return b;
}
/* operator<< forwards to the std::string overload */
std::ostream& operator<<(std::ostream& os,const user_entry& user)
{
return os<<user.first_name<<" "<<user.last_name<<" "<<user.age;
}
/* operator>> internally uses std::string's operator>> */
std::istream& operator>>(std::istream& is,user_entry& user)
{
return is>>user.first_name>>user.last_name>>user.age;
}
std::string full_name(const user_entry& user)
{
std::string full;
/* get() returns the underlying const std::string&.
* Smart-pointer syntax can also be used.
*/
full.reserve(
user.first_name.get().size()+ /* using get() */
user.last_name->size()+1); /* using operator-> */
/* here, on the other hand, implicit conversion is used */
full+=user.first_name;
full+=" ";
full+=user.last_name;
return full;
}
/* flyweight<std::string> value is immutable, but a flyweight object can
* be assigned a different value.
*/
void change_name(user_entry& user,const std::string& f,const std::string& l)
{
user.first_name=f;
user.last_name=l;
}
int main()
{
/* play a little with a vector of user_entry's */
std::string users_txt=
"olegh smith 31\n"
"john brown 28\n"
"anna jones 45\n"
"maria garcia 30\n"
"john fox 56\n"
"anna brown 19\n"
"thomas smith 46\n"
"andrew martin 28";
std::vector<user_entry> users;
std::istringstream iss(users_txt);
while(iss){
user_entry u;
if(iss>>u)users.push_back(u);
}
change_name(users[0],"oleg","smith");
user_entry anna("anna","jones",20);
std::replace_if(
users.begin(),users.end(),
boost::bind(same_name,_1,anna),
anna);
std::copy(
users.begin(),users.end(),
std::ostream_iterator<user_entry>(std::cout,"\n"));
return 0;
}
|