(root_name);
43 | }
44 | };
45 |
46 | struct HtmlBuilder
47 | {
48 | HtmlBuilder(string root_name)
49 | {
50 | root.name = root_name;
51 | }
52 |
53 | // void to start with
54 | HtmlBuilder& add_child(string child_name, string child_text)
55 | {
56 | HtmlElement e{ child_name, child_text };
57 | root.elements.emplace_back(e);
58 | return *this;
59 | }
60 |
61 | string str() { return root.str(); }
62 |
63 | operator HtmlElement() const { return root; }
64 | HtmlElement root;
65 | };
66 |
67 | int main()
68 | {
69 | // hello
70 | auto text = "hello";
71 | string output;
72 | output += "";
73 | output += text;
74 | output += "
";
75 | printf("%s
", text);
76 |
77 | //
78 | string words[] = { "hello", "world" };
79 | ostringstream oss;
80 | oss << "";
81 | for (auto w : words)
82 | oss << " - " << w << "
";
83 | oss << "
";
84 | printf(oss.str().c_str());
85 |
86 | // easier
87 | HtmlBuilder builder{ "ul" };
88 | builder.add_child("li", "hello").add_child("li", "world");
89 | cout << builder.str() << endl;
90 |
91 | HtmlElement e = HtmlElement::build("ul")
92 | ->add_child("li", "hello").add_child("li", "world");
93 | cout << e.str() << endl;
94 |
95 | getchar();
96 | return 0;
97 | }
--------------------------------------------------------------------------------
/composite/composite.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 |
5 | struct Neuron
6 | {
7 | vector in, out;
8 |
9 | Neuron() {}
10 |
11 | template void connect_to(T& other);
12 |
13 | Neuron* begin() { return this; }
14 | Neuron* end() { return this + 1; }
15 | };
16 |
17 | template
18 | void Neuron::connect_to(T& other) {
19 | for (Neuron& to : other)
20 | connect_to(to);
21 | }
22 |
23 | template<>
24 | void Neuron::connect_to(Neuron& other) {
25 | out.push_back(&other);
26 | other.in.push_back(this);
27 | }
28 |
29 | struct NeuronLayer : vector
30 | {
31 | NeuronLayer(int count)
32 | {
33 | while (count --> 0)
34 | emplace_back(Neuron{});
35 | }
36 |
37 | template void connect_to(T& other)
38 | {
39 | for (Neuron& from : *this)
40 | for (Neuron& to : other)
41 | from.connect_to(to);
42 | }
43 | };
44 |
45 | int main()
46 | {
47 | Neuron n, n2;
48 | NeuronLayer nl{3}, nl2{5};
49 |
50 | n.connect_to(n2); // Neuron::connect_to
51 | n.connect_to(nl); // Neuron::connect_to
52 | nl.connect_to(n); // what we did begin()/end() for
53 | nl.connect_to(nl2); // NL::connect_to
54 |
55 | getchar();
56 | return 0;
57 | }
--------------------------------------------------------------------------------
/facet-builders/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(FILES facet-builders.cpp
2 | Person.h Person.cpp
3 | PersonBuilder.h PersonBuilder.cpp
4 | PersonJobBuilder.h PersonAddressBuilder.h)
5 | add_executable(FacetBuilders ${FILES})
--------------------------------------------------------------------------------
/facet-builders/Person.cpp:
--------------------------------------------------------------------------------
1 | #include "Person.h"
2 | #include "PersonBuilder.h"
3 |
4 | PersonBuilder Person::create()
5 | {
6 | return PersonBuilder{};
7 | }
--------------------------------------------------------------------------------
/facet-builders/Person.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | using namespace std;
4 | using namespace std::string_literals;
5 | #include
6 | class PersonBuilder;
7 |
8 | class Person
9 | {
10 | // address
11 | string street_address, post_code, city;
12 |
13 | // employment
14 | string company_name, position;
15 | int annual_income = 0;
16 |
17 | Person() {}
18 | public:
19 | static PersonBuilder create();
20 |
21 | Person(Person&& other)
22 | : street_address{move(other.street_address)},
23 | post_code{move(other.post_code)},
24 | city{move(other.city)},
25 | company_name{move(other.company_name)},
26 | position{move(other.position)},
27 | annual_income{other.annual_income}
28 | {
29 | }
30 |
31 | Person& operator=(Person&& other)
32 | {
33 | if (this == &other)
34 | return *this;
35 | street_address = move(other.street_address);
36 | post_code = move(other.post_code);
37 | city = move(other.city);
38 | company_name = move(other.company_name);
39 | position = move(other.position);
40 | annual_income = other.annual_income;
41 | return *this;
42 | }
43 |
44 | friend ostream& operator<<(ostream& os, const Person& obj)
45 | {
46 | return os
47 | << "street_address: "s << obj.street_address
48 | << " post_code: "s << obj.post_code
49 | << " city: "s << obj.city
50 | << " company_name: "s << obj.company_name
51 | << " position: "s << obj.position
52 | << " annual_income: "s << boost::lexical_cast(obj.annual_income);
53 | }
54 |
55 | friend class PersonBuilder;
56 | friend class PersonAddressBuilder;
57 | friend class PersonJobBuilder;
58 | };
59 |
--------------------------------------------------------------------------------
/facet-builders/PersonAddressBuilder.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | class PersonAddressBuilder : public PersonBuilder
5 | {
6 | typedef PersonAddressBuilder Self;
7 | public:
8 | explicit PersonAddressBuilder(Person& person)
9 | : PersonBuilder{ person }
10 | {
11 | }
12 |
13 | Self& at(std::string street_address)
14 | {
15 | person.street_address = street_address;
16 | return *this;
17 | }
18 |
19 | Self& with_postcode(std::string post_code)
20 | {
21 | person.post_code = post_code;
22 | return *this;
23 | }
24 |
25 | Self& in(std::string city)
26 | {
27 | person.city = city;
28 | return *this;
29 | }
30 | };
--------------------------------------------------------------------------------
/facet-builders/PersonBuilder.cpp:
--------------------------------------------------------------------------------
1 | #include "PersonBuilder.h"
2 | #include "PersonAddressBuilder.h"
3 | #include "PersonJobBuilder.h"
4 |
5 | PersonAddressBuilder PersonBuilder::lives()
6 | {
7 | return PersonAddressBuilder{ person };
8 | }
9 |
10 | PersonJobBuilder PersonBuilder::works()
11 | {
12 | return PersonJobBuilder{ person };
13 | }
--------------------------------------------------------------------------------
/facet-builders/PersonBuilder.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Person.h"
3 |
4 | class PersonAddressBuilder;
5 | class PersonJobBuilder;
6 |
7 | class PersonBuilder
8 | {
9 | Person p;
10 | protected:
11 | Person& person;
12 | explicit PersonBuilder(Person& person)
13 | : person{ person }
14 | {
15 | }
16 | public:
17 | PersonBuilder() :
18 | person{p}
19 | {
20 |
21 | }
22 |
23 | operator Person()
24 | {
25 | return std::move(person);
26 | }
27 |
28 | // builder facets
29 |
30 | PersonAddressBuilder lives();
31 | PersonJobBuilder works();
32 | };
33 |
--------------------------------------------------------------------------------
/facet-builders/PersonJobBuilder.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "PersonBuilder.h"
3 |
4 | class PersonJobBuilder : public PersonBuilder
5 | {
6 | typedef PersonJobBuilder Self;
7 | public:
8 | explicit PersonJobBuilder(Person& person)
9 | : PersonBuilder{ person }
10 | {
11 | }
12 |
13 | Self& at(std::string company_name)
14 | {
15 | person.company_name = company_name;
16 | return *this;
17 | }
18 |
19 | Self& as_a(std::string position)
20 | {
21 | person.position = position;
22 | return *this;
23 | }
24 |
25 | Self& earning(int annual_income)
26 | {
27 | person.annual_income = annual_income;
28 | return *this;
29 | }
30 | };
--------------------------------------------------------------------------------
/facet-builders/facet-builders.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | using namespace std;
8 |
9 | #include "Person.h"
10 | #include "PersonBuilder.h"
11 | #include "PersonAddressBuilder.h"
12 | #include "PersonJobBuilder.h"
13 |
14 | int main()
15 | {
16 | Person p = Person::create()
17 | .lives().at("123 London Road").with_postcode("SW1 1GB").in("London")
18 | .works().at("PragmaSoft").as_a("Consultant").earning(10e6);
19 |
20 | cout << p << endl;
21 | getchar();
22 | return 0;
23 | }
--------------------------------------------------------------------------------
/groovy-builder/groovy-builder.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | struct Tag
8 | {
9 | string name;
10 | string text;
11 | vector children;
12 | vector> attributes;
13 |
14 | friend ostream& operator<<(ostream& os, const Tag& tag)
15 | {
16 | os << "<" << tag.name;
17 |
18 | for (const auto& att : tag.attributes)
19 | os << " " << att.first << "=\"" << att.second << "\"";
20 |
21 | if (tag.children.size() == 0 && tag.text.length() == 0)
22 | {
23 | os << "/>" << endl;
24 | }
25 | else
26 | {
27 | os << ">" << endl;
28 |
29 | if (tag.text.length())
30 | os << tag.text << endl;
31 |
32 | for (const auto& child : tag.children)
33 | os << " " << child;
34 |
35 | os << "" << tag.name << ">" << endl;
36 | }
37 |
38 | return os;
39 | }
40 | protected:
41 |
42 | Tag(const string& name, const string& text)
43 | : name{name},
44 | text{text}
45 | {
46 | }
47 |
48 |
49 | Tag(const string& name, const vector& children)
50 | : name{name},
51 | children{children}
52 | {
53 | }
54 | };
55 |
56 | struct P : Tag
57 | {
58 | explicit P(const string& text)
59 | : Tag{"p", text}
60 | {
61 | }
62 |
63 | P(initializer_list children)
64 | : Tag("p", children)
65 | {
66 | }
67 |
68 | };
69 |
70 | struct IMG : Tag
71 | {
72 | explicit IMG(const string& url)
73 | : Tag{"img", ""}
74 | {
75 | attributes.emplace_back(make_pair("src", url));
76 | }
77 | };
78 |
79 |
80 | int main()
81 | {
82 | cout <<
83 |
84 | P {
85 | IMG {"http://pokemon.com/pikachu.png"}
86 | }
87 |
88 | << endl;
89 |
90 | getchar();
91 | return 0;
92 | }
--------------------------------------------------------------------------------
/maybe-monad/maybe-monad.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | using namespace std;
7 |
8 | struct Address {
9 | string* house_name = nullptr;
10 | };
11 |
12 | struct Person {
13 | Address* address = nullptr;
14 | };
15 |
16 | template struct Maybe;
17 | template Maybe maybe(T* context)
18 | {
19 | return Maybe(context);
20 | }
21 |
22 | template
23 | struct Maybe {
24 | T* context;
25 |
26 | Maybe(T *context) : context(context) { }
27 |
28 | template
29 | auto With(TFunc evaluator)
30 | {
31 | return context != nullptr ? maybe(evaluator(context)) : nullptr;
32 | };
33 |
34 | template
35 | auto Do(TFunc action)
36 | {
37 | if (context != nullptr) action(context);
38 | return *this;
39 | }
40 | };
41 |
42 |
43 |
44 | void print_house_name(Person* p)
45 | {
46 | // if (p != nullptr && p->address != nullptr && p->address->house_name != nullptr)
47 | // cout << *p->address->house_name << endl;
48 | auto z = maybe(p)
49 | .With([](auto x) { return x->address; })
50 | .With([](auto x) { return x->house_name; })
51 | .Do([](auto x) { cout << *x << endl; });
52 | }
53 |
54 |
55 |
56 | int main()
57 | {
58 | print_house_name(nullptr);
59 |
60 | Person p;
61 |
62 | print_house_name(&p); // nothing
63 |
64 | p.address = new Address;
65 | p.address->house_name = new string("My Big Castle");
66 | print_house_name(&p);
67 |
68 | delete p.address->house_name;
69 | delete p.address;
70 |
71 | getchar();
72 | return 0;
73 | }
--------------------------------------------------------------------------------
/specification/specification.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | using namespace std;
6 |
7 | enum class Color { Red, Green, Blue };
8 | enum class Size {Small, Medium, Large };
9 |
10 | struct Product
11 | {
12 | string name;
13 | Color color;
14 | Size size;
15 | };
16 |
17 | struct ProductFilter
18 | {
19 | typedef vector Items;
20 | static Items by_color(Items items, Color color)
21 | {
22 | Items result;
23 | for (auto& i : items)
24 | if (i->color == color)
25 | result.push_back(i);
26 | return result;
27 | }
28 |
29 | static Items by_size(Items items, Size size)
30 | {
31 | Items result;
32 | for (auto& i : items)
33 | if (i->size == size)
34 | result.push_back(i);
35 | return result;
36 | }
37 |
38 | // size and color
39 | static Items by_color_and_size(Items items, Size size, Color color)
40 | {
41 | Items result;
42 | for (auto& i : items)
43 | if (i->size == size && i->color == color)
44 | result.push_back(i);
45 | return result;
46 | }
47 |
48 | // violated OCP b/c we had to jump in and change the underlying object
49 | // stable objects are easier to maintain
50 | };
51 |
52 | template struct ISpecification
53 | {
54 | virtual bool is_satisfied(T* item) = 0;
55 | };
56 |
57 | template struct IFilter
58 | {
59 | virtual vector filter(vector items, ISpecification& spec) = 0;
60 | };
61 |
62 | struct BetterFilter : IFilter
63 | {
64 | vector filter(vector items, ISpecification& spec) override
65 | {
66 | vector result;
67 | for (auto& p : items)
68 | if (spec.is_satisfied(p))
69 | result.push_back(p);
70 | return result;
71 | }
72 | };
73 |
74 | struct ColorSpecification : ISpecification
75 | {
76 | Color color;
77 |
78 | explicit ColorSpecification(const Color color)
79 | : color{color}
80 | {
81 | }
82 |
83 |
84 | bool is_satisfied(Product* item) override {
85 | return item->color == color;
86 | }
87 | };
88 |
89 | struct SizeSpecification : ISpecification
90 | {
91 | Size size;
92 |
93 | explicit SizeSpecification(const Size size)
94 | : size{ size }
95 | {
96 | }
97 |
98 | bool is_satisfied(Product* item) override {
99 | return item->size == size;
100 | }
101 | };
102 |
103 | template struct AndSpecification : ISpecification
104 | {
105 | ISpecification& first;
106 | ISpecification& second;
107 |
108 | AndSpecification(ISpecification& first, ISpecification& second)
109 | : first{first},
110 | second{second}
111 | {
112 | }
113 |
114 | bool is_satisfied(T* item) override
115 | {
116 | return first.is_satisfied(item) && second.is_satisfied(item);
117 | }
118 | };
119 |
120 | int main()
121 | {
122 | Product apple{ "Apple", Color::Green, Size::Small };
123 | Product tree{ "Tree", Color::Green, Size::Large };
124 | Product house{ "House", Color::Blue, Size::Large };
125 |
126 | vector all{ &apple, &tree, &house };
127 |
128 | BetterFilter bf;
129 | ColorSpecification green(Color::Green);
130 |
131 | auto green_things = bf.filter(all, green);
132 | for (auto& x : green_things)
133 | cout << x->name << " is green" << endl;
134 |
135 | SizeSpecification big(Size::Large);
136 | AndSpecification green_and_big{ big, green };
137 |
138 | auto big_green_things = bf.filter(all, green_and_big);
139 | for (auto& x : big_green_things)
140 | cout << x->name << " is big and green" << endl;
141 |
142 | getchar();
143 | return 0;
144 | }
--------------------------------------------------------------------------------