├── .gitignore ├── .idea ├── DesignPatternsWebinar.iml ├── encodings.xml ├── misc.xml └── modules.xml ├── CMakeLists.txt ├── adapter └── adapter.cpp ├── builder └── builder.cpp ├── composite └── composite.cpp ├── facet-builders ├── CMakeLists.txt ├── Person.cpp ├── Person.h ├── PersonAddressBuilder.h ├── PersonBuilder.cpp ├── PersonBuilder.h ├── PersonJobBuilder.h └── facet-builders.cpp ├── groovy-builder └── groovy-builder.cpp ├── maybe-monad └── maybe-monad.cpp └── specification └── specification.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/intellij,c++ 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff: 9 | .idea/workspace.xml 10 | .idea/tasks.xml 11 | .idea/dictionaries 12 | .idea/vcs.xml 13 | .idea/jsLibraryMappings.xml 14 | 15 | # Sensitive or high-churn files: 16 | .idea/dataSources.ids 17 | .idea/dataSources.xml 18 | .idea/dataSources.local.xml 19 | .idea/sqlDataSources.xml 20 | .idea/dynamic.xml 21 | .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | .idea/gradle.xml 25 | .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.iws 32 | 33 | ## Plugin-specific files: 34 | 35 | # IntelliJ 36 | /out/ 37 | 38 | # mpeltonen/sbt-idea plugin 39 | .idea_modules/ 40 | 41 | # JIRA plugin 42 | atlassian-ide-plugin.xml 43 | 44 | # Crashlytics plugin (for Android Studio and IntelliJ) 45 | com_crashlytics_export_strings.xml 46 | crashlytics.properties 47 | crashlytics-build.properties 48 | fabric.properties 49 | 50 | ### Intellij Patch ### 51 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 52 | 53 | # *.iml 54 | # modules.xml 55 | 56 | 57 | ### C++ ### 58 | # Compiled Object files 59 | *.slo 60 | *.lo 61 | *.o 62 | *.obj 63 | 64 | # Precompiled Headers 65 | *.gch 66 | *.pch 67 | 68 | # Compiled Dynamic libraries 69 | *.so 70 | *.dylib 71 | *.dll 72 | 73 | # Fortran module files 74 | *.mod 75 | 76 | # Compiled Static libraries 77 | *.lai 78 | *.la 79 | *.a 80 | *.lib 81 | 82 | # Executables 83 | *.exe 84 | *.out 85 | *.app 86 | -------------------------------------------------------------------------------- /.idea/DesignPatternsWebinar.iml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(DesignPatternsWebinar) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") 5 | 6 | # made with the 'incboost' macro 7 | find_package(Boost) 8 | if (Boost_FOUND) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | endif () 11 | 12 | set(ADAPTER_FILES adapter/adapter.cpp) 13 | add_executable(Adapter ${ADAPTER_FILES}) 14 | 15 | set(COMPOSITE_FILES composite/composite.cpp) 16 | add_executable(Composite ${COMPOSITE_FILES}) 17 | 18 | set(SPECIFICATION_FILES specification/specification.cpp) 19 | add_executable(Specifiction ${SPECIFICATION_FILES}) 20 | 21 | set(BUILDER_FILES builder/builder.cpp) 22 | add_executable(Builder ${BUILDER_FILES}) 23 | 24 | set(GROOVY_BUILDER_FILES groovy-builder/groovy-builder.cpp) 25 | add_executable(GroovyBuilder ${GROOVY_BUILDER_FILES}) 26 | 27 | add_subdirectory(facet-builders) 28 | 29 | set(MAYBE_MONAD_FILES maybe-monad/maybe-monad.cpp) 30 | add_executable(MaybeMonad ${MAYBE_MONAD_FILES}) -------------------------------------------------------------------------------- /adapter/adapter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | 9 | class String { 10 | std::string s; 11 | public: 12 | 13 | String(const string &s) : s(s) { } 14 | 15 | String to_lower_copy() const { 16 | return {boost::to_lower_copy(s)}; 17 | } 18 | 19 | vector split(const string& delimeter = " ") const { 20 | vector parts; 21 | boost::split(parts, s, boost::is_any_of(delimeter), 22 | boost::token_compress_on); 23 | return vector(parts.begin(), parts.end()); 24 | } 25 | 26 | size_t get_length() const { return s.length(); } 27 | }; 28 | 29 | int main() 30 | { 31 | // goal: take a string "Hello World", 32 | // make lowercase, split into words and measure their length 33 | 34 | string s{"Hello World"}; 35 | 36 | // Standard library is not enough, we need to use Boost: 37 | 38 | string sl = boost::to_lower_copy(s); 39 | vector parts; 40 | boost::split(parts, sl, boost::is_any_of(" "), boost::token_compress_on); 41 | 42 | for (auto& p : parts) 43 | cout << p.length() << "\n"; // length or size? 44 | 45 | // same with an adapter 46 | String s2{"Hello World"}; 47 | for (auto& q : s2.to_lower_copy().split()) 48 | cout << q.get_length() << "\n"; 49 | 50 | getchar(); 51 | return 0; 52 | } -------------------------------------------------------------------------------- /builder/builder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct HtmlBuilder; 10 | 11 | struct HtmlElement 12 | { 13 | string name; 14 | string text; 15 | vector elements; 16 | const size_t indent_size = 2; 17 | 18 | HtmlElement() {} 19 | HtmlElement(const string& name, const string& text) 20 | : name(name), 21 | text(text) 22 | { 23 | } 24 | 25 | string str(int indent = 0) const 26 | { 27 | ostringstream oss; 28 | string i(indent_size*indent, ' '); 29 | oss << i << "<" << name << ">" << endl; 30 | if (text.size() > 0) 31 | oss << string(indent_size*(indent + 1), ' ') << text << endl; 32 | 33 | for (const auto& e : elements) 34 | oss << e.str(indent + 1); 35 | 36 | oss << i << "" << endl; 37 | return oss.str(); 38 | } 39 | 40 | static unique_ptr build(string root_name) 41 | { 42 | return make_unique(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 | //
  • hello
  • world
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 << "" << 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 | } --------------------------------------------------------------------------------