summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/flyweight/example/basic.cpp
blob: 405dff721a4261ea64a727dfadfe8da30bab3569 (plain)
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
/* Boost.Flyweight basic example.
 *
 * Copyright 2006-2008 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.hpp>
#include <boost/flyweight.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

using namespace boost::flyweights;

/* 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& */

  full.reserve(
    user.first_name.get().size()+user.last_name.get().size()+1);

  /* 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;
}