• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Boost.Flyweight example of custom factory.
2  *
3  * Copyright 2006-2008 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 /* We include the default components of Boost.Flyweight except the factory,
12  * which will be provided by ourselves.
13  */
14 #include <boost/flyweight/flyweight.hpp>
15 #include <boost/flyweight/factory_tag.hpp>
16 #include <boost/flyweight/static_holder.hpp>
17 #include <boost/flyweight/simple_locking.hpp>
18 #include <boost/flyweight/refcounted.hpp>
19 #include <boost/tokenizer.hpp>
20 #include <functional>
21 #include <iostream>
22 #include <set>
23 
24 using namespace boost::flyweights;
25 
26 /* custom factory based on std::set with some logging capabilities */
27 
28 /* Entry is the type of the stored objects. Value is the type
29  * on which flyweight operates, that is, the T in flyweoght<T>. It
30  * is guaranteed that Entry implicitly converts to const Value&.
31  * The factory class could accept other template arguments (for
32  * instance, a comparison predicate for the values), we leave it like
33  * that for simplicity.
34  */
35 
36 template<typename Entry,typename Key>
37 class verbose_factory_class
38 {
39   /* Entry store. Since Entry is implicitly convertible to const Key&,
40    * we can directly use std::less<Key> as the comparer for std::set.
41    */
42 
43   typedef std::set<Entry,std::less<Key> > store_type;
44 
45   store_type store;
46 
47 public:
48   typedef typename store_type::iterator handle_type;
49 
insert(const Entry & x)50   handle_type insert(const Entry& x)
51   {
52     /* locate equivalent entry or insert otherwise */
53 
54     std::pair<handle_type, bool> p=store.insert(x);
55     if(p.second){ /* new entry */
56       std::cout<<"new: "<<(const Key&)x<<std::endl;
57     }
58     else{         /* existing entry */
59       std::cout<<"hit: "<<(const Key&)x<<std::endl;
60     }
61     return p.first;
62   }
63 
erase(handle_type h)64   void erase(handle_type h)
65   {
66     std::cout<<"del: "<<(const Key&)*h<<std::endl;
67     store.erase(h);
68   }
69 
entry(handle_type h)70   const Entry& entry(handle_type h)
71   {
72     return *h; /* handle_type is an iterator */
73   }
74 };
75 
76 /* Specifier for verbose_factory_class. The simplest way to tag
77  * this struct as a factory specifier, so that flyweight<> accepts it
78  * as such, is by deriving from boost::flyweights::factory_marker.
79  * See the documentation for info on alternative tagging methods.
80  */
81 
82 struct verbose_factory: factory_marker
83 {
84   template<typename Entry,typename Key>
85   struct apply
86   {
87     typedef verbose_factory_class<Entry,Key> type;
88   } ;
89 };
90 
91 /* ready to use it */
92 
93 typedef flyweight<std::string,verbose_factory> fw_string;
94 
main()95 int main()
96 {
97   typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
98 
99 
100   std::string text=
101     "I celebrate myself, and sing myself, "
102     "And what I assume you shall assume, "
103     "For every atom belonging to me as good belongs to you. "
104 
105     "I loafe and invite my soul, "
106     "I lean and loafe at my ease observing a spear of summer grass. "
107 
108     "My tongue, every atom of my blood, form'd from this soil, this air, "
109     "Born here of parents born here from parents the same, and their "
110     "    parents the same, "
111     "I, now thirty-seven years old in perfect health begin, "
112     "Hoping to cease not till death.";
113 
114   std::vector<fw_string> v;
115 
116   text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
117   for(text_tokenizer::iterator it=tok.begin();it!=tok.end();){
118     v.push_back(fw_string(*it++));
119   }
120 
121   return 0;
122 }
123