From 3afd5d5b1a1274660db5755a7532dc438007cc32 Mon Sep 17 00:00:00 2001 From: gwens Date: Tue, 17 Apr 2018 13:46:42 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 2 + Behavioral/Behavioral.sln | 138 + .../ChainOfResponsibility.vcxproj | 153 + .../ChainOfResponsibility.vcxproj.filters | 7 + .../ChainOfResponsibility.vcxproj.user | 4 + .../CoRCodingExercise.cpp | 135 + .../ChainOfResponsibility/cor_broker.cpp | 116 + .../ChainOfResponsibility/cor_pointer.cpp | 126 + Behavioral/Command/Command.vcxproj | 152 + Behavioral/Command/Command.vcxproj.filters | 7 + Behavioral/Command/Command.vcxproj.user | 4 + Behavioral/Command/CommandCodingExercise.cpp | 72 + Behavioral/Command/command.cpp | 124 + Behavioral/Command/command_composite.cpp | 171 + Behavioral/Command/command_undo.cpp | 104 + Behavioral/Interpreter/Interpreter.vcxproj | 152 + .../Interpreter/Interpreter.vcxproj.filters | 6 + .../Interpreter/Interpreter.vcxproj.user | 4 + .../Interpreter/InterpreterCodingExercise.cpp | 115 + Behavioral/Interpreter/handmade.cpp | 172 + Behavioral/Iterator/Iterator.vcxproj | 166 + Behavioral/Iterator/Iterator.vcxproj.filters | 13 + Behavioral/Iterator/Iterator.vcxproj.user | 4 + .../Iterator/IteratorCodingExercise.cpp | 71 + Behavioral/Iterator/facade.cpp | 68 + Behavioral/Iterator/iterator.cpp | 239 ++ Behavioral/Iterator/packages.config | 4 + Behavioral/Iterator/recursive_generator.h | 157 + Behavioral/Mediator/Mediator.vcxproj | 167 + Behavioral/Mediator/Mediator.vcxproj.filters | 36 + Behavioral/Mediator/Mediator.vcxproj.user | 4 + .../Mediator/MediatorCodingExercise.cpp | 68 + Behavioral/Mediator/chat.cpp | 28 + Behavioral/Mediator/chatroom.cpp | 28 + Behavioral/Mediator/chatroom.h | 10 + Behavioral/Mediator/packages.config | 4 + Behavioral/Mediator/person.cpp | 23 + Behavioral/Mediator/person.h | 32 + Behavioral/Mediator/soccer.cpp | 92 + Behavioral/Memento/Memento.vcxproj | 150 + Behavioral/Memento/Memento.vcxproj.filters | 6 + Behavioral/Memento/Memento.vcxproj.user | 4 + Behavioral/Memento/MementoCodingExercise.cpp | 103 + Behavioral/Memento/memento.cpp | 149 + Behavioral/NullObject/NullObject.vcxproj | 150 + .../NullObject/NullObject.vcxproj.filters | 6 + Behavioral/NullObject/NullObject.vcxproj.user | 4 + Behavioral/NullObject/null_object.cpp | 46 + Behavioral/Observer/Observer.vcxproj | 156 + Behavioral/Observer/Observer.vcxproj.filters | 10 + Behavioral/Observer/Observer.vcxproj.user | 4 + .../Observer/ObserverCodingExercise.cpp | 116 + Behavioral/Observer/new/Observable.cpp | 2 + Behavioral/Observer/new/Observable.hpp | 32 + Behavioral/Observer/new/Observer.cpp | 1 + Behavioral/Observer/new/Observer.hpp | 12 + Behavioral/Observer/new/SaferObservable.cpp | 1 + Behavioral/Observer/new/SaferObservable.hpp | 46 + Behavioral/Observer/new/headers.hpp | 34 + Behavioral/Observer/new/main.cpp | 151 + Behavioral/Observer/observer1.cpp | 103 + Behavioral/Observer/observer2.cpp | 132 + Behavioral/Observer/observer3.cpp | 53 + Behavioral/Observer/observer_book.cpp | 157 + Behavioral/Observer/observer_notes.cpp | 195 ++ Behavioral/State/State.vcxproj | 125 + Behavioral/State/State.vcxproj.filters | 11 + Behavioral/State/State.vcxproj.user | 4 + Behavioral/State/StateCodingExercise.cpp | 87 + Behavioral/State/classic.cpp | 76 + Behavioral/State/handmade.cpp | 137 + Behavioral/State/msm.cpp | 121 + Behavioral/Strategy/Strategy.vcxproj | 151 + Behavioral/Strategy/Strategy.vcxproj.filters | 7 + Behavioral/Strategy/Strategy.vcxproj.user | 4 + .../Strategy/StrategyCodingExercise.cpp | 102 + Behavioral/Strategy/strategy_dynamic.cpp | 99 + Behavioral/Strategy/strategy_static.cpp | 91 + .../TemplateMethod/TemplateMethod.vcxproj | 150 + .../TemplateMethod.vcxproj.filters | 6 + .../TemplateMethod.vcxproj.user | 4 + .../TemplateMethodCodingExercise.cpp | 108 + Behavioral/TemplateMethod/template_method.cpp | 70 + Behavioral/Visitor/Visitor.vcxproj | 163 + Behavioral/Visitor/Visitor.vcxproj.filters | 17 + Behavioral/Visitor/Visitor.vcxproj.user | 4 + Behavioral/Visitor/VisitorCodingExercise.cpp | 127 + Behavioral/Visitor/model.hpp | 121 + Behavioral/Visitor/multimethods.cpp | 83 + Behavioral/Visitor/single_double.cpp | 136 + Behavioral/Visitor/std_visit.cpp | 38 + Behavioral/Visitor/visitor.cpp | 150 + Behavioral/Visitor/visitor.hpp | 24 + Behavioral/Visitor/visitor_acyclic.cpp | 113 + Behavioral/Visitor/visitor_double.cpp | 152 + Behavioral/Visitor/visitor_intrusive.cpp | 59 + Behavioral/Visitor/visitor_reflective.cpp | 82 + Contributing.md | 14 + CppDesignPatterns.sln | 330 ++ Creational/Creational.sln | 28 + Creational/Creational.tss | 11 + Creational/Creational/AbstractFactory.cpp | 33 + Creational/Creational/BoostDI.cpp | 77 + Creational/Creational/BoostDIDemo.hpp | 41 + Creational/Creational/Builder.cpp | 105 + .../Creational/BuilderCodingExercise.cpp | 130 + Creational/Creational/CoffeeFactory.h | 14 + .../CompositeBuilderClassDiagram.mdj | 2927 ++++++++++++++++ Creational/Creational/Creational.vcxproj | 193 + .../Creational/Creational.vcxproj.filters | 140 + Creational/Creational/Creational.vcxproj.user | 4 + Creational/Creational/DIP.cpp | 88 + Creational/Creational/DrinkFactory.h | 49 + Creational/Creational/Facets.cpp | 22 + Creational/Creational/Factory.cpp | 43 + .../Creational/FactoryCodingExercise.cpp | 55 + Creational/Creational/FactoryExercise.h | 7 + Creational/Creational/FactoryMethod.cpp | 64 + Creational/Creational/GroovyStyle.cpp | 93 + Creational/Creational/HotDrink.h | 29 + Creational/Creational/HotDrinkFactory.h | 7 + Creational/Creational/ISP.cpp | 64 + Creational/Creational/InnerFactory.cpp | 61 + Creational/Creational/LSP.cpp | 59 + Creational/Creational/MaybeMonad.cpp | 71 + Creational/Creational/Monostate.cpp | 16 + Creational/Creational/OCP.cpp | 159 + Creational/Creational/Person.cpp | 7 + Creational/Creational/Person.h | 66 + Creational/Creational/PersonAddressBuilder.h | 30 + Creational/Creational/PersonBuilder.cpp | 13 + Creational/Creational/PersonBuilder.h | 35 + Creational/Creational/PersonJobBuilder.h | 30 + Creational/Creational/Prototype.cpp | 217 ++ .../Creational/PrototypeCodingExercise.cpp | 69 + Creational/Creational/SRP.cpp | 58 + Creational/Creational/Serialization.cpp | 89 + Creational/Creational/Singleton.h | 109 + .../Creational/SingletonCodingExercise.cpp | 43 + Creational/Creational/SingletonTests.cpp | 32 + Creational/Creational/TeaFactory.h | 9 + Creational/Creational/UnknownExercise.txt | 196 ++ Creational/Creational/capitals.txt | 20 + Creational/Creational/di.h | 3103 +++++++++++++++++ LICENSE.txt | 27 + README.md | 15 + Structural/Adapter/.vs/Adapter/v14/.suo | Bin 0 -> 26112 bytes Structural/Adapter/Adapter.vcxproj | 159 + Structural/Adapter/Adapter.vcxproj.filters | 9 + Structural/Adapter/Adapter.vcxproj.user | 4 + Structural/Adapter/AdapterCodingExercise.cpp | 71 + Structural/Adapter/adapter.cpp | 71 + Structural/AdapterVisual/AdapterVisual.aps | Bin 0 -> 109052 bytes Structural/AdapterVisual/AdapterVisual.cpp | 90 + Structural/AdapterVisual/AdapterVisual.h | 32 + Structural/AdapterVisual/AdapterVisual.rc | Bin 0 -> 11308 bytes .../AdapterVisual/AdapterVisual.vcxproj | 214 ++ .../AdapterVisual.vcxproj.filters | 63 + .../AdapterVisual/AdapterVisual.vcxproj.user | 4 + Structural/AdapterVisual/AdapterVisualDlg.cpp | 266 ++ Structural/AdapterVisual/AdapterVisualDlg.h | 41 + Structural/AdapterVisual/Geometry.h | 57 + Structural/AdapterVisual/Resource.h | 21 + .../AdapterVisual/res/AdapterVisual.ico | Bin 0 -> 67777 bytes .../AdapterVisual/res/AdapterVisual.rc2 | Bin 0 -> 810 bytes Structural/AdapterVisual/stdafx.cpp | 8 + Structural/AdapterVisual/stdafx.h | 55 + Structural/AdapterVisual/targetver.h | 8 + Structural/Bridge/Bridge.vcxproj | 159 + Structural/Bridge/Bridge.vcxproj.filters | 20 + Structural/Bridge/Bridge.vcxproj.user | 4 + Structural/Bridge/BridgeCodingExercise.cpp | 81 + Structural/Bridge/Person.cpp | 28 + Structural/Bridge/Person.h | 19 + Structural/Bridge/bridge.cpp | 84 + Structural/Composite/ArrayBackedProps.cpp | 95 + Structural/Composite/Composite.vcxproj | 156 + .../Composite/Composite.vcxproj.filters | 11 + Structural/Composite/Composite.vcxproj.user | 4 + .../Composite/CompositeCodingExercise.cpp | 75 + Structural/Composite/composite.cpp | 87 + Structural/Composite/graphics.h | 51 + Structural/Composite/neurons.cpp | 106 + Structural/Decorator/Decorator.vcxproj | 150 + .../Decorator/Decorator.vcxproj.filters | 6 + Structural/Decorator/Decorator.vcxproj.user | 4 + .../Decorator/DecoratorCodingExercise.cpp | 114 + Structural/Decorator/decorator.cpp | 304 ++ "Structural/Fa\303\247ade/Bloom.cpp" | 42 + "Structural/Fa\303\247ade/Console.h" | 51 + .../Fa\303\247ade/Fa\303\247ade.vcxproj" | 150 + .../Fa\303\247ade.vcxproj.filters" | 6 + .../Fa\303\247ade/Fa\303\247ade.vcxproj.user" | 4 + Structural/Flyweight/.vscode/.browse.VC.db | Bin 0 -> 79872 bytes Structural/Flyweight/Flyweight.vcxproj | 151 + .../Flyweight/Flyweight.vcxproj.filters | 7 + Structural/Flyweight/Flyweight.vcxproj.user | 4 + .../Flyweight/FlyweightCodingExercise.cpp | 88 + Structural/Flyweight/capitalize.cpp | 95 + Structural/Flyweight/flyweight.cpp | 114 + Structural/NullObject/.vscode/.browse.VC.db | Bin 0 -> 78848 bytes Structural/NullObject/NullObject.vcxproj | 150 + .../NullObject/NullObject.vcxproj.filters | 6 + Structural/NullObject/NullObject.vcxproj.user | 4 + Structural/NullObject/nullobject.cpp | 115 + .../Controllers/PingPongController.cs | 44 + .../PingPongService/PingPongService.csproj | 33 + .../PingPongService/Project_Readme.html | 188 + .../Properties/launchSettings.json | 26 + Structural/PingPongService/Startup.cs | 62 + Structural/PingPongService/appsettings.json | 10 + Structural/PingPongService/wwwroot/web.config | 9 + Structural/Proxy/.vscode/.browse.VC.db | Bin 0 -> 74752 bytes Structural/Proxy/Proxy.vcxproj | 168 + Structural/Proxy/Proxy.vcxproj.filters | 9 + Structural/Proxy/Proxy.vcxproj.user | 4 + Structural/Proxy/ProxyCodingExercise.cpp | 90 + Structural/Proxy/packages.config | 5 + Structural/Proxy/proxy.cpp | 204 ++ Structural/Structural.sln | 133 + 220 files changed, 21228 insertions(+) create mode 100644 .gitattributes create mode 100644 Behavioral/Behavioral.sln create mode 100644 Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj create mode 100644 Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.filters create mode 100644 Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.user create mode 100644 Behavioral/ChainOfResponsibility/CoRCodingExercise.cpp create mode 100644 Behavioral/ChainOfResponsibility/cor_broker.cpp create mode 100644 Behavioral/ChainOfResponsibility/cor_pointer.cpp create mode 100644 Behavioral/Command/Command.vcxproj create mode 100644 Behavioral/Command/Command.vcxproj.filters create mode 100644 Behavioral/Command/Command.vcxproj.user create mode 100644 Behavioral/Command/CommandCodingExercise.cpp create mode 100644 Behavioral/Command/command.cpp create mode 100644 Behavioral/Command/command_composite.cpp create mode 100644 Behavioral/Command/command_undo.cpp create mode 100644 Behavioral/Interpreter/Interpreter.vcxproj create mode 100644 Behavioral/Interpreter/Interpreter.vcxproj.filters create mode 100644 Behavioral/Interpreter/Interpreter.vcxproj.user create mode 100644 Behavioral/Interpreter/InterpreterCodingExercise.cpp create mode 100644 Behavioral/Interpreter/handmade.cpp create mode 100644 Behavioral/Iterator/Iterator.vcxproj create mode 100644 Behavioral/Iterator/Iterator.vcxproj.filters create mode 100644 Behavioral/Iterator/Iterator.vcxproj.user create mode 100644 Behavioral/Iterator/IteratorCodingExercise.cpp create mode 100644 Behavioral/Iterator/facade.cpp create mode 100644 Behavioral/Iterator/iterator.cpp create mode 100644 Behavioral/Iterator/packages.config create mode 100644 Behavioral/Iterator/recursive_generator.h create mode 100644 Behavioral/Mediator/Mediator.vcxproj create mode 100644 Behavioral/Mediator/Mediator.vcxproj.filters create mode 100644 Behavioral/Mediator/Mediator.vcxproj.user create mode 100644 Behavioral/Mediator/MediatorCodingExercise.cpp create mode 100644 Behavioral/Mediator/chat.cpp create mode 100644 Behavioral/Mediator/chatroom.cpp create mode 100644 Behavioral/Mediator/chatroom.h create mode 100644 Behavioral/Mediator/packages.config create mode 100644 Behavioral/Mediator/person.cpp create mode 100644 Behavioral/Mediator/person.h create mode 100644 Behavioral/Mediator/soccer.cpp create mode 100644 Behavioral/Memento/Memento.vcxproj create mode 100644 Behavioral/Memento/Memento.vcxproj.filters create mode 100644 Behavioral/Memento/Memento.vcxproj.user create mode 100644 Behavioral/Memento/MementoCodingExercise.cpp create mode 100644 Behavioral/Memento/memento.cpp create mode 100644 Behavioral/NullObject/NullObject.vcxproj create mode 100644 Behavioral/NullObject/NullObject.vcxproj.filters create mode 100644 Behavioral/NullObject/NullObject.vcxproj.user create mode 100644 Behavioral/NullObject/null_object.cpp create mode 100644 Behavioral/Observer/Observer.vcxproj create mode 100644 Behavioral/Observer/Observer.vcxproj.filters create mode 100644 Behavioral/Observer/Observer.vcxproj.user create mode 100644 Behavioral/Observer/ObserverCodingExercise.cpp create mode 100644 Behavioral/Observer/new/Observable.cpp create mode 100644 Behavioral/Observer/new/Observable.hpp create mode 100644 Behavioral/Observer/new/Observer.cpp create mode 100644 Behavioral/Observer/new/Observer.hpp create mode 100644 Behavioral/Observer/new/SaferObservable.cpp create mode 100644 Behavioral/Observer/new/SaferObservable.hpp create mode 100644 Behavioral/Observer/new/headers.hpp create mode 100644 Behavioral/Observer/new/main.cpp create mode 100644 Behavioral/Observer/observer1.cpp create mode 100644 Behavioral/Observer/observer2.cpp create mode 100644 Behavioral/Observer/observer3.cpp create mode 100644 Behavioral/Observer/observer_book.cpp create mode 100644 Behavioral/Observer/observer_notes.cpp create mode 100644 Behavioral/State/State.vcxproj create mode 100644 Behavioral/State/State.vcxproj.filters create mode 100644 Behavioral/State/State.vcxproj.user create mode 100644 Behavioral/State/StateCodingExercise.cpp create mode 100644 Behavioral/State/classic.cpp create mode 100644 Behavioral/State/handmade.cpp create mode 100644 Behavioral/State/msm.cpp create mode 100644 Behavioral/Strategy/Strategy.vcxproj create mode 100644 Behavioral/Strategy/Strategy.vcxproj.filters create mode 100644 Behavioral/Strategy/Strategy.vcxproj.user create mode 100644 Behavioral/Strategy/StrategyCodingExercise.cpp create mode 100644 Behavioral/Strategy/strategy_dynamic.cpp create mode 100644 Behavioral/Strategy/strategy_static.cpp create mode 100644 Behavioral/TemplateMethod/TemplateMethod.vcxproj create mode 100644 Behavioral/TemplateMethod/TemplateMethod.vcxproj.filters create mode 100644 Behavioral/TemplateMethod/TemplateMethod.vcxproj.user create mode 100644 Behavioral/TemplateMethod/TemplateMethodCodingExercise.cpp create mode 100644 Behavioral/TemplateMethod/template_method.cpp create mode 100644 Behavioral/Visitor/Visitor.vcxproj create mode 100644 Behavioral/Visitor/Visitor.vcxproj.filters create mode 100644 Behavioral/Visitor/Visitor.vcxproj.user create mode 100644 Behavioral/Visitor/VisitorCodingExercise.cpp create mode 100644 Behavioral/Visitor/model.hpp create mode 100644 Behavioral/Visitor/multimethods.cpp create mode 100644 Behavioral/Visitor/single_double.cpp create mode 100644 Behavioral/Visitor/std_visit.cpp create mode 100644 Behavioral/Visitor/visitor.cpp create mode 100644 Behavioral/Visitor/visitor.hpp create mode 100644 Behavioral/Visitor/visitor_acyclic.cpp create mode 100644 Behavioral/Visitor/visitor_double.cpp create mode 100644 Behavioral/Visitor/visitor_intrusive.cpp create mode 100644 Behavioral/Visitor/visitor_reflective.cpp create mode 100644 Contributing.md create mode 100644 CppDesignPatterns.sln create mode 100644 Creational/Creational.sln create mode 100644 Creational/Creational.tss create mode 100644 Creational/Creational/AbstractFactory.cpp create mode 100644 Creational/Creational/BoostDI.cpp create mode 100644 Creational/Creational/BoostDIDemo.hpp create mode 100644 Creational/Creational/Builder.cpp create mode 100644 Creational/Creational/BuilderCodingExercise.cpp create mode 100644 Creational/Creational/CoffeeFactory.h create mode 100644 Creational/Creational/CompositeBuilderClassDiagram.mdj create mode 100644 Creational/Creational/Creational.vcxproj create mode 100644 Creational/Creational/Creational.vcxproj.filters create mode 100644 Creational/Creational/Creational.vcxproj.user create mode 100644 Creational/Creational/DIP.cpp create mode 100644 Creational/Creational/DrinkFactory.h create mode 100644 Creational/Creational/Facets.cpp create mode 100644 Creational/Creational/Factory.cpp create mode 100644 Creational/Creational/FactoryCodingExercise.cpp create mode 100644 Creational/Creational/FactoryExercise.h create mode 100644 Creational/Creational/FactoryMethod.cpp create mode 100644 Creational/Creational/GroovyStyle.cpp create mode 100644 Creational/Creational/HotDrink.h create mode 100644 Creational/Creational/HotDrinkFactory.h create mode 100644 Creational/Creational/ISP.cpp create mode 100644 Creational/Creational/InnerFactory.cpp create mode 100644 Creational/Creational/LSP.cpp create mode 100644 Creational/Creational/MaybeMonad.cpp create mode 100644 Creational/Creational/Monostate.cpp create mode 100644 Creational/Creational/OCP.cpp create mode 100644 Creational/Creational/Person.cpp create mode 100644 Creational/Creational/Person.h create mode 100644 Creational/Creational/PersonAddressBuilder.h create mode 100644 Creational/Creational/PersonBuilder.cpp create mode 100644 Creational/Creational/PersonBuilder.h create mode 100644 Creational/Creational/PersonJobBuilder.h create mode 100644 Creational/Creational/Prototype.cpp create mode 100644 Creational/Creational/PrototypeCodingExercise.cpp create mode 100644 Creational/Creational/SRP.cpp create mode 100644 Creational/Creational/Serialization.cpp create mode 100644 Creational/Creational/Singleton.h create mode 100644 Creational/Creational/SingletonCodingExercise.cpp create mode 100644 Creational/Creational/SingletonTests.cpp create mode 100644 Creational/Creational/TeaFactory.h create mode 100644 Creational/Creational/UnknownExercise.txt create mode 100644 Creational/Creational/capitals.txt create mode 100644 Creational/Creational/di.h create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 Structural/Adapter/.vs/Adapter/v14/.suo create mode 100644 Structural/Adapter/Adapter.vcxproj create mode 100644 Structural/Adapter/Adapter.vcxproj.filters create mode 100644 Structural/Adapter/Adapter.vcxproj.user create mode 100644 Structural/Adapter/AdapterCodingExercise.cpp create mode 100644 Structural/Adapter/adapter.cpp create mode 100644 Structural/AdapterVisual/AdapterVisual.aps create mode 100644 Structural/AdapterVisual/AdapterVisual.cpp create mode 100644 Structural/AdapterVisual/AdapterVisual.h create mode 100644 Structural/AdapterVisual/AdapterVisual.rc create mode 100644 Structural/AdapterVisual/AdapterVisual.vcxproj create mode 100644 Structural/AdapterVisual/AdapterVisual.vcxproj.filters create mode 100644 Structural/AdapterVisual/AdapterVisual.vcxproj.user create mode 100644 Structural/AdapterVisual/AdapterVisualDlg.cpp create mode 100644 Structural/AdapterVisual/AdapterVisualDlg.h create mode 100644 Structural/AdapterVisual/Geometry.h create mode 100644 Structural/AdapterVisual/Resource.h create mode 100644 Structural/AdapterVisual/res/AdapterVisual.ico create mode 100644 Structural/AdapterVisual/res/AdapterVisual.rc2 create mode 100644 Structural/AdapterVisual/stdafx.cpp create mode 100644 Structural/AdapterVisual/stdafx.h create mode 100644 Structural/AdapterVisual/targetver.h create mode 100644 Structural/Bridge/Bridge.vcxproj create mode 100644 Structural/Bridge/Bridge.vcxproj.filters create mode 100644 Structural/Bridge/Bridge.vcxproj.user create mode 100644 Structural/Bridge/BridgeCodingExercise.cpp create mode 100644 Structural/Bridge/Person.cpp create mode 100644 Structural/Bridge/Person.h create mode 100644 Structural/Bridge/bridge.cpp create mode 100644 Structural/Composite/ArrayBackedProps.cpp create mode 100644 Structural/Composite/Composite.vcxproj create mode 100644 Structural/Composite/Composite.vcxproj.filters create mode 100644 Structural/Composite/Composite.vcxproj.user create mode 100644 Structural/Composite/CompositeCodingExercise.cpp create mode 100644 Structural/Composite/composite.cpp create mode 100644 Structural/Composite/graphics.h create mode 100644 Structural/Composite/neurons.cpp create mode 100644 Structural/Decorator/Decorator.vcxproj create mode 100644 Structural/Decorator/Decorator.vcxproj.filters create mode 100644 Structural/Decorator/Decorator.vcxproj.user create mode 100644 Structural/Decorator/DecoratorCodingExercise.cpp create mode 100644 Structural/Decorator/decorator.cpp create mode 100644 "Structural/Fa\303\247ade/Bloom.cpp" create mode 100644 "Structural/Fa\303\247ade/Console.h" create mode 100644 "Structural/Fa\303\247ade/Fa\303\247ade.vcxproj" create mode 100644 "Structural/Fa\303\247ade/Fa\303\247ade.vcxproj.filters" create mode 100644 "Structural/Fa\303\247ade/Fa\303\247ade.vcxproj.user" create mode 100644 Structural/Flyweight/.vscode/.browse.VC.db create mode 100644 Structural/Flyweight/Flyweight.vcxproj create mode 100644 Structural/Flyweight/Flyweight.vcxproj.filters create mode 100644 Structural/Flyweight/Flyweight.vcxproj.user create mode 100644 Structural/Flyweight/FlyweightCodingExercise.cpp create mode 100644 Structural/Flyweight/capitalize.cpp create mode 100644 Structural/Flyweight/flyweight.cpp create mode 100644 Structural/NullObject/.vscode/.browse.VC.db create mode 100644 Structural/NullObject/NullObject.vcxproj create mode 100644 Structural/NullObject/NullObject.vcxproj.filters create mode 100644 Structural/NullObject/NullObject.vcxproj.user create mode 100644 Structural/NullObject/nullobject.cpp create mode 100644 Structural/PingPongService/Controllers/PingPongController.cs create mode 100644 Structural/PingPongService/PingPongService.csproj create mode 100644 Structural/PingPongService/Project_Readme.html create mode 100644 Structural/PingPongService/Properties/launchSettings.json create mode 100644 Structural/PingPongService/Startup.cs create mode 100644 Structural/PingPongService/appsettings.json create mode 100644 Structural/PingPongService/wwwroot/web.config create mode 100644 Structural/Proxy/.vscode/.browse.VC.db create mode 100644 Structural/Proxy/Proxy.vcxproj create mode 100644 Structural/Proxy/Proxy.vcxproj.filters create mode 100644 Structural/Proxy/Proxy.vcxproj.user create mode 100644 Structural/Proxy/ProxyCodingExercise.cpp create mode 100644 Structural/Proxy/packages.config create mode 100644 Structural/Proxy/proxy.cpp create mode 100644 Structural/Structural.sln diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/Behavioral/Behavioral.sln b/Behavioral/Behavioral.sln new file mode 100644 index 0000000..33852c4 --- /dev/null +++ b/Behavioral/Behavioral.sln @@ -0,0 +1,138 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Iterator", "Iterator\Iterator.vcxproj", "{ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChainOfResponsibility", "ChainOfResponsibility\ChainOfResponsibility.vcxproj", "{35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Memento", "Memento\Memento.vcxproj", "{0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Observer", "Observer\Observer.vcxproj", "{014C7C95-2A69-460B-8A91-AE0F67D65342}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Command", "Command\Command.vcxproj", "{C5DCA564-9139-4274-BC7E-41A0311721B0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Interpreter", "Interpreter\Interpreter.vcxproj", "{1FB6D834-DFE3-404A-9619-AA0085611897}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Strategy", "Strategy\Strategy.vcxproj", "{76DDB609-2C93-41A2-BDED-5E0F2F81652B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mediator", "Mediator\Mediator.vcxproj", "{2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NullObject", "NullObject\NullObject.vcxproj", "{D5F1806D-FE8A-4754-B8A0-334FF29272DA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Visitor", "Visitor\Visitor.vcxproj", "{AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TemplateMethod", "TemplateMethod\TemplateMethod.vcxproj", "{522A86A0-1065-4568-9329-9214081C7993}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "State", "State\State.vcxproj", "{84B29C64-523E-4C27-9FC6-017C0AC23FEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x64.ActiveCfg = Debug|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x64.Build.0 = Debug|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x86.ActiveCfg = Debug|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x86.Build.0 = Debug|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x64.ActiveCfg = Release|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x64.Build.0 = Release|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x86.ActiveCfg = Release|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x86.Build.0 = Release|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x64.ActiveCfg = Debug|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x64.Build.0 = Debug|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x86.ActiveCfg = Debug|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x86.Build.0 = Debug|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x64.ActiveCfg = Release|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x64.Build.0 = Release|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x86.ActiveCfg = Release|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x86.Build.0 = Release|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x64.ActiveCfg = Debug|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x64.Build.0 = Debug|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x86.ActiveCfg = Debug|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x86.Build.0 = Debug|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x64.ActiveCfg = Release|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x64.Build.0 = Release|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x86.ActiveCfg = Release|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x86.Build.0 = Release|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x64.ActiveCfg = Debug|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x64.Build.0 = Debug|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x86.ActiveCfg = Debug|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x86.Build.0 = Debug|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x64.ActiveCfg = Release|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x64.Build.0 = Release|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x86.ActiveCfg = Release|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x86.Build.0 = Release|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x64.ActiveCfg = Debug|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x64.Build.0 = Debug|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x86.ActiveCfg = Debug|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x86.Build.0 = Debug|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x64.ActiveCfg = Release|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x64.Build.0 = Release|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x86.ActiveCfg = Release|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x86.Build.0 = Release|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x64.ActiveCfg = Debug|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x64.Build.0 = Debug|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x86.ActiveCfg = Debug|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x86.Build.0 = Debug|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x64.ActiveCfg = Release|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x64.Build.0 = Release|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x86.ActiveCfg = Release|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x86.Build.0 = Release|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x64.ActiveCfg = Debug|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x64.Build.0 = Debug|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x86.ActiveCfg = Debug|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x86.Build.0 = Debug|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x64.ActiveCfg = Release|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x64.Build.0 = Release|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x86.ActiveCfg = Release|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x86.Build.0 = Release|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x64.ActiveCfg = Debug|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x64.Build.0 = Debug|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x86.ActiveCfg = Debug|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x86.Build.0 = Debug|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x64.ActiveCfg = Release|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x64.Build.0 = Release|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x86.ActiveCfg = Release|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x86.Build.0 = Release|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x64.ActiveCfg = Debug|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x64.Build.0 = Debug|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x86.ActiveCfg = Debug|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x86.Build.0 = Debug|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x64.ActiveCfg = Release|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x64.Build.0 = Release|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x86.ActiveCfg = Release|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x86.Build.0 = Release|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x64.ActiveCfg = Debug|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x64.Build.0 = Debug|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x86.ActiveCfg = Debug|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x86.Build.0 = Debug|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x64.ActiveCfg = Release|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x64.Build.0 = Release|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x86.ActiveCfg = Release|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x86.Build.0 = Release|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x64.ActiveCfg = Debug|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x64.Build.0 = Debug|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x86.ActiveCfg = Debug|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x86.Build.0 = Debug|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x64.ActiveCfg = Release|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x64.Build.0 = Release|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x86.ActiveCfg = Release|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x86.Build.0 = Release|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x64.ActiveCfg = Debug|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x64.Build.0 = Debug|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x86.ActiveCfg = Debug|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x86.Build.0 = Debug|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x64.ActiveCfg = Release|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x64.Build.0 = Release|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x86.ActiveCfg = Release|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj b/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj new file mode 100644 index 0000000..45599e9 --- /dev/null +++ b/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9} + Win32Proj + ChainOfResponsibility + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.filters b/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.filters new file mode 100644 index 0000000..f11bec5 --- /dev/null +++ b/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.filters @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.user b/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/ChainOfResponsibility/ChainOfResponsibility.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/ChainOfResponsibility/CoRCodingExercise.cpp b/Behavioral/ChainOfResponsibility/CoRCodingExercise.cpp new file mode 100644 index 0000000..c4b982e --- /dev/null +++ b/Behavioral/ChainOfResponsibility/CoRCodingExercise.cpp @@ -0,0 +1,135 @@ +#include +#include +using namespace std; + +struct Creature; +struct Game +{ + vector creatures; +}; + +struct StatQuery +{ + enum Statistic { attack, defense } statistic; + int result; +}; + +struct Creature +{ +protected: + Game& game; + int base_attack, base_defense; + +public: + Creature(Game &game, int base_attack, int base_defense) : game(game), base_attack(base_attack), + base_defense(base_defense) {} + + virtual int get_attack() = 0; + virtual int get_defense() = 0; + virtual void query(void* source, StatQuery& sq) = 0; +}; + +class Goblin : public Creature +{ + int get_statistic(StatQuery::Statistic stat) + { + StatQuery q{stat,0}; + for (auto c : game.creatures) + c->query(this, q); + return q.result; + } +public: + Goblin(Game &game, int base_attack, int base_defense) : Creature(game, base_attack, base_defense) {} + + Goblin(Game &game) : Creature(game, 1, 1) {} + + int get_attack() override { + return get_statistic(StatQuery::attack); + } + + int get_defense() override { + return get_statistic(StatQuery::defense); + } + + void query(void *source, StatQuery &sq) override { + if (source == this) + { + switch (sq.statistic) + { + case StatQuery::attack: + sq.result += base_attack; + break; + case StatQuery::defense: + sq.result += base_defense; + break; + } + } else + { + if (sq.statistic == StatQuery::defense) + { + sq.result++; + } + } + } +}; + +class GoblinKing : public Goblin +{ +public: + GoblinKing(Game &game) : Goblin(game, 3, 3) {} + + void query(void *source, StatQuery &sq) override { + if (source != this && sq.statistic == StatQuery::attack) + { + sq.result++; + } + else Goblin::query(source, sq); + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace +{ + class Evaluate : public testing::Test + { + public: + }; + + TEST_F(Evaluate, ManyGoblinsTest) + { + Game game; + Goblin goblin{game}; + game.creatures.push_back(&goblin); + + cout << "Checking that a baseline goblin is a 1/1...\n"; + + ASSERT_EQ(1, goblin.get_attack()); + ASSERT_EQ(1, goblin.get_defense()); + + cout << "Adding a second goblin, now they should be 1/2...\n"; + Goblin goblin2{game}; + game.creatures.push_back(&goblin2); + + ASSERT_EQ(1, goblin.get_attack()); + ASSERT_EQ(2, goblin.get_defense()); + + cout << "Adding a goblin king, now a goblin should be 2/3...\n"; + GoblinKing goblin3{game}; + game.creatures.push_back(&goblin3); + + ASSERT_EQ(2, goblin.get_attack()); + ASSERT_EQ(3, goblin.get_defense()); + } + +} // namespace + +int main(int ac, char* av[]) +{ + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/ChainOfResponsibility/cor_broker.cpp b/Behavioral/ChainOfResponsibility/cor_broker.cpp new file mode 100644 index 0000000..abf4ae8 --- /dev/null +++ b/Behavioral/ChainOfResponsibility/cor_broker.cpp @@ -0,0 +1,116 @@ +#include +#include +using namespace std; +#include +using namespace boost::signals2; + + +struct Query +{ + string creature_name; + enum Argument { attack, defense } argument; + int result; + + + Query(const string& creature_name, const Argument argument, const int result) + : creature_name(creature_name), + argument(argument), + result(result) + { + } +}; + +struct Game // mediator +{ + signal queries; +}; + +class Creature +{ + Game& game; + int attack, defense; +public: + string name; + Creature(Game& game, const string& name, const int attack, const int defense) + : game(game), + attack(attack), + defense(defense), + name(name) + { + } + + // no need for this to be virtual + int GetAttack() const + { + Query q{ name, Query::Argument::attack, attack }; + game.queries(q); + return q.result; + } + + friend ostream& operator<<(ostream& os, const Creature& obj) + { + return os + << "name: " << obj.name + << " attack: " << obj.GetAttack() // note here + << " defense: " << obj.defense; + } +}; + +class CreatureModifier +{ + Game& game; + Creature& creature; +public: + virtual ~CreatureModifier() = default; + + // there is no handle() function + + CreatureModifier(Game& game, Creature& creature) + : game(game), + creature(creature) + { + } +}; + +class DoubleAttackModifier : public CreatureModifier +{ + connection conn; +public: + DoubleAttackModifier(Game& game, Creature& creature) + : CreatureModifier(game, creature) + { + // whenever someone wants this creature's attack, + // we return DOUBLE the value + conn = game.queries.connect([&](Query& q) + { + if (q.creature_name == creature.name && + q.argument == Query::Argument::attack) + q.result *= 2; + }); + } + + ~DoubleAttackModifier() + { + conn.disconnect(); + } +}; + +// similar idea, but Query instead of Command +int main(int ac, char* av) +{ + Game game; + Creature goblin{ game, "Strong Goblin", 2, 2 }; + + cout << goblin << endl; + + { + DoubleAttackModifier dam{ game, goblin }; + + cout << goblin << endl; + } + + cout << goblin << endl; + + getchar(); + return 0; +} diff --git a/Behavioral/ChainOfResponsibility/cor_pointer.cpp b/Behavioral/ChainOfResponsibility/cor_pointer.cpp new file mode 100644 index 0000000..535d0de --- /dev/null +++ b/Behavioral/ChainOfResponsibility/cor_pointer.cpp @@ -0,0 +1,126 @@ +#include +#include +using namespace std; + +struct Creature +{ + string name; + int attack, defense; + + Creature(const string& name, const int attack, const int defense) + : name(name), + attack(attack), + defense(defense) + { + } + + + friend ostream& operator<<(ostream& os, const Creature& obj) + { + return os + << "name: " << obj.name + << " attack: " << obj.attack + << " defense: " << obj.defense; + } +}; + +class CreatureModifier +{ + CreatureModifier* next{ nullptr }; // unique_ptr +protected: + Creature& creature; // pointer or shared_ptr +public: + explicit CreatureModifier(Creature& creature) + : creature(creature) + { + } + virtual ~CreatureModifier() = default; + + void add(CreatureModifier* cm) + { + if (next) next->add(cm); + else next = cm; + } + + // two approaches: + + // 1. Always call base handle(). There could be additional logic here. + // 2. Only call base handle() when you cannot handle things yourself. + + virtual void handle() + { + if (next) next->handle(); + } +}; + +// 1. Double the creature's attack +// 2. Increase defense by 1 unless power > 2 +// 3. No bonuses can be applied to this creature + +class NoBonusesModifier : public CreatureModifier +{ +public: + explicit NoBonusesModifier(Creature& creature) + : CreatureModifier(creature) + { + } + + void handle() override + { + // nothing + } +}; + +class DoubleAttackModifier : public CreatureModifier +{ +public: + explicit DoubleAttackModifier(Creature& creature) + : CreatureModifier(creature) + { + } + + void handle() override + { + creature.attack *= 2; + CreatureModifier::handle(); + } +}; + +class IncreaseDefenseModifier : public CreatureModifier +{ +public: + explicit IncreaseDefenseModifier(Creature& creature) + : CreatureModifier(creature) + { + } + + + void handle() override + { + if (creature.attack <= 2) + creature.defense += 1; + CreatureModifier::handle(); + } +}; + +int main_() +{ + Creature goblin{ "Goblin", 1, 1 }; + CreatureModifier root{ goblin }; + DoubleAttackModifier r1{ goblin }; + DoubleAttackModifier r1_2{ goblin }; + IncreaseDefenseModifier r2{ goblin }; + //NoBonusesModifier nb{ goblin }; // effectively Command objects + + //root.add(&nb); + root.add(&r1); + root.add(&r1_2); + root.add(&r2); + + root.handle(); // annoying + + cout << goblin << endl; + + //getchar(); + return 0; +} diff --git a/Behavioral/Command/Command.vcxproj b/Behavioral/Command/Command.vcxproj new file mode 100644 index 0000000..ef1fa4f --- /dev/null +++ b/Behavioral/Command/Command.vcxproj @@ -0,0 +1,152 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {C5DCA564-9139-4274-BC7E-41A0311721B0} + Win32Proj + Command + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost\ + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Command/Command.vcxproj.filters b/Behavioral/Command/Command.vcxproj.filters new file mode 100644 index 0000000..e4c4214 --- /dev/null +++ b/Behavioral/Command/Command.vcxproj.filters @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Behavioral/Command/Command.vcxproj.user b/Behavioral/Command/Command.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Command/Command.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Command/CommandCodingExercise.cpp b/Behavioral/Command/CommandCodingExercise.cpp new file mode 100644 index 0000000..1f3c2b1 --- /dev/null +++ b/Behavioral/Command/CommandCodingExercise.cpp @@ -0,0 +1,72 @@ +#include +#include +using namespace std; + +struct Command +{ + enum Action { deposit, withdraw } action; + int amount{0}; + bool success{false}; +}; + +struct Account +{ + int balance{0}; + + void process(Command& cmd) + { + switch (cmd.action) + { + case Command::deposit: + balance += cmd.amount; + cmd.success = true; + break; + case Command::withdraw: + cmd.success = (balance >= cmd.amount); + if (cmd.success) balance -= cmd.amount; + break; + } + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace +{ + class Evaluate : public testing::Test + { + public: + }; + + TEST_F(Evaluate, LotsOfAccountTests) + { + Account a; + Command command{Command::deposit, 100}; + a.process(command); + + ASSERT_EQ(100, a.balance); + ASSERT_TRUE(command.success); + + command = Command{Command::withdraw, 50}; + a.process(command); + + ASSERT_EQ(50, a.balance); + ASSERT_TRUE(command.success); + + command = Command{Command::withdraw, 150}; + a.process(command); + + ASSERT_EQ(50, a.balance); + ASSERT_FALSE(command.success); + } +} // namespace + +int main(int ac, char* av[]) +{ + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/Command/command.cpp b/Behavioral/Command/command.cpp new file mode 100644 index 0000000..5b17377 --- /dev/null +++ b/Behavioral/Command/command.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +using namespace std; + +struct BankAccount +{ + int balance = 0; + int overdraft_limit = -500; + + void deposit(int amount) + { + balance += amount; + cout << "deposited " << amount << ", balance now " << + balance << "\n"; + } + + void withdraw(int amount) + { + if (balance - amount >= overdraft_limit) + { + balance -= amount; + cout << "withdrew " << amount << ", balance now " << + balance << "\n"; + } + } +}; + +struct Command +{ + virtual ~Command() = default; + virtual void call() const = 0; + virtual void undo() const = 0; +}; + +// should really be BankAccountCommand +struct BankAccountCommand : Command +{ + BankAccount& account; + enum Action { deposit, withdraw } action; + int amount; + + BankAccountCommand(BankAccount& account, + const Action action, const int amount) + : account(account), action(action), amount(amount) {} + + void call() const override + { + switch (action) + { + case deposit: + account.deposit(amount); + break; + case withdraw: + account.withdraw(amount); + break; + default: break; + } + } + + void undo() const override + { + switch (action) + { + case withdraw: + account.deposit(amount); + break; + case deposit: + account.withdraw(amount); + break; + default: break; + } + } +}; + +// vector doesn't have virtual dtor, but who cares? +struct CompositeBankAccountCommand + : vector, Command +{ + CompositeBankAccountCommand(const initializer_list& items) + : vector(items) {} + + void call() const override + { + for (auto& cmd : *this) + cmd.call(); + } + + void undo() const override + { + for (auto& cmd : *this) + cmd.undo(); + } +}; + +int main_987() +{ + BankAccount ba; + /*vector commands{*/ + CompositeBankAccountCommand commands { + BankAccountCommand{ba, BankAccountCommand::deposit, 100}, + BankAccountCommand{ba, BankAccountCommand::withdraw, 200} + }; + + cout << ba.balance << endl; + + // apply all the commands + /*for (auto& cmd : commands) + { + cmd.call(); + }*/ + commands.call(); + + cout << ba.balance << endl; + + /*for_each(commands.rbegin(), commands.rend(), + [](const BankAccountCommand& cmd) { cmd.undo(); });*/ + commands.undo(); + + cout << ba.balance << endl; + + getchar(); + return 0; +} diff --git a/Behavioral/Command/command_composite.cpp b/Behavioral/Command/command_composite.cpp new file mode 100644 index 0000000..625be02 --- /dev/null +++ b/Behavioral/Command/command_composite.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +using namespace std; + +struct BankAccount +{ + int balance = 0; + int overdraft_limit = -500; + + void deposit(int amount) + { + balance += amount; + cout << "deposited " << amount << ", balance now " << + balance << "\n"; + } + + bool withdraw(int amount) + { + if (balance - amount >= overdraft_limit) + { + balance -= amount; + cout << "withdrew " << amount << ", balance now " << + balance << "\n"; + return true; + } + return false; + } +}; + +struct Command +{ + bool succeeded; + virtual void call() = 0; + virtual void undo() = 0; +}; + +// should really be BankAccountCommand +struct BankAccountCommand : Command +{ + BankAccount& account; + enum Action { deposit, withdraw } action; + int amount; + + BankAccountCommand(BankAccount& account, const Action action, + const int amount) + : account(account), + action(action), amount(amount) + { + succeeded = false; + } + + void call() override + { + switch (action) + { + case deposit: + account.deposit(amount); + succeeded = true; + break; + case withdraw: + succeeded = account.withdraw(amount); + break; + } + } + + void undo() override + { + if (!succeeded) return; + + switch (action) + { + case withdraw: + if (succeeded) + account.deposit(amount); + break; + case deposit: + account.withdraw(amount); + break; + } + } +}; + +// vector doesn't have virtual dtor, but who cares? +struct CompositeBankAccountCommand : vector, Command +{ + CompositeBankAccountCommand(const initializer_list& _Ilist) + : vector(_Ilist) + { + } + + void call() override + { + for (auto& cmd : *this) + cmd.call(); + } + + void undo() override + { + for (auto it = rbegin(); it != rend(); ++it) + it->undo(); + } +}; + +struct DependentCompositeCommand : CompositeBankAccountCommand +{ + explicit DependentCompositeCommand( + const initializer_list& _Ilist) + : CompositeBankAccountCommand{ _Ilist } {} + + void call() override + { + bool ok = true; + for (auto& cmd : *this) + { + if (ok) + { + cmd.call(); + ok = cmd.succeeded; + } + else + { + cmd.succeeded = false; + } + } + } +}; + +struct MoneyTransferCommand : DependentCompositeCommand +{ + MoneyTransferCommand(BankAccount& from, + BankAccount& to, int amount): + DependentCompositeCommand + { + BankAccountCommand{from, BankAccountCommand::withdraw, amount}, + BankAccountCommand{to, BankAccountCommand::deposit, amount} + } {} +}; + + +int main() +{ + BankAccount ba; + /*vector commands{*/ + CompositeBankAccountCommand commands{ + BankAccountCommand{ ba, BankAccountCommand::deposit, 100 }, + BankAccountCommand{ ba, BankAccountCommand::withdraw, 200 } + }; + + cout << ba.balance << endl; + + // apply all the commands + /*for (auto& cmd : commands) + { + cmd.call(); + }*/ + commands.call(); + + cout << ba.balance << endl; + + /*for_each(commands.rbegin(), commands.rend(), + [](const BankAccountCommand& cmd) { cmd.undo(); });*/ + commands.undo(); + + cout << ba.balance << endl; + + getchar(); + return 0; +} diff --git a/Behavioral/Command/command_undo.cpp b/Behavioral/Command/command_undo.cpp new file mode 100644 index 0000000..c9cdeb9 --- /dev/null +++ b/Behavioral/Command/command_undo.cpp @@ -0,0 +1,104 @@ +#include "headers.hpp" + +struct BankAccount +{ + int balance{0}; + int overdraft_limit{-500}; + + void deposit(int amount) + { + balance += amount; + cout << "deposited " << amount + << ", balance is now " << balance << endl; + } + + bool withdraw(int amount) + { + if (balance - amount >= overdraft_limit) + { + balance -= amount; + cout << "withdrew " << amount + << ", balance is now " << balance << endl; + return true; + } + return false; + } + + friend ostream &operator<<(ostream &os, const BankAccount &account) { + os << "balance: " << account.balance; + return os; + } +}; + +struct Command +{ + bool succeeded; + virtual void call() = 0; + virtual void undo() = 0; +}; + +struct BankAccountCommand : Command +{ + BankAccount& account; + enum Action { deposit, withdraw } action; + int amount; + + BankAccountCommand(BankAccount &account, Action action, int amount) : account(account), action(action), + amount(amount) { + succeeded = false; + } + + void call() override { + switch (action) + { + case deposit: + account.deposit(amount); + succeeded = true; + break; + case withdraw: + succeeded = account.withdraw(amount); + break; + } + } + + void undo() override { + if (!succeeded) return; + + switch (action) + { + case deposit: + account.withdraw(amount); + break; + case withdraw: + account.deposit(amount); + break; + } + } + + +}; + +int main() +{ + BankAccount ba; + + vector commands + { + BankAccountCommand{ba, BankAccountCommand::deposit, 100}, + BankAccountCommand{ba, BankAccountCommand::withdraw, 200} + }; + + cout << ba << endl; + + for (auto& cmd : commands) + cmd.call(); + + for (auto it = commands.rbegin(); it != commands.rend(); ++it) + { + it->undo(); + } + + cout << ba << endl; + + return 0; +} \ No newline at end of file diff --git a/Behavioral/Interpreter/Interpreter.vcxproj b/Behavioral/Interpreter/Interpreter.vcxproj new file mode 100644 index 0000000..2c71287 --- /dev/null +++ b/Behavioral/Interpreter/Interpreter.vcxproj @@ -0,0 +1,152 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {1FB6D834-DFE3-404A-9619-AA0085611897} + Win32Proj + Interpreter + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Interpreter/Interpreter.vcxproj.filters b/Behavioral/Interpreter/Interpreter.vcxproj.filters new file mode 100644 index 0000000..d95abf8 --- /dev/null +++ b/Behavioral/Interpreter/Interpreter.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Behavioral/Interpreter/Interpreter.vcxproj.user b/Behavioral/Interpreter/Interpreter.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Interpreter/Interpreter.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Interpreter/InterpreterCodingExercise.cpp b/Behavioral/Interpreter/InterpreterCodingExercise.cpp new file mode 100644 index 0000000..f6a2801 --- /dev/null +++ b/Behavioral/Interpreter/InterpreterCodingExercise.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +using namespace std; + + +inline vector split(const string& stringToSplit) +{ + vector result; + size_t pos = 0, lastPos = 0; + while ((pos = stringToSplit.find_first_of("+-", lastPos)) != string::npos) + { + result.push_back(stringToSplit.substr(lastPos, pos-lastPos+1)); + lastPos = pos+1; + } + result.push_back(stringToSplit.substr(lastPos)); + return result; +} + +struct ExpressionProcessor +{ + map variables; + + enum NextOp + { + nothing, + plus, + minus + }; + + int calculate(const string& expression) + { + int current; + auto next_op = nothing; + + auto parts = split(expression); + + cout << "parts (" << parts.size() << "): "; + for (auto& part : parts) + cout << "`" << part << "` "; + cout << endl; + + for (auto& part : parts) + { + auto no_op = split(part); + auto first = no_op[0]; + int value, z; + + try + { + value = stoi(first); + } + catch (const invalid_argument&) + { + if (first.length() == 1 && + variables.find(first[0]) != variables.end()) + { + value = variables[first[0]]; + } + else return 0; + } + + switch (next_op) + { + case nothing: + current = value; + break; + case plus: + current += value; + break; + case minus: + current -= value; + break; + } + + if (*part.rbegin() == '+') next_op = plus; + else if (*part.rbegin() == '-') next_op = minus; + } + + return current; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace +{ + class Evaluate : public testing::Test + { + public: + }; + + TEST_F(Evaluate, LotsOfAccountTests) + { + ExpressionProcessor ep; + ep.variables['x'] = 5; + + ASSERT_EQ(1, ep.calculate("1")); + ASSERT_EQ(3, ep.calculate("1+2")); + ASSERT_EQ(6, ep.calculate("1+x")); + ASSERT_EQ(0, ep.calculate("1+xy")); + } +} // namespace + +int main(int ac, char* av[]) +{ + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/Interpreter/handmade.cpp b/Behavioral/Interpreter/handmade.cpp new file mode 100644 index 0000000..4c1d743 --- /dev/null +++ b/Behavioral/Interpreter/handmade.cpp @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +using namespace std; +#include + +// lexing ================================================= + +struct Token +{ + enum Type { integer, plus, minus, lparen, rparen } type; + string text; + + explicit Token(Type type, const string& text) : + type{type}, text{text} {} + + friend ostream& operator<<(ostream& os, const Token& obj) + { + return os << "`" << obj.text << "`"; + } +}; + +vector lex(const string& input) +{ + vector result; + + for (int i = 0; i < input.size(); ++i) + { + switch (input[i]) + { + case '+': + result.push_back(Token{ Token::plus, "+" }); + break; + case '-': + result.push_back(Token{ Token::minus, "-" }); + break; + case '(': + result.push_back(Token{ Token::lparen, "(" }); + break; + case ')': + result.push_back(Token{ Token::rparen, ")" }); + break; + default: + // number + ostringstream buffer; + buffer << input[i]; + for (int j = i + 1; j < input.size(); ++j) + { + if (isdigit(input[j])) + { + buffer << input[j]; + ++i; + } + else + { + result.push_back(Token{ Token::integer, buffer.str() }); + break; + } + } + } + } + + return result; +} + +// parsing ===================================================== + +struct Element +{ + virtual ~Element() = default; + virtual int eval() const = 0; +}; + +struct Integer : Element +{ + int value; + explicit Integer(const int value) + : value(value) + { + } + int eval() const override { return value; } +}; + +struct BinaryOperation : Element +{ + enum Type { addition, subtraction } type; + shared_ptr lhs, rhs; + + int eval() const override + { + if (type == addition) + return lhs->eval() + rhs->eval(); + return lhs->eval() - rhs->eval(); + } +}; + +shared_ptr parse(const vector& tokens) +{ + auto result = make_unique(); + bool have_lhs = false; + for (size_t i = 0; i < tokens.size(); i++) + { + auto token = tokens[i]; + switch(token.type) + { + case Token::integer: + { + int value = boost::lexical_cast(token.text); + auto integer = make_shared(value); + if (!have_lhs) { + result->lhs = integer; + have_lhs = true; + } + else result->rhs = integer; + } + break; + case Token::plus: + result->type = BinaryOperation::addition; + break; + case Token::minus: + result->type = BinaryOperation::subtraction; + break; + case Token::lparen: + { + int j = i; + for (; j < tokens.size(); ++j) + if (tokens[j].type == Token::rparen) + break; // found it! + + vector subexpression(&tokens[i + 1], &tokens[j]); + auto element = parse(subexpression); + if (!have_lhs) + { + result->lhs = element; + have_lhs = true; + } + else result->rhs = element; + i = j; // advance + } + break; + } + } + return result; +} + + + +int main() +{ + string input{ "(13-4)-(12+1)" }; // see if you can make nested braces work + auto tokens = lex(input); + + // let's see the tokens + for (auto& t : tokens) + cout << t << " "; + cout << endl; + + try { + auto parsed = parse(tokens); + cout << input << " = " << parsed->eval() << endl; + } + catch (const exception& e) + { + cout << e.what() << endl; + } + + getchar(); + return 0; +} diff --git a/Behavioral/Iterator/Iterator.vcxproj b/Behavioral/Iterator/Iterator.vcxproj new file mode 100644 index 0000000..4f94085 --- /dev/null +++ b/Behavioral/Iterator/Iterator.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3} + Win32Proj + Iterator + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + /await + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + /await + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/Behavioral/Iterator/Iterator.vcxproj.filters b/Behavioral/Iterator/Iterator.vcxproj.filters new file mode 100644 index 0000000..b1d5319 --- /dev/null +++ b/Behavioral/Iterator/Iterator.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Iterator/Iterator.vcxproj.user b/Behavioral/Iterator/Iterator.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Iterator/Iterator.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Iterator/IteratorCodingExercise.cpp b/Behavioral/Iterator/IteratorCodingExercise.cpp new file mode 100644 index 0000000..9201f3d --- /dev/null +++ b/Behavioral/Iterator/IteratorCodingExercise.cpp @@ -0,0 +1,71 @@ +#include +#include +using namespace std; + +template +struct Node +{ + T value; + Node *left{nullptr}, *right{nullptr}, *parent{nullptr}; + + Node(T value) : value(value) {} + + Node(T value, Node *left, Node *right) : value(value), left(left), right(right) { + left->parent = right->parent = this; + } + + void preorder_traversal_impl(Node* current, vector*>& result) + { + result.push_back(current); + if (current->left) + { + preorder_traversal_impl(current->left, result); + } + if (current->right) + { + preorder_traversal_impl(current->right, result); + } + } + + // traverse the node and its children preorder + // and put all the results into `result` + void preorder_traversal(vector*>& result) + { + preorder_traversal_impl(this, result); + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, ExampleTest) { + Node c{'c'}; + Node d{'d'}; + Node e{'e'}; + Node b{'b', &c, &d}; + Node a{'a', &b, &e}; + + vector*> result; + a.preorder_traversal(result); + + ostringstream oss; + for (auto n : result) + oss << n->value; + ASSERT_EQ("abcde", oss.str()); + } + +} // namespace + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/Iterator/facade.cpp b/Behavioral/Iterator/facade.cpp new file mode 100644 index 0000000..f24e8e3 --- /dev/null +++ b/Behavioral/Iterator/facade.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +using namespace std; + +#include + + +struct Node +{ + string value; + Node* next = nullptr; + + explicit Node(const string& value) + : value(value) + { + } + + + Node(const string& value, Node* const parent) + : value(value) + { + parent->next = this; + } +}; + +struct ListIterator : boost::iterator_facade +{ + Node* current = nullptr; + + + ListIterator() + { + } + + explicit ListIterator(Node* const current) + : current(current) + { + } + +private: + friend class boost::iterator_core_access; + + void increment() { current = current->next; } + + bool equal(const ListIterator& other) const + { return other.current == current; }; + + Node& dereference() const + { return *current; } +}; + +int main_0() +{ + Node alpha{ "alpha" }; + Node beta{ "beta", &alpha}; + Node gamma{ "gamma", &beta }; + + for_each(ListIterator{ &alpha }, ListIterator{}, + [](const Node& n) + { + cout << n.value << endl; + }); + + getchar(); + return 0; +} diff --git a/Behavioral/Iterator/iterator.cpp b/Behavioral/Iterator/iterator.cpp new file mode 100644 index 0000000..a419f55 --- /dev/null +++ b/Behavioral/Iterator/iterator.cpp @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +#include "recursive_generator.h" + +template struct BinaryTree; + +// todo: refactor to refer to parent instead of entire tree +template struct Node +{ + T value = T(); + Node *left = nullptr; + Node *right = nullptr; + Node *parent = nullptr; + BinaryTree* tree = nullptr; + + explicit Node(const T& value) + : value(value) + { + } + + Node(const T& value, Node* const left, Node* const right) + : value(value), + left(left), + right(right) + { + this->left->tree = this->right->tree = tree; + this->left->parent = this->right->parent = this; + } + + void set_tree(BinaryTree* t) + { + tree = t; + if (left) left->set_tree(t); + if (right) right->set_tree(t); + } + + ~Node() + { + if (left) delete left; + if (right) delete right; + } +}; + +template struct BinaryTree +{ + Node* root = nullptr; + + explicit BinaryTree(Node* const root) + : root{ root }, pre_order{ *this } + { + root->set_tree(this); + } + + ~BinaryTree() { if (root) delete root; } + + template + struct PreOrderIterator + { + Node* current; + + explicit PreOrderIterator(Node* current) + : current(current) + { + } + + bool operator!=(const PreOrderIterator& other) + { + return current != other.current; + } + + // no continuations in C++ (unlike C#) + PreOrderIterator& operator++() + { + if (current->right) + { + current = current->right; + while (current->left) + current = current->left; + } + else + { + Node* p = current->parent; + while (p && current == p->right) + { + current = p; + p = p->parent; + } + current = p; + } + return *this; + } + + Node& operator*() { return *current; } + }; + + typedef PreOrderIterator iterator; + + iterator end() + { + return iterator{ nullptr }; + } + + iterator begin() + { + Node* n = root; + + if (n) + while (n->left) + n = n->left; + return iterator{ n }; + } + + // expose as a traversal object + // todo: make this inorder + class pre_order_traversal + { + BinaryTree& tree; + public: + pre_order_traversal(BinaryTree& tree) : tree{tree} {} + iterator begin() { return tree.begin(); } + iterator end() { return tree.end(); } + } pre_order; + + // todo: postorder iterator using recursive coroutines + + experimental::generator*> post_order() + { + return post_order_impl(root); + } + +private: + // or use a recursive_generator + experimental::generator*> post_order_impl(Node* node) + { + if (node) + { + for (auto x : post_order_impl(node->left)) + co_yield x; + for (auto y : post_order_impl(node->right)) + co_yield y; + co_yield node; + } + } +}; + +void std_iterators() +{ + vector names{ "john", "jane", "jill", "jack" }; + + vector::iterator it = names.begin(); // or begin(names) + cout << "first name is " << *it << "\n"; + + ++it; // advance the iterator + it->append(string(" goodall")); + cout << "second name is " << *it << "\n"; + + while (++it != names.end()) + { + cout << "another name: " << *it << "\n"; + } + + // traversing the entire vector backwards + // note global rbegin/rend, note ++ not -- + // expand auto here + for (auto ri = rbegin(names); ri != rend(names); ++ri) + { + cout << *ri; + if (ri + 1 != rend(names)) // iterator arithmetic + cout << ", "; + } + cout << endl; + + // constant iterators + vector::const_reverse_iterator jack = crbegin(names); + // won't work + //*jack += "reacher"; + + for (auto& name : names) + cout << "name = " << name << "\n"; +} + +// in order traversal +void binary_tree_iterator() +{ + // me + // / \ + // mother father + // / \ + // m'm m'f + + BinaryTree family{ + new Node{"me", + new Node{"mother", + new Node{"mother's mother"}, + new Node{"mother's father"} + }, + new Node{"father"} + } + }; + + // pre order traversal + for (auto it = family.begin(); it != family.end(); ++it) + { + cout << (*it).value << "\n"; + } + + cout << "=== and now, through a dedicated object:\n"; + + // use iterator name + for (const auto& it: family.pre_order) + { + cout << it.value << "\n"; + } + + cout << "=== postorder travesal with coroutines:\n"; + + // use coroutines (yields pointers!) + // postorder: m'm, m'f m f me + for (auto it: family.post_order()) + { + cout << it->value << endl; + } +} + + +int main() +{ + //std_iterators(); + binary_tree_iterator(); + + getchar(); + return 0; +} diff --git a/Behavioral/Iterator/packages.config b/Behavioral/Iterator/packages.config new file mode 100644 index 0000000..f8a1db9 --- /dev/null +++ b/Behavioral/Iterator/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Iterator/recursive_generator.h b/Behavioral/Iterator/recursive_generator.h new file mode 100644 index 0000000..b0a9f38 --- /dev/null +++ b/Behavioral/Iterator/recursive_generator.h @@ -0,0 +1,157 @@ +#pragma once + +#include + +// This class implements delegating (potentially recursive) recursive_generator. +// It supports two kind of yield expressions: +// +// co_yield V; +// co_yield G_of_T; +// +// Where V is a value convertible to T and +// G_of_T is a recursive_generator. +// +// Usage example: +// +// #include +// #include "recursive_recursive_generator.h" +// +// recursive_generator range(int start, int end, int step = 1) { +// for (; start < end; start += step) +// co_yield start; +// } +// +// recursive_generator f() { +// co_yield 1; +// co_yield range(10, 15); +// co_yield -1; +// co_yield range(1000, 9999, 1000); +// } +// +// int main() { +// for (auto v : f()) +// printf("%d ", v); +// puts(""); +// } +// +// Output: 1 10 11 12 13 14 -1 1000 2000 3000 4000 5000 6000 7000 8000 9000 + + +template struct recursive_generator { + struct promise_type; + using handle = std::experimental::coroutine_handle; + + struct promise_type { + T const *value; + + promise_type *prev; + promise_type *top_or_root; + + promise_type *top() { return top_or_root; } + promise_type *root() { + if (is_root()) + return this; + return top_or_root; + } + + void set_top(promise_type *p) { top_or_root = p; } + void set_root(promise_type *p) { top_or_root = p; } + + promise_type() : prev(this), top_or_root(this) {} + + bool is_root() { return prev == this; } + + T const &get() { return *value; } + + void resume() { handle::from_promise(*this)(); } + bool done() { return handle::from_promise(*this).done(); } + + recursive_generator get_return_object() { return { *this }; } + + auto initial_suspend() { return std::experimental::suspend_always{}; } + + auto final_suspend() { return std::experimental::suspend_always{}; } + + auto yield_value(T const &v) { + value = &v; + return std::experimental::suspend_always{}; + } + + auto yield_value(recursive_generator &&v) { + auto &inner = v.impl.promise(); + inner.prev = this; + inner.top_or_root = root(); + inner.top_or_root->top_or_root = &v.impl.promise(); + + inner.resume(); + + struct suspend_if { + bool _Ready; + explicit suspend_if(bool _Condition) : _Ready(!_Condition) {} + bool await_ready() { return _Ready; } + void await_suspend(std::experimental::coroutine_handle<>) {} + void await_resume() {} + }; + + return suspend_if(!top()->done()); + } + + void pull() { + if (!top()->done()) { + top()->resume(); + } + while (top()->done()) { + if (top()->is_root()) + return; + + top_or_root = top()->prev; + top()->resume(); + } + } + }; + + ~recursive_generator() { + if (impl) { + impl.destroy(); + } + } + + struct iterator { + handle rh; + + iterator(decltype(nullptr)) {} + iterator(handle rh) : rh(rh) {} + + iterator &operator++() { + rh.promise().pull(); + if (rh.done()) { + rh = nullptr; + } + return *this; + } + + bool operator!=(iterator const &rhs) { return rh != rhs.rh; } + + T const &operator*() { return rh.promise().top()->get(); } + }; + + iterator begin() { + impl.promise().pull(); + if (impl.done()) + return { nullptr }; + return { impl }; + } + + iterator end() { return { nullptr }; } + + recursive_generator(recursive_generator const &) = delete; + recursive_generator &operator=(recursive_generator const &) = delete; + + recursive_generator(recursive_generator &&rhs) : impl(rhs.impl) { rhs.impl = nullptr; } + recursive_generator &operator=(recursive_generator &&rhs) = delete; + +private: + recursive_generator(promise_type &p) : impl(handle::from_promise(p)) {} + + handle impl; +}; \ No newline at end of file diff --git a/Behavioral/Mediator/Mediator.vcxproj b/Behavioral/Mediator/Mediator.vcxproj new file mode 100644 index 0000000..4989fbe --- /dev/null +++ b/Behavioral/Mediator/Mediator.vcxproj @@ -0,0 +1,167 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16} + Win32Proj + Mediator + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/Behavioral/Mediator/Mediator.vcxproj.filters b/Behavioral/Mediator/Mediator.vcxproj.filters new file mode 100644 index 0000000..9e67197 --- /dev/null +++ b/Behavioral/Mediator/Mediator.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + chatroom + + + chatroom + + + chatroom + + + soccer + + + + + {8afe6fe8-628f-4c42-9336-1888d26d7370} + + + {50ca6257-88ca-442c-9c65-99f125b87a06} + + + + + chatroom + + + chatroom + + + + + + \ No newline at end of file diff --git a/Behavioral/Mediator/Mediator.vcxproj.user b/Behavioral/Mediator/Mediator.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Mediator/Mediator.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Mediator/MediatorCodingExercise.cpp b/Behavioral/Mediator/MediatorCodingExercise.cpp new file mode 100644 index 0000000..eafff4d --- /dev/null +++ b/Behavioral/Mediator/MediatorCodingExercise.cpp @@ -0,0 +1,68 @@ +#include +#include +using namespace std; + +struct IParticipant +{ + virtual void notify(IParticipant* sender, int value) = 0; +}; + +struct Mediator +{ + vector participants; + void say(IParticipant* sender, int value) + { + for (auto p : participants) + p->notify(sender, value); + } +}; + +struct Participant : IParticipant +{ + int value{0}; + Mediator& mediator; + + Participant(Mediator &mediator) : mediator(mediator) + { + mediator.participants.push_back(this); + } + + void notify(IParticipant *sender, int value) override { + if (sender != this) + this->value += value; + } + + void say(int value) + { + mediator.say(this, value); + } +}; + +#include "gtest/gtest.h" +#include "helpers/iohelper.h" + +#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, LongMediationTest) { + Mediator m; + Participant p1{m}, p2{m}; + + ASSERT_EQ(0, p1.value); + ASSERT_EQ(0, p2.value); + + p1.say(2); + + ASSERT_EQ(0, p1.value); + ASSERT_EQ(2, p2.value); + + p2.say(4); + + ASSERT_EQ(4, p1.value); + ASSERT_EQ(2, p2.value); + } + +} // namespace diff --git a/Behavioral/Mediator/chat.cpp b/Behavioral/Mediator/chat.cpp new file mode 100644 index 0000000..1029ef3 --- /dev/null +++ b/Behavioral/Mediator/chat.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +using namespace std; + +#include "person.h" +#include "chatroom.h" + +int main__() +{ + ChatRoom room; + + Person john{ "john" }; + Person jane{ "jane" }; + room.join(&john); + room.join(&jane); + john.say("hi room"); + jane.say("oh, hey john"); + + Person simon("simon"); + room.join(&simon); + simon.say("hi everyone!"); + + jane.pm("simon", "glad you could join us, simon"); + + getchar(); + return 0; +} diff --git a/Behavioral/Mediator/chatroom.cpp b/Behavioral/Mediator/chatroom.cpp new file mode 100644 index 0000000..1a13635 --- /dev/null +++ b/Behavioral/Mediator/chatroom.cpp @@ -0,0 +1,28 @@ +#include "person.h" +#include "chatroom.h" +#include + +void ChatRoom::broadcast(const string& origin, const string& message) +{ + for (auto p : people) + if (p->name != origin) + p->receive(origin, message); +} + +void ChatRoom::join(Person* p) +{ + string join_msg = p->name + " joins the chat"; + broadcast("room", join_msg); + + p->room = this; + people.push_back(p); +} + +void ChatRoom::message(const string& origin, const string& who, const string& message) +{ + auto target = find_if(begin(people), end(people), [&](const Person* p) { return p->name == who; }); + if (target != end(people)) + { + (*target)->receive(origin, message); + } +} diff --git a/Behavioral/Mediator/chatroom.h b/Behavioral/Mediator/chatroom.h new file mode 100644 index 0000000..aaf3db6 --- /dev/null +++ b/Behavioral/Mediator/chatroom.h @@ -0,0 +1,10 @@ +#pragma once + +struct ChatRoom +{ + vector people; // assume append-only + + void join(Person* p); + void broadcast(const string& origin, const string& message); + void message(const string& origin, const string& who, const string& message); +}; diff --git a/Behavioral/Mediator/packages.config b/Behavioral/Mediator/packages.config new file mode 100644 index 0000000..046fef1 --- /dev/null +++ b/Behavioral/Mediator/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Mediator/person.cpp b/Behavioral/Mediator/person.cpp new file mode 100644 index 0000000..54565be --- /dev/null +++ b/Behavioral/Mediator/person.cpp @@ -0,0 +1,23 @@ +#include "person.h" +#include "chatroom.h" + +Person::Person(const string& name) : name(name) +{ +} + +void Person::receive(const string& origin, const string& message) +{ + string s{ origin + ": \"" + message + "\"" }; + cout << "[" << name << "'s chat session] " << s << "\n"; + chat_log.emplace_back(s); +} + +void Person::say(const string& message) const +{ + room->broadcast(name, message); +} + +void Person::pm(const string& who, const string& message) const +{ + room->message(name, who, message); +} diff --git a/Behavioral/Mediator/person.h b/Behavioral/Mediator/person.h new file mode 100644 index 0000000..a1e5386 --- /dev/null +++ b/Behavioral/Mediator/person.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +using namespace std; + +struct ChatRoom; + +struct Person +{ + string name; + ChatRoom* room = nullptr; + + Person(const string& name); + void receive(const string& origin, const string& message); + + void say(const string& message) const; + vector chat_log; + + void pm(const string& who, const string& message) const; + + // generated in IDE + friend bool operator==(const Person& lhs, const Person& rhs) + { + return lhs.name == rhs.name; + } + + friend bool operator!=(const Person& lhs, const Person& rhs) + { + return !(lhs == rhs); + } +}; diff --git a/Behavioral/Mediator/soccer.cpp b/Behavioral/Mediator/soccer.cpp new file mode 100644 index 0000000..e23a6a9 --- /dev/null +++ b/Behavioral/Mediator/soccer.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +struct Game; +using namespace std; + +#include +using namespace boost::signals2; + +struct EventData +{ + virtual ~EventData() = default; + virtual void print() const = 0; +}; + +struct Player; +struct PlayerScoredData : EventData +{ + string player_name; + int goals_scored_so_far; + + PlayerScoredData(const string& player_name, const int goals_scored_so_far) + : player_name(player_name), + goals_scored_so_far(goals_scored_so_far) + { + } + + void print() const override + { + cout << player_name << " has scored! (their " + << goals_scored_so_far << " goal)" << "\n"; + } +}; + +struct Game +{ + signal events; // observer +}; + +struct Player +{ + string name; + int goals_scored = 0; + Game& game; + + + Player(const string& name, Game& game) + : name(name), + game(game) + { + } + + void score() + { + goals_scored++; + PlayerScoredData ps{name, goals_scored}; + game.events(&ps); + } +}; + +struct Coach +{ + Game& game; + + explicit Coach(Game& game) + : game(game) + { + // celebrate if player has scored <3 goals + game.events.connect([](EventData* e) + { + PlayerScoredData* ps = dynamic_cast(e); + if (ps && ps->goals_scored_so_far < 3) + { + cout << "coach says: well done, " << ps->player_name << "\n"; + } + }); + } +}; + +int main() +{ + Game game; + Player player{ "Sam", game }; + Coach coach{ game }; + + player.score(); + player.score(); + player.score(); // ignored by coach + + getchar(); + return 0; +} diff --git a/Behavioral/Memento/Memento.vcxproj b/Behavioral/Memento/Memento.vcxproj new file mode 100644 index 0000000..835bf44 --- /dev/null +++ b/Behavioral/Memento/Memento.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA} + Win32Proj + Memento + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Memento/Memento.vcxproj.filters b/Behavioral/Memento/Memento.vcxproj.filters new file mode 100644 index 0000000..232073a --- /dev/null +++ b/Behavioral/Memento/Memento.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Behavioral/Memento/Memento.vcxproj.user b/Behavioral/Memento/Memento.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Memento/Memento.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Memento/MementoCodingExercise.cpp b/Behavioral/Memento/MementoCodingExercise.cpp new file mode 100644 index 0000000..1209566 --- /dev/null +++ b/Behavioral/Memento/MementoCodingExercise.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +using namespace std; + +struct Token +{ + int value; + + Token(int value) : value(value) {} +}; + +struct Memento +{ + vector> tokens; +}; + +struct TokenMachine +{ + vector> tokens; + + Memento add_token(int value) + { + return add_token(make_shared(value)); + } + + Memento add_token(const shared_ptr& token) + { + tokens.push_back(token); + Memento m; + for (auto t : tokens) + m.tokens.emplace_back(make_shared(t->value)); + return m; + } + + void revert(const Memento& m) + { + tokens.clear(); + for (auto t : m.tokens) + tokens.emplace_back(make_shared(t->value)); + } +}; + +#include "gtest/gtest.h" +//#include "helpers/iohelper.h" +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, SingleTokenTest) { + TokenMachine tm; + auto m = tm.add_token(123); + tm.add_token(456); + tm.revert(m); + ASSERT_EQ(1, tm.tokens.size()); + ASSERT_EQ(123, tm.tokens[0]->value); + } + + TEST_F(Evaluate, TwoTokenTest) + { + TokenMachine tm; + tm.add_token(1); + auto m = tm.add_token(2); + tm.add_token(3); + tm.revert(m); + ASSERT_EQ(2, tm.tokens.size()); + ASSERT_EQ(1, tm.tokens[0]->value) + << "First toke should have value 1, you got " + << tm.tokens[0]->value; + ASSERT_EQ(2, tm.tokens[1]->value); + } + + TEST_F(Evaluate, FiddledTokenTest) + { + TokenMachine tm; + cout << "Made a token with value=111 and kept a reference\n"; + auto token = make_shared(111); + cout << "Added this token to the list\n"; + tm.add_token(token); + auto m = tm.add_token(222); + cout << "Changed this token's value to 333 :)\n"; + token->value = 333; + tm.revert(m); + + ASSERT_EQ(2, tm.tokens.size()) + << "At this point, token machine should have exactly " + << "two tokens, you got " << tm.tokens.size(); + + ASSERT_EQ(111, tm.tokens[0]->value) + << "You got the token value wrong here. " + << "Hint: did you init the memento by-value?"; + } + +} // namespace + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} diff --git a/Behavioral/Memento/memento.cpp b/Behavioral/Memento/memento.cpp new file mode 100644 index 0000000..f8a9862 --- /dev/null +++ b/Behavioral/Memento/memento.cpp @@ -0,0 +1,149 @@ +#include +#include +#include +#include +using namespace std; + +class Memento +{ + int balance; +public: + Memento(int balance) + : balance(balance) + { + } + friend class BankAccount; + friend class BankAccount2; +}; + +class BankAccount +{ + int balance = 0; +public: + explicit BankAccount(const int balance) + : balance(balance) + { + } + + Memento deposit(int amount) + { + balance += amount; + return { balance }; + } + + void restore(const Memento& m) + { + balance = m.balance; + } + + friend ostream& operator<<(ostream& os, const BankAccount& obj) + { + return os << "balance: " << obj.balance; + } +}; + +// undo/redo =================================== + +class BankAccount2 +{ + int balance = 0; + vector> changes; + int current; +public: + explicit BankAccount2(const int balance) + : balance(balance) + { + changes.emplace_back(make_shared(balance)); + current = 0; + } + + shared_ptr deposit(int amount) + { + balance += amount; + auto m = make_shared(balance); + changes.push_back(m); + ++current; + return m; + } + + void restore(const shared_ptr& m) + { + if (m) + { + balance = m->balance; + changes.push_back(m); + current = changes.size() - 1; + } + } + + shared_ptr undo() + { + if (current > 0) + { + --current; + auto m = changes[current]; + balance = m->balance; + return m; + } + return{}; + } + + shared_ptr redo() + { + if (current + 1 < changes.size()) + { + ++current; + auto m = changes[current]; + balance = m->balance; + return m; + } + return{}; + } + + friend ostream& operator<<(ostream& os, const BankAccount2& obj) + { + return os << "balance: " << obj.balance; + } +}; + +void memento() +{ + BankAccount ba{ 100 }; + auto m1 = ba.deposit(50); // 150 + auto m2 = ba.deposit(25); // 175 + cout << ba << "\n"; + + // undo to m1 + ba.restore(m1); + cout << ba << "\n"; + + // redo + ba.restore(m2); + cout << ba << "\n"; +} + +void undo_redo() +{ + BankAccount2 ba{ 100 }; + ba.deposit(50); + ba.deposit(25); // 125 + cout << ba << "\n"; + + ba.undo(); + cout << "Undo 1: " << ba << "\n"; + ba.undo(); + cout << "Undo 2: " << ba << "\n"; + ba.redo(); + cout << "Redo 2: " << ba << "\n"; + + ba.undo(); +} + +int main() +{ + // memento() + undo_redo(); + + getchar(); + return 0; +} diff --git a/Behavioral/NullObject/NullObject.vcxproj b/Behavioral/NullObject/NullObject.vcxproj new file mode 100644 index 0000000..e6dd90e --- /dev/null +++ b/Behavioral/NullObject/NullObject.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D5F1806D-FE8A-4754-B8A0-334FF29272DA} + Win32Proj + NullObject + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/NullObject/NullObject.vcxproj.filters b/Behavioral/NullObject/NullObject.vcxproj.filters new file mode 100644 index 0000000..172ec33 --- /dev/null +++ b/Behavioral/NullObject/NullObject.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Behavioral/NullObject/NullObject.vcxproj.user b/Behavioral/NullObject/NullObject.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/NullObject/NullObject.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/NullObject/null_object.cpp b/Behavioral/NullObject/null_object.cpp new file mode 100644 index 0000000..78f05c2 --- /dev/null +++ b/Behavioral/NullObject/null_object.cpp @@ -0,0 +1,46 @@ +#include +#include +using namespace std; + +struct Log +{ + virtual void LogInfo(const string& message) const = 0; +}; + +struct ConsoleLog : Log +{ + void LogInfo(const string& message) const override + { + cout << message << endl; + } +}; + +template +struct PaymentProcessing +{ + static_assert(is_base_of::value, "LogType must be a Log"); + + LogType log; + + // alternatively, ctor + + void Process() + { + log.LogMessage("Processing payments..."); + } +}; + +int main() +{ + struct NullLog : Log + { + void LogInfo(const string& message) const override + { + } + }; + + PaymentProcessing pp; + + getchar(); + return 0; +} diff --git a/Behavioral/Observer/Observer.vcxproj b/Behavioral/Observer/Observer.vcxproj new file mode 100644 index 0000000..e612d3a --- /dev/null +++ b/Behavioral/Observer/Observer.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {014C7C95-2A69-460B-8A91-AE0F67D65342} + Win32Proj + Observer + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Observer/Observer.vcxproj.filters b/Behavioral/Observer/Observer.vcxproj.filters new file mode 100644 index 0000000..b7aebfd --- /dev/null +++ b/Behavioral/Observer/Observer.vcxproj.filters @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Observer/Observer.vcxproj.user b/Behavioral/Observer/Observer.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Observer/Observer.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Observer/ObserverCodingExercise.cpp b/Behavioral/Observer/ObserverCodingExercise.cpp new file mode 100644 index 0000000..c7b65d7 --- /dev/null +++ b/Behavioral/Observer/ObserverCodingExercise.cpp @@ -0,0 +1,116 @@ +#include +#include +using namespace std; + +struct IRat +{ + virtual void rat_enters(IRat* sender) = 0; + virtual void rat_dies(IRat* sender) = 0; + virtual void notify(IRat* target) = 0; +}; + +struct Game +{ + vector rats; + virtual void fire_rat_enters(IRat* sender) + { + for (auto rat : rats) rat->rat_enters(sender); + } + virtual void fire_rat_dies(IRat* sender) + { + for (auto rat : rats) rat->rat_dies(sender); + } + virtual void fire_notify(IRat* target) + { + for (auto rat : rats) rat->notify(target); + } +}; + +struct Rat : IRat +{ + Game& game; + int attack{1}; + + Rat(Game &game) : game(game) + { + game.rats.push_back(this); + game.fire_rat_enters(this); + } + + ~Rat() { game.fire_rat_dies(this); } + + void rat_enters(IRat *sender) override { + if (sender != this) + { + ++attack; + game.fire_notify(sender); + } + } + + void rat_dies(IRat *sender) override { + --attack; + } + + void notify(IRat *target) override { + if (target == this) ++attack; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, SingleRatTest) + { + Game game; + Rat rat{game}; + ASSERT_EQ(1, rat.attack); + } + + TEST_F(Evaluate, TwoRatTest) + { + Game game; + Rat rat{game}; + Rat rat2{game}; + ASSERT_EQ(2, rat.attack); + ASSERT_EQ(2, rat2.attack); + } + + TEST_F(Evaluate, ThreeRatsOneDies) + { + Game game; + Rat rat{game}; + ASSERT_EQ(1, rat.attack); + + Rat rat2{game}; + ASSERT_EQ(2, rat.attack); + ASSERT_EQ(2, rat2.attack); + + { + Rat rat3{game}; + + ASSERT_EQ(3, rat.attack); + ASSERT_EQ(3, rat2.attack); + ASSERT_EQ(3, rat3.attack); + } + + ASSERT_EQ(2, rat.attack); + ASSERT_EQ(2, rat2.attack); + } + +} // namespace + +// ERROR ON UDEMY'S END, POST AGAIN + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/Observer/new/Observable.cpp b/Behavioral/Observer/new/Observable.cpp new file mode 100644 index 0000000..7e2caa8 --- /dev/null +++ b/Behavioral/Observer/new/Observable.cpp @@ -0,0 +1,2 @@ +#include "Observer.hpp" +#include "Observable.hpp" diff --git a/Behavioral/Observer/new/Observable.hpp b/Behavioral/Observer/new/Observable.hpp new file mode 100644 index 0000000..187e4e5 --- /dev/null +++ b/Behavioral/Observer/new/Observable.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +template struct Observer; + +template struct Observable +{ + // should this be an std::set? + std::vector*> observers; +public: + // informs all observers when a change is made + void notify(T& source, const std::string& field_name) + { + for (auto observer : observers) + observer->field_changed(source, field_name); + } + + void subscribe(Observer& observer) + { + observers.push_back(&observer); + } + + void unsubscribe(Observer& observer) + { + observers.erase( + remove(observers.begin(), observers.end(), &observer), + observers.end() + ); + } +}; \ No newline at end of file diff --git a/Behavioral/Observer/new/Observer.cpp b/Behavioral/Observer/new/Observer.cpp new file mode 100644 index 0000000..18f09c7 --- /dev/null +++ b/Behavioral/Observer/new/Observer.cpp @@ -0,0 +1 @@ +#include "Observer.hpp" diff --git a/Behavioral/Observer/new/Observer.hpp b/Behavioral/Observer/new/Observer.hpp new file mode 100644 index 0000000..2d2b4fa --- /dev/null +++ b/Behavioral/Observer/new/Observer.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +template struct Observer +{ + virtual void field_changed( + T& source, // reference to the object that changed + const std::string& field_name // name of field (property) that changed + ) = 0; +}; + + diff --git a/Behavioral/Observer/new/SaferObservable.cpp b/Behavioral/Observer/new/SaferObservable.cpp new file mode 100644 index 0000000..0152c26 --- /dev/null +++ b/Behavioral/Observer/new/SaferObservable.cpp @@ -0,0 +1 @@ +#include "SaferObservable.hpp" diff --git a/Behavioral/Observer/new/SaferObservable.hpp b/Behavioral/Observer/new/SaferObservable.hpp new file mode 100644 index 0000000..d4fdc39 --- /dev/null +++ b/Behavioral/Observer/new/SaferObservable.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include + + +template struct Observer; + +template struct SaferObservable +{ + std::vector*> observers; + //std::mutex mtx; + typedef std::recursive_mutex mutex_t; + mutex_t mtx; // not recommended +public: + // informs all observers when a change is made + void notify(T& source, const std::string& field_name) + { + std::scoped_lock lock{mtx}; + for (auto observer : observers) + if (observer) // added for reentrancy + observer->field_changed(source, field_name); + } + + void subscribe(Observer& observer) + { + std::scoped_lock lock{mtx}; + observers.push_back(&observer); + } + + void unsubscribe(Observer& observer) + { +// std::scoped_lock lock{mtx}; +// observers.erase( +// remove(observers.begin(), observers.end(), &observer), +// observers.end() +// ); + + // avoid taking a lock here + // avoid removal of the object + auto it = std::find(begin(observers), end(observers), &observer); + if (it != end(observers)) + *it = nullptr; // not viable for an std::set + } +}; \ No newline at end of file diff --git a/Behavioral/Observer/new/headers.hpp b/Behavioral/Observer/new/headers.hpp new file mode 100644 index 0000000..be56e92 --- /dev/null +++ b/Behavioral/Observer/new/headers.hpp @@ -0,0 +1,34 @@ +#pragma once + +#define _USE_MATH_DEFINES +#define _HAS_AUTO_PTR_ETC 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +//using namespace std::string_literals; + +//#include +//#include +//#include +//#include +#include +//#include +using namespace boost; +using namespace boost::signals2; + +#define GTEST_LANG_CXX11 1 +#include \ No newline at end of file diff --git a/Behavioral/Observer/new/main.cpp b/Behavioral/Observer/new/main.cpp new file mode 100644 index 0000000..b8dafcc --- /dev/null +++ b/Behavioral/Observer/new/main.cpp @@ -0,0 +1,151 @@ +#include "Headers.hpp" +#include "Observer.hpp" +#include "Observable.hpp" +#include "SaferObservable.hpp" + +class Person : public SaferObservable +{ + int age; +public: + Person(int age) : age(age) {} + + int get_age() const + { + return age; + } + + // no dependencies +// void set_age(int age) +// { +// if (this->age == age) return; +// this->age = age; +// notify(*this, "age"); +// } + + void set_age(int age) + { + if (this->age == age) return; + + auto old_can_vote = get_can_vote(); + this->age = age; + notify(*this, "age"); + + // determine if voting status changed + if (old_can_vote != get_can_vote()) + notify(*this, "can_vote"); + } + + bool get_can_vote() const + { + return age >= 16; + } +}; + +// we could define a Person-specific listener +struct PersonListener +{ + virtual void person_changed(Person& p, + const string property_name) = 0; +}; // changes can occur on other objects, so + + +struct ConsolePersonObserver + : public Observer // , Observer +{ + void field_changed(Person &source, const string &field_name) override + { + cout << "Person's " << field_name << " has changed to "; + if (field_name == "age") cout << source.get_age(); + if (field_name == "can_vote") cout << boolalpha << source.get_can_vote(); + cout << ".\n"; + } +}; + +// keeps monitoring a person until they're old enough to drive +// when they're old enough, stops monitoring them +struct TrafficAdministration : Observer +{ + void field_changed(Person &source, const std::string &field_name) override + { + if (field_name == "age") + { + if (source.get_age() < 17) + cout << "Whoa there, you're not old enough to drive!\n"; + else + { + // let's not monitor them anymore + cout << "Oh, ok, we no longer care!\n"; + source.unsubscribe(*this); + } + } + } +}; + +// observable with Boost.Signals2 +template struct Observable2 +{ + signal field_changed; +}; + +class Person2 : public Observable2 +{ + int age; +public: + int get_age() const + { + return age; + } + + void set_age(int age) + { + if (this->age == age) return; + this->age = age; + field_changed(*this, "age"); + } +}; + +int main(int ac, char* av[]) +{ + // observer + Person person{10}; + ConsolePersonObserver cpo; + person.subscribe(cpo); + + person.set_age(11); + person.set_age(12); + + //person.unsubscribe(&cpo); + person.set_age(13); + + // boost signals observer + Person2 p2; + auto conn = p2.field_changed.connect([](Person2& p, const string& field_name) + { + cout << field_name << " has changed"; + }); + p2.set_age(20); + conn.disconnect(); + + // dependency problems + cout << "Reaching adulthood...\n"; + person.set_age(20); + + // thread safety and reentrancy + person.unsubscribe(cpo); + TrafficAdministration ta; + person.subscribe(ta); + + person.set_age(16); + + try + { + person.set_age(17); + // notify() --> field_changed() --> ubsubscribe() + } + catch (const std::exception& e) + { + cout << "Oops, " << e.what() << "\n"; + } + + return 0; +} \ No newline at end of file diff --git a/Behavioral/Observer/observer1.cpp b/Behavioral/Observer/observer1.cpp new file mode 100644 index 0000000..0b2d7a0 --- /dev/null +++ b/Behavioral/Observer/observer1.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +using namespace std; +#include +using namespace boost; + +namespace +{ + + struct Person; + + struct PersonListener + { + virtual ~PersonListener() = default; + virtual void person_changed(Person& p, const string& property_name, const any new_value) = 0; + }; + + struct Person + { + explicit Person(int age) + : age(age) + { + } + + int get_age() const + { + return age; + } + + void set_age(const int age); + + bool get_can_vote() const + { + return age >= 16; + } + + void subscribe(PersonListener* pl); + + void notify(const string& property_name, const any new_value); + private: + int age; + vector listeners; + }; + + void Person::set_age(const int age) + { + if (this->age == age) return; + + auto old_c_v = get_can_vote(); + + this->age = age; + notify("age", this->age); + + auto new_c_v = get_can_vote(); + if (old_c_v != new_c_v) + { + notify("can_vote", new_c_v); + } + } + + void Person::subscribe(PersonListener* pl) + { + listeners.push_back(pl); + } + + void Person::notify(const string& property_name, const any new_value) + { + for (const auto listener : listeners) + listener->person_changed(*this, property_name, new_value); + } + + struct ConsoleListener : PersonListener + { + void person_changed(Person& p, const string& property_name, const any new_value) override + { + cout << "person's " << property_name << " has been changed to "; + if (property_name == "age") + { + cout << any_cast(new_value); + } + else if (property_name == "can_vote") + { + cout << any_cast(new_value); + } + cout << "\n"; + } + }; + + int main() + { + Person p{ 14 }; + ConsoleListener cl; + p.subscribe(&cl); + p.set_age(15); + p.set_age(16); + + + getchar(); + return 0; + } + +} \ No newline at end of file diff --git a/Behavioral/Observer/observer2.cpp b/Behavioral/Observer/observer2.cpp new file mode 100644 index 0000000..80607b7 --- /dev/null +++ b/Behavioral/Observer/observer2.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +using namespace std; +#include +using namespace boost; + +namespace { + +struct Person; + +struct PersonListener +{ + virtual ~PersonListener() = default; + virtual void person_changed(Person& p, const string& property_name, const any new_value) = 0; +}; + +static mutex mtx; + +struct Person +{ + explicit Person(int age) + : age(age) + { + } + + int get_age() const + { + return age; + } + + void set_age(const int age) + { + if (this->age == age) return; + + auto old_c_v = get_can_vote(); + + this->age = age; + notify("age", this->age); + + auto new_c_v = get_can_vote(); + if (old_c_v != new_c_v) + { + notify("can_vote", new_c_v); + } + } + + bool get_can_vote() const + { + return age >= 16; + } + + void subscribe(PersonListener* pl) + { + lock_guard guard{ mtx }; + + // prevent existing references? + if (find(begin(listeners), end(listeners), pl) == end(listeners)) + listeners.push_back(pl); + } + void ubsubscribe(PersonListener* pl) + { + lock_guard guard{ mtx }; + if (listeners.empty()) return; + // multiple identical listeners? + // erase-remove idiom? + for (auto it = listeners.begin(); it != listeners.end(); ++it) + { + if (*it == pl) + { + *it = nullptr; // just mark as nullptr + } + } + } +private: + int age; + vector listeners; + + void notify(const string& property_name, const any new_value) + { + lock_guard guard{ mtx }; + for (const auto listener : listeners) + if (listener) + listener->person_changed(*this, property_name, new_value); + + // erase-remove + listeners.erase( + remove(listeners.begin(), listeners.end(), nullptr), + listeners.end() + ); + } + + // std::list (easier to remove elements) + // concurrent_vector? yes, but no easy erase-remove +}; + +struct ConsoleListener : PersonListener +{ + void person_changed(Person& p, const string& property_name, + const any new_value) override + { + cout << "person's " << property_name << " has been changed to "; + if (property_name == "age") + { + cout << any_cast(new_value); + } + else if (property_name == "can_vote") + { + cout << any_cast(new_value); + } + cout << "\n"; + } +}; + +int main__x_() +{ + Person p{ 14 }; + ConsoleListener cl; + p.subscribe(&cl); + p.subscribe(&cl); // ignored + p.set_age(15); + p.set_age(16); + p.ubsubscribe(&cl); + p.set_age(17); + + + getchar(); + return 0; +} + +} \ No newline at end of file diff --git a/Behavioral/Observer/observer3.cpp b/Behavioral/Observer/observer3.cpp new file mode 100644 index 0000000..a83b082 --- /dev/null +++ b/Behavioral/Observer/observer3.cpp @@ -0,0 +1,53 @@ +#include +#include +using namespace std; +#include +using namespace boost; +using namespace signals2; + +namespace { + +template +struct Observable +{ + virtual ~Observable() = default; + signal property_changed; +}; + +struct Person : Observable +{ + explicit Person(int age) + : age(age) + { + } + + int get_age() const + { + return age; + } + + void set_age(const int age) + { + if (this->age == age) return; + + this->age = age; + property_changed(*this, "age"); + } + +private: + int age; +}; + +int main_() +{ + Person p{123}; + p.property_changed.connect([](Person&, const string& prop_name) + { + cout << prop_name << " has been changed" << endl; + }); + p.set_age(20); + + getchar(); + return 0; +} +} \ No newline at end of file diff --git a/Behavioral/Observer/observer_book.cpp b/Behavioral/Observer/observer_book.cpp new file mode 100644 index 0000000..079b9e7 --- /dev/null +++ b/Behavioral/Observer/observer_book.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +#include +using namespace Concurrency; + +#include + +template struct Observer; + +template +struct Observable +{ + typedef mutex mutex_t; + + void notify(T& source, const string& name) + { + vector*> observers_copy; + { + lock_guard lock{ mtx }; + observers_copy = observers; + } + for (auto obs : observers_copy) + if (obs) + obs->field_changed(source, name); + + observers.erase( + remove(observers.begin(), observers.end(), nullptr), + observers.end()); + } + /*void notify(T& source, const string& name) + { + lock_guard lock{ mtx }; + for (auto obs : observers) + if (obs) + obs->field_changed(source, name); + + observers.erase( + remove(observers.begin(), observers.end(), nullptr), + observers.end()); + }*/ + void subscribe(Observer* f) + { + lock_guard lock{ mtx }; + observers.push_back(f); + } + void unsubscribe(Observer* o) + { + lock_guard lock{ mtx }; + auto it = find(observers.begin(), observers.end(), o); + if (it != observers.end()) + *it = nullptr; // cannot do this for a set + } +private: + vector*> observers; + mutex_t mtx; +}; + +template struct Observer +{ + virtual void field_changed(T& source, const string& field_name) = 0; +}; + +struct Person : Observable +{ + explicit Person(const int age) + : age(age) + { + } + + int get_age() const + { + return age; + } + + void set_age(const int age) + { + if (this->age == age) return; + + auto old_can_vote = can_vote(); + this->age = age; + + notify(*this, "age"); + + if (old_can_vote != can_vote()) + notify(*this, "can_vote"); + } + + bool can_vote() const + { + return age >= 16; + } + +private: + int age; +}; + +struct Creature +{ + +}; + +struct ConsolePersonObserver : Observer +{ + void field_changed(Person& source, const string& field_name) override + { + cout << "Person's " << field_name << " has changed to " + << source.get_age() << ".\n"; + } +}; + +struct TrafficAdministration : Observer +{ + void TrafficAdministration::field_changed( + Person& source, const string& field_name) override + { + if (field_name == "age") + { + if (source.get_age() < 17) + cout << "Whoa there, you are not old enough to drive!\n"; + else + { + // oh, ok, they are old enough, let's not monitor them anymore + cout << "We no longer care!\n"; + source.unsubscribe(this); + } + } + } +}; + + + +int main() +{ + cout << "observer book" << endl; + + /*Person p{ 20 }; + ConsolePersonObserver cpo; + p.subscribe(&cpo); + p.set_age(21); + p.set_age(22);*/ + + Person p{ 10 }; + TrafficAdministration o; + p.subscribe(&o); + p.set_age(16); + p.set_age(17); + p.set_age(21); + + getchar(); + return 0; +} diff --git a/Behavioral/Observer/observer_notes.cpp b/Behavioral/Observer/observer_notes.cpp new file mode 100644 index 0000000..4b46326 --- /dev/null +++ b/Behavioral/Observer/observer_notes.cpp @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +class Foo; +using namespace std; + +// function pointer + +// observer pattern in quantlib + +// changes in a collection vs its members + +// boost::signal +// proeprty change notification +// rxcpp + +recursive_mutex mtx; +// but even so, this can deadlock + +struct Listener +{ + virtual void fooChanged(Foo* foo); // not const + virtual ~Listener() = default; +}; + + +class Foo +{ + string s; + vector listeners; // set<>? + // also, list<> instead of vector lets you remove while iterating +public: + + virtual string GetS() const + { + return s; + } + + virtual void SetS(const string cs) + { + // lock here too? + if (s != cs) + { + s = cs; + notifyListeners(); + } + } + + void addListener(Listener* l) + { + listeners.push_back(l); + + // add might reallocate the vector, so recursive add fails + } + + bool removeListener(Listener* l) + { + // doesn't remove things + //remove(listeners.begin(), listeners.end(), l); + + + + listeners.erase( + remove(listeners.begin(), listeners.end(), l), + listeners.end() + ); + + // alternatively, find and remove + // this just removes 1st occurrence + listeners.erase( + find(listeners.begin(), listeners.end(), l) + ); + + // but what happens if item is NOT in the list? + // this crashes because find() returns end() :( + + + auto it = find(listeners.begin(), listeners.end(), l); + if (it != listeners.end()) + { + listeners.erase(it); + + // return true? + } + // return false + + // can also begin rbegin()/rend() + // no, erase() does not take a reverse_iterator + + // whose alice are we removing? should we be + // returning a memento? + + // point is, this is all crap for ordering and such + + // how about NOT removing but just nulling + for (auto it = listeners.begin(); it != listeners.end(); ++it) + { + if (*it == l) + { + *it = nullptr; // only the first one + // but we can only handle the case of removing ourselves + // not other people + return true; + } + } + + // and BTW, null listeners will be nuked! maybe a check? + + return false; + } +private: + void notifyListeners() + { + lock_guard lg(mtx); // non-recursive + + if (listeners.empty()) return; + + // implicit ++ here that will crash on recusive + // array indexing? + int size = listeners.size(); + for (int i = 0; i < size; ++i) + if (listeners[i]) + listeners[i]->fooChanged(this); // not safe + // remove any nulls + listeners.erase( + remove(listeners.begin(), listeners.end(), nullptr), + listeners.end() + ); + + // better version at 31:12 + } +}; + +void Listener::fooChanged(Foo* foo) +{ + cout << "foo has been changed to " << foo << "\n"; +} + +struct ScopeListener : Listener +{ + Foo& foo; + + explicit ScopeListener(Foo& foo) + : foo(foo) + { + startListening(); + } + + ~ScopeListener() + { + stopListening(); + } + + void startListening() { foo.addListener(this); } + void stopListening() { foo.removeListener(this); } + + + void fooChanged(Foo* foo) override; +}; + +void ScopeListener::fooChanged(Foo* foo) +{ + cout << foo->GetS(); + this->stopListening(); +} + +void cppnow_talk() +{ + // alice and bob - listeners are ordered (priority?) + + // add same listener twice - should it be a set? + // if I remove one, I remove 2 of them + // locally code worries about itself, but then, + // how do I know an item is already there + // either usage_count or set<> + + Foo foo; + ScopeListener sl(foo); + + foo.SetS("abc"); // will crash + // removing a listener inside a listener + // changing an iterated collection! + + // and then an observer has a pointer to a different observer +} + +int main__() +{ + cppnow_talk(); + + getchar(); + return 0; +} diff --git a/Behavioral/State/State.vcxproj b/Behavioral/State/State.vcxproj new file mode 100644 index 0000000..ddebade --- /dev/null +++ b/Behavioral/State/State.vcxproj @@ -0,0 +1,125 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {84B29C64-523E-4C27-9FC6-017C0AC23FEC} + State + 8.1 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + c:\boost + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + c:\boost + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/State/State.vcxproj.filters b/Behavioral/State/State.vcxproj.filters new file mode 100644 index 0000000..7b7d708 --- /dev/null +++ b/Behavioral/State/State.vcxproj.filters @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/State/State.vcxproj.user b/Behavioral/State/State.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/State/State.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/State/StateCodingExercise.cpp b/Behavioral/State/StateCodingExercise.cpp new file mode 100644 index 0000000..a7ee000 --- /dev/null +++ b/Behavioral/State/StateCodingExercise.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +using namespace std; + +class CombinationLock +{ + vector combination; + int digits_entered{0}; + bool failed{false}; + + void reset() + { + status = "LOCKED"; + digits_entered = 0; + failed = false; + } +public: + string status; + + CombinationLock(const vector &combination) : combination(combination) { + reset(); + } + + void enter_digit(int digit) + { + if (status == "LOCKED") status = ""; + status += to_string(digit); + if (combination[digits_entered] != digit) + { + failed = true; + } + digits_entered++; + + if (digits_entered == combination.size()) + status = failed ? "ERROR" : "OPEN"; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, TestSuccess) + { + CombinationLock cl({1,2,3}); + ASSERT_EQ("LOCKED", cl.status); + + cl.enter_digit(1); + ASSERT_EQ("1", cl.status); + + cl.enter_digit(2); + ASSERT_EQ("12", cl.status); + + cl.enter_digit(3); + ASSERT_EQ("OPEN", cl.status); + } + + TEST_F(Evaluate, TestFailure) + { + CombinationLock cl({1,2,3}); + ASSERT_EQ("LOCKED", cl.status); + + cl.enter_digit(1); + ASSERT_EQ("1", cl.status); + + cl.enter_digit(2); + ASSERT_EQ("12", cl.status); + + cl.enter_digit(5); + ASSERT_EQ("ERROR", cl.status); + } + +} // namespace + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/State/classic.cpp b/Behavioral/State/classic.cpp new file mode 100644 index 0000000..9193315 --- /dev/null +++ b/Behavioral/State/classic.cpp @@ -0,0 +1,76 @@ +#include +#include +using namespace std; + +class LightSwitch; + +struct State +{ + virtual void on(LightSwitch *ls) + { + cout << "Light is already on\n"; + } + virtual void off(LightSwitch *ls) + { + cout << "Light is already off\n"; + } +}; + +struct OnState : State +{ + OnState() + { + cout << "Light turned on\n"; + } + + void off(LightSwitch* ls) override; +}; + +struct OffState : State +{ + OffState() + { + cout << "Light turned off\n"; + } + + void on(LightSwitch* ls) override; +}; + +class LightSwitch +{ + State *state; +public: + LightSwitch() + { + state = new OffState(); + } + void set_state(State* state) + { + this->state = state; + } + void on() { state->on(this); } + void off() { state->off(this); } +}; + +void OnState::off(LightSwitch* ls) +{ + cout << "Switching light off...\n"; + ls->set_state(new OffState()); + delete this; +} + +void OffState::on(LightSwitch* ls) +{ + cout << "Switching light on...\n"; + ls->set_state(new OnState()); + delete this; +} + +void main_3() +{ + LightSwitch ls; + ls.on(); + ls.off(); + ls.off(); + getchar(); +} \ No newline at end of file diff --git a/Behavioral/State/handmade.cpp b/Behavioral/State/handmade.cpp new file mode 100644 index 0000000..86475db --- /dev/null +++ b/Behavioral/State/handmade.cpp @@ -0,0 +1,137 @@ +#include +#include +#include +#include +using namespace std; + +enum class State +{ + off_hook, + connecting, + connected, + on_hold, + on_hook +}; + +inline ostream& operator<<(ostream& os, const State& s) +{ + switch (s) + { + case State::off_hook: + os << "off the hook"; + break; + case State::connecting: + os << "connecting"; + break; + case State::connected: + os << "connected"; + break; + case State::on_hold: + os << "on hold"; + break; + case State::on_hook: + os << "on the hook"; + break; + } + return os; +} + +enum class Trigger +{ + call_dialed, + hung_up, + call_connected, + placed_on_hold, + taken_off_hold, + left_message, + stop_using_phone +}; + +inline ostream& operator<<(ostream& os, const Trigger& t) +{ + switch (t) + { + case Trigger::call_dialed: + os << "call dialed"; + break; + case Trigger::hung_up: + os << "hung up"; + break; + case Trigger::call_connected: + os << "call connected"; + break; + case Trigger::placed_on_hold: + os << "placed on hold"; + break; + case Trigger::taken_off_hold: + os << "taken off hold"; + break; + case Trigger::left_message: + os << "left message"; + break; + case Trigger::stop_using_phone: + os << "putting phone on hook"; + break; + default: break; + } + return os; +} + +int main_f(char* argv[]) +{ + map>> rules; + + rules[State::off_hook] = { + {Trigger::call_dialed, State::connecting}, + {Trigger::stop_using_phone, State::on_hook} + }; + + rules[State::connecting] = { + {Trigger::hung_up, State::off_hook}, + {Trigger::call_connected, State::connected} + }; + + rules[State::connected] = { + {Trigger::left_message, State::off_hook}, + {Trigger::hung_up, State::off_hook}, + {Trigger::placed_on_hold, State::on_hold} + }; + + rules[State::on_hold] = { + {Trigger::taken_off_hold, State::connected}, + {Trigger::hung_up, State::off_hook} + }; + + State currentState{ State::off_hook }, + exitState{ State::on_hook }; + + while (true) + { + cout << "The phone is currently " << currentState << endl; + select_trigger: + cout << "Select a trigger:" << "\n"; + + int i = 0; + for (auto item : rules[currentState]) + { + cout << i++ << ". " << item.first << "\n"; + } + + int input; + cin >> input; + if (input < 0 || (input+1) > rules[currentState].size()) + { + cout << "Incorrect option. Please try again." << "\n"; + goto select_trigger; + } + + currentState = rules[currentState][input].second; + if (currentState == exitState) break; + } + + cout << "We are done using the phone" << "\n"; + + getchar(); + getchar(); + return 0; +} diff --git a/Behavioral/State/msm.cpp b/Behavioral/State/msm.cpp new file mode 100644 index 0000000..04a4fc3 --- /dev/null +++ b/Behavioral/State/msm.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +using namespace std; + +// back-end +#include + +//front-end +#include +#include + +namespace msm = boost::msm; +namespace mpl = boost::mpl; +using namespace msm::front; + +vector state_names{ + "off hook"s, + "connecting"s, + "connected"s, + "on hold"s, + "destroyed"s +}; + +// transitions/events +struct CallDialed {}; +struct HungUp {}; +struct CallConnected {}; +struct PlacedOnHold {}; +struct TakenOffHold {}; +struct LeftMessage {}; +struct PhoneThrownIntoWall {}; + +struct PhoneStateMachine : state_machine_def +{ + bool angry{ true }; // start with false + + struct OffHook : state<> {}; + struct Connecting : state<> + { + template + void on_entry(Event const& evt, FSM&) + { + cout << "We are connecting..." << endl; + } + // also on_exit + }; + struct Connected : state<> {}; + struct OnHold : state<> {}; + struct PhoneDestroyed : state<> {}; + + struct PhoneBeingDestroyed + { + template + void operator()(EVT const&, FSM&, SourceState&, TargetState&) + { + cout << "Phone breaks into a million pieces" << endl; + } + }; + + struct CanDestroyPhone + { + template + bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) + { + return fsm.angry; + } + }; + + // start, event, target, action, guard + struct transition_table : mpl::vector < + Row, + Row, + Row, + Row + > {}; + + // starting state + typedef OffHook initial_state; + + // what happens if there's nowhere to go + template + void no_transition(Event const& e, FSM&, int state) + { + cout << "No transition from state " << state_names[state] + << " on event " << typeid(e).name() << endl; + } +}; + + + +int main() +{ + msm::back::state_machine phone; + + auto info = [&]() + { + auto i = phone.current_state()[0]; + cout << "The phone is currently " << + state_names[i] << "\n"; + }; + + info(); + phone.process_event(CallDialed{}); + info(); + phone.process_event(CallConnected{}); + info(); + phone.process_event(PlacedOnHold{}); + info(); + phone.process_event(PhoneThrownIntoWall{}); + info(); + + // try process_event here :) + phone.process_event(CallDialed{}); + + cout << "We are done using the phone" << "\n"; + + getchar(); + return 0; +} diff --git a/Behavioral/Strategy/Strategy.vcxproj b/Behavioral/Strategy/Strategy.vcxproj new file mode 100644 index 0000000..20ef18f --- /dev/null +++ b/Behavioral/Strategy/Strategy.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {76DDB609-2C93-41A2-BDED-5E0F2F81652B} + Win32Proj + Strategy + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Strategy/Strategy.vcxproj.filters b/Behavioral/Strategy/Strategy.vcxproj.filters new file mode 100644 index 0000000..1e9dd3a --- /dev/null +++ b/Behavioral/Strategy/Strategy.vcxproj.filters @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Behavioral/Strategy/Strategy.vcxproj.user b/Behavioral/Strategy/Strategy.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Strategy/Strategy.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Strategy/StrategyCodingExercise.cpp b/Behavioral/Strategy/StrategyCodingExercise.cpp new file mode 100644 index 0000000..72238bb --- /dev/null +++ b/Behavioral/Strategy/StrategyCodingExercise.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include +using namespace std; + +struct DiscriminantStrategy +{ + virtual double calculate_discriminant(double a, double b, double c) = 0; +}; + +struct OrdinaryDiscriminantStrategy : DiscriminantStrategy +{ + double calculate_discriminant(double a, double b, double c) override { + return b*b - 4*a*c; + } +}; + +struct RealDiscriminantStrategy : DiscriminantStrategy +{ + double calculate_discriminant(double a, double b, double c) override { + double result = b*b - 4*a*c; + return result >= 0 ? result : numeric_limits::quiet_NaN(); + } +}; + +class QuadraticEquationSolver +{ + DiscriminantStrategy& strategy; +public: + QuadraticEquationSolver(DiscriminantStrategy &strategy) : strategy(strategy) {} + + tuple, complex> solve(double a, double b, double c) + { + complex disc{strategy.calculate_discriminant(a,b,c), 0}; + auto root_disc = sqrt(disc); + return { + (-b+root_disc) / (2*a), + (-b-root_disc) / (2*a) }; + }; +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, PositiveTestOrdinaryStrategy) + { + OrdinaryDiscriminantStrategy strategy; + QuadraticEquationSolver solver{strategy}; + auto results = solver.solve(1,10,16); + ASSERT_EQ(complex(-2,0), get<0>(results)); + ASSERT_EQ(complex(-8,0), get<1>(results)); + } + + TEST_F(Evaluate, PositiveTestRealStrategy) + { + RealDiscriminantStrategy strategy; + QuadraticEquationSolver solver{strategy}; + auto results = solver.solve(1,10,16); + ASSERT_EQ(complex(-2,0), get<0>(results)); + ASSERT_EQ(complex(-8,0), get<1>(results)); + } + + TEST_F(Evaluate, NegativeTestOrdinaryStrategy) + { + OrdinaryDiscriminantStrategy strategy; + QuadraticEquationSolver solver{strategy}; + auto results = solver.solve(1,4,5); + ASSERT_EQ(complex(-2,1), get<0>(results)); + ASSERT_EQ(complex(-2,-1), get<1>(results)); + } + + TEST_F(Evaluate, NegativeTestRealStrategy) + { + RealDiscriminantStrategy strategy; + QuadraticEquationSolver solver{strategy}; + auto results = solver.solve(1,4,5); + auto x1 = get<0>(results); + auto x2 = get<1>(results); + ASSERT_TRUE(isnan(x1.real())); + ASSERT_TRUE(isnan(x2.real())); + ASSERT_TRUE(isnan(x1.imag())); + ASSERT_TRUE(isnan(x2.imag())); + } + +} // namespace + +// ERROR ON UDEMY'S END, POST AGAIN + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/Strategy/strategy_dynamic.cpp b/Behavioral/Strategy/strategy_dynamic.cpp new file mode 100644 index 0000000..6509ac0 --- /dev/null +++ b/Behavioral/Strategy/strategy_dynamic.cpp @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +using namespace std; + +enum class OutputFormat +{ + Markdown, + Html +}; + +struct ListStrategy +{ + virtual ~ListStrategy() = default; + virtual void add_list_item(ostringstream& oss, const string& item) {}; + virtual void start(ostringstream& oss) {}; + virtual void end(ostringstream& oss) {}; +}; + +struct MarkdownListStrategy : ListStrategy +{ + void add_list_item(ostringstream& oss, const string& item) override + { + oss << " * " << item << endl; + } +}; + +struct HtmlListStrategy : ListStrategy +{ + void start(ostringstream& oss) override + { + oss << "
    " << endl; + } + + void end(ostringstream& oss) override + { + oss << "
" << endl; + } + + void add_list_item(ostringstream& oss, const string& item) override + { + oss << "
  • " << item << "
  • " << endl; + } +}; + +struct TextProcessor +{ + void clear() + { + oss.str(""); + oss.clear(); + } + void append_list(const vector items) + { + list_strategy->start(oss); + for (auto& item : items) + list_strategy->add_list_item(oss, item); + list_strategy->end(oss); + } + + void set_output_format(const OutputFormat format) + { + switch(format) + { + case OutputFormat::Markdown: + list_strategy = make_unique(); + break; + case OutputFormat::Html: + list_strategy = make_unique(); + break; + default: + throw runtime_error("Unsupported strategy."); + } + } + string str() const { return oss.str(); } +private: + ostringstream oss; + unique_ptr list_strategy; +}; + +int main_() +{ + // markdown + TextProcessor tp; + tp.set_output_format(OutputFormat::Markdown); + tp.append_list({"foo", "bar", "baz"}); + cout << tp.str() << endl; + + // html + tp.clear(); + tp.set_output_format(OutputFormat::Html); + tp.append_list({"foo", "bar", "baz"}); + cout << tp.str() << endl; + + getchar(); + return 0; +} diff --git a/Behavioral/Strategy/strategy_static.cpp b/Behavioral/Strategy/strategy_static.cpp new file mode 100644 index 0000000..da19028 --- /dev/null +++ b/Behavioral/Strategy/strategy_static.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +using namespace std; + +enum class OutputFormat +{ + Markdown, + Html +}; + +struct ListStrategy +{ + virtual ~ListStrategy() = default; + virtual void add_list_item(ostringstream& oss, const string& item) = 0; + virtual void start(ostringstream& oss) = 0; + virtual void end(ostringstream& oss) = 0; +}; + +struct MarkdownListStrategy : ListStrategy +{ + void start(ostringstream& oss) override + { + } + + void end(ostringstream& oss) override + { + } + + void add_list_item(ostringstream& oss, const string& item) override + { + oss << " * " << item << endl; + } +}; + +struct HtmlListStrategy : ListStrategy +{ + void start(ostringstream& oss) override + { + oss << "
      " << endl; + } + + void end(ostringstream& oss) override + { + oss << "
    " << endl; + } + + void add_list_item(ostringstream& oss, const string& item) override + { + oss << "
  • " << item << "
  • " << endl; + } +}; + +template +struct TextProcessor +{ + void clear() + { + oss.str(""); + oss.clear(); + } + void append_list(const vector items) + { + list_strategy.start(oss); + for (auto& item : items) + list_strategy.add_list_item(oss, item); + list_strategy.end(oss); + } + string str() const { return oss.str(); } +private: + ostringstream oss; + LS list_strategy; +}; + +int main() +{ + // markdown + TextProcessor tpm; + tpm.append_list({"foo", "bar", "baz"}); + cout << tpm.str() << endl; + + // html + TextProcessor tph; + tph.append_list({"foo", "bar", "baz"}); + cout << tph.str() << endl; + + getchar(); + return 0; +} diff --git a/Behavioral/TemplateMethod/TemplateMethod.vcxproj b/Behavioral/TemplateMethod/TemplateMethod.vcxproj new file mode 100644 index 0000000..fde8dcc --- /dev/null +++ b/Behavioral/TemplateMethod/TemplateMethod.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {522A86A0-1065-4568-9329-9214081C7993} + Win32Proj + TemplateMethod + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/TemplateMethod/TemplateMethod.vcxproj.filters b/Behavioral/TemplateMethod/TemplateMethod.vcxproj.filters new file mode 100644 index 0000000..5880af1 --- /dev/null +++ b/Behavioral/TemplateMethod/TemplateMethod.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Behavioral/TemplateMethod/TemplateMethod.vcxproj.user b/Behavioral/TemplateMethod/TemplateMethod.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/TemplateMethod/TemplateMethod.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/TemplateMethod/TemplateMethodCodingExercise.cpp b/Behavioral/TemplateMethod/TemplateMethodCodingExercise.cpp new file mode 100644 index 0000000..e945b4f --- /dev/null +++ b/Behavioral/TemplateMethod/TemplateMethodCodingExercise.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include +using namespace std; + +struct Creature +{ + int attack, health; + + Creature(int attack, int health) : attack(attack), health(health) {} +}; + +struct CardGame +{ + vector creatures; + + CardGame(const vector &creatures) : creatures(creatures) {} + + // return -1 if there is no clear winner + int combat(int creature1, int creature2) + { + Creature& first = creatures[creature1]; + Creature& second = creatures[creature2]; + hit(first, second); + hit(second, first); + bool first_alive = first.health > 0; + bool second_alive = second.health > 0; + if (first_alive == second_alive) return -1; + return first_alive ? creature1 : creature2; + } + + virtual void hit(Creature& attacker, Creature& other) = 0; +}; + +struct TemporaryCardDamageGame : CardGame +{ + TemporaryCardDamageGame(const vector &creatures) : CardGame(creatures) {} + + void hit(Creature &attacker, Creature &other) override { + auto old_health = other.health; + other.health -= attacker.attack; + if (other.health > 0) other.health = old_health; + } +}; + +struct PermanentCardDamageGame : CardGame +{ + PermanentCardDamageGame(const vector &creatures) : CardGame(creatures) {} + + void hit(Creature &attacker, Creature &other) override + { + other.health -= attacker.attack; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, ImpasseTest) + { + Creature c1{1,2}; + Creature c2{1,2}; + TemporaryCardDamageGame game({c1,c2}); + ASSERT_EQ(-1, game.combat(0,1)); + ASSERT_EQ(-1, game.combat(0,1)); + } + + TEST_F(Evaluate, TemporaryMurderTest) + { + Creature c1{1,1}; + Creature c2{2,2}; + TemporaryCardDamageGame game({c1,c2}); + ASSERT_EQ(1, game.combat(0,1)); + } + + TEST_F(Evaluate, DoubleMurderTest) + { + Creature c1{2,2}; + Creature c2{2,2}; + TemporaryCardDamageGame game({c1,c2}); + ASSERT_EQ(-1, game.combat(0,1)) << "The expectation here is that two 2/2 creatures kill each other"; + } + + TEST_F(Evaluate, PermanentDamageDeathTest) + { + Creature c1{1,2}; + Creature c2{1,3}; + PermanentCardDamageGame game({c1, c2}); + ASSERT_EQ(-1, game.combat(0,1)) << "1/2 vs 1/3 should have no winner after first round of combat"; + ASSERT_EQ(1, game.combat(0,1)) << "1/1 vs 1/2 here, so winner should be = 1"; + } + +} // namespace + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/TemplateMethod/template_method.cpp b/Behavioral/TemplateMethod/template_method.cpp new file mode 100644 index 0000000..b28cd14 --- /dev/null +++ b/Behavioral/TemplateMethod/template_method.cpp @@ -0,0 +1,70 @@ +#include +#include +using namespace std; + +class Game +{ +public: + explicit Game(int number_of_players) + : number_of_players(number_of_players) + { + } + + void run() + { + start(); + while (!have_winner()) + take_turn(); + cout << "Player " << get_winner() << " wins.\n"; + } + +protected: + virtual void start() = 0; + virtual bool have_winner() = 0; + virtual void take_turn() = 0; + virtual int get_winner() = 0; + + int current_player{ 0 }; + int number_of_players; +}; + +class Chess : public Game +{ +public: + explicit Chess() : Game{ 2 } {} + +protected: + void start() override + { + cout << "Starting a game of chess with " << number_of_players << " players\n"; + } + + bool have_winner() override + { + return turns == max_turns; + } + + void take_turn() override + { + cout << "Turn " << turns << " taken by player " << current_player << "\n"; + turns++; + current_player = (current_player + 1) % number_of_players; + } + + int get_winner() override + { + return current_player; + } + +private: + int turns{ 0 }, max_turns{ 10 }; +}; + +int main() +{ + Chess chess; + chess.run(); + + getchar(); + return 0; +} diff --git a/Behavioral/Visitor/Visitor.vcxproj b/Behavioral/Visitor/Visitor.vcxproj new file mode 100644 index 0000000..356bdee --- /dev/null +++ b/Behavioral/Visitor/Visitor.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8} + Win32Proj + Visitor + 8.1 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + c:\boost + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Visitor/Visitor.vcxproj.filters b/Behavioral/Visitor/Visitor.vcxproj.filters new file mode 100644 index 0000000..a501fa9 --- /dev/null +++ b/Behavioral/Visitor/Visitor.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Behavioral/Visitor/Visitor.vcxproj.user b/Behavioral/Visitor/Visitor.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Behavioral/Visitor/Visitor.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Behavioral/Visitor/VisitorCodingExercise.cpp b/Behavioral/Visitor/VisitorCodingExercise.cpp new file mode 100644 index 0000000..d4229d4 --- /dev/null +++ b/Behavioral/Visitor/VisitorCodingExercise.cpp @@ -0,0 +1,127 @@ +#include +#include +using namespace std; + +struct Value; +struct AdditionExpression; +struct MultiplicationExpression; + +struct ExpressionVisitor +{ + virtual void accept(Value& value) = 0; + virtual void accept(AdditionExpression& ae) = 0; + virtual void accept(MultiplicationExpression& me) = 0; +}; + +struct Expression +{ + virtual void visit(ExpressionVisitor& ev) = 0; +}; + +struct Value : Expression +{ + int value; + + Value(int value) : value(value) {} + + void visit(ExpressionVisitor &ev) override + { + ev.accept(*this); + } +}; + +struct AdditionExpression : Expression +{ + Expression &lhs, &rhs; + + AdditionExpression(Expression &lhs, Expression &rhs) : lhs(lhs), rhs(rhs) {} + + void visit(ExpressionVisitor &ev) override + { + ev.accept(*this); + } +}; + +struct MultiplicationExpression : Expression +{ + Expression &lhs, &rhs; + + MultiplicationExpression(Expression &lhs, Expression &rhs) + : lhs(lhs), rhs(rhs) {} + + void visit(ExpressionVisitor &ev) override + { + ev.accept(*this); + } +}; + +struct ExpressionPrinter : ExpressionVisitor +{ + void accept(Value &value) override + { + oss << value.value; + } + + void accept(AdditionExpression &ae) override + { + oss << "("; + ae.lhs.visit(*this); + oss << "+"; + ae.rhs.visit(*this); + oss << ")"; + } + + void accept(MultiplicationExpression &me) override + { + me.lhs.visit(*this); + oss << "*"; + me.rhs.visit(*this); + } + + string str() const { return oss.str(); } + +private: + ostringstream oss; +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +namespace { + + class Evaluate : public ::testing::Test {}; + + TEST_F(Evaluate, SimpleAddition) + { + Value v{2}; + AdditionExpression simple{v,v}; + ExpressionPrinter ep; + ep.accept(simple); + ASSERT_EQ("(2+2)", ep.str()); + } + + TEST_F(Evaluate, ProductOfAdditionAndValue) + { + Value _2{2}; + Value _3{3}; + Value _4{4}; + AdditionExpression ae{_2, _3}; + MultiplicationExpression expr{ae, _4}; + ExpressionPrinter ep; + ep.accept(expr); + ASSERT_EQ("(2+3)*4", ep.str()); + } + +} // namespace + +// ERROR ON UDEMY'S END, POST AGAIN + +int main(int ac, char* av[]) +{ + //::testing::GTEST_FLAG(catch_exceptions) = false; + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Behavioral/Visitor/model.hpp b/Behavioral/Visitor/model.hpp new file mode 100644 index 0000000..3a858e2 --- /dev/null +++ b/Behavioral/Visitor/model.hpp @@ -0,0 +1,121 @@ +#pragma once +#include + +struct Visitor; + +struct Element +{ + virtual ~Element() = default; + + // print + virtual void print_html(ostringstream& oss) const = 0; + // violates open-closed + // virtual void print_markdown(ostringstream& oss) const = 0; + + // visitor + virtual void accept(Visitor& v) const = 0; +}; + +struct Div : vector, Element +{ + Div(const initializer_list& _Ilist) + : vector(_Ilist) + { + } + + + void accept(Visitor& v) const override + { + } + + void print_html(ostringstream& oss) const override + { + oss << "
    \n"; + for_each(begin(), end(), [&](const Element* e) + { + e->print_html(oss); + }); + oss << "
    \n"; + } +}; + +struct TextElement : Element +{ + explicit TextElement(const string& text) + : text(text) + { + } + + string text; +}; + +struct Paragraph : TextElement +{ + explicit Paragraph(const string& text) + : TextElement(text) + { + } + + + void accept(Visitor& v) const override + { + v.visit(*this); + } + + void print_html(ostringstream& oss) const override + { + oss << "

    " << text << "

    \n"; + } +}; + +struct BoldParagraph : Paragraph +{ + explicit BoldParagraph(const string& text) + : Paragraph(text) + { + } + + + void accept(Visitor& v) const override { + v.visit(*this); + } +}; + +struct ListItem : TextElement +{ + explicit ListItem(const string& text) + : TextElement(text) + { + } + + void accept(Visitor& v) const override + { + v.visit(*this); + } + + void print_html(ostringstream& oss) const override + { + oss << "
  • " << text << "
  • \n"; + } +}; + +struct List : Element, vector +{ + List(const initializer_list& list) + : vector(list) + { + } + + + void accept(Visitor& v) const override + { + v.visit(*this); + } + + void print_html(ostringstream& oss) const override + { + oss << "
      \n"; + for_each(begin(), end(), [&](const ListItem& li) { li.print_html(oss); }); + oss << "
    \n"; + } +}; \ No newline at end of file diff --git a/Behavioral/Visitor/multimethods.cpp b/Behavioral/Visitor/multimethods.cpp new file mode 100644 index 0000000..e9cbc4d --- /dev/null +++ b/Behavioral/Visitor/multimethods.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +using namespace std; + +struct GameObject; +void collide(GameObject& first, GameObject& second); + +struct GameObject +{ + virtual ~GameObject() = default; + virtual type_index type() const = 0; + + virtual void collide(GameObject& other) { ::collide(*this, other); } +}; + +template struct GameObjectImpl : GameObject +{ + type_index type() const override + { + return typeid(T); + } +}; + +struct Planet : GameObjectImpl {}; +struct Asteroid : GameObjectImpl {}; +struct Spaceship : GameObjectImpl {}; +struct ArmedSpaceship : Spaceship +{ + type_index type() const override { + return typeid(ArmedSpaceship); // required for collision to function + } +}; // model limitation + +void spaceship_planet() { cout << "spaceship lands on planet\n"; } +void asteroid_planet() { cout << "asteroid burns up in atmosphere\n"; } +void asteroid_spaceship() { cout << "asteroid hits and destroys spaceship\n"; } +void asteroid_armed_spaceship() { cout << "spaceship shoots asteroid\n"; } + +map, void(*)(void)> outcomes{ + {{typeid(Spaceship), typeid(Planet)}, spaceship_planet}, + {{typeid(Asteroid),typeid(Planet)}, asteroid_planet}, + {{typeid(Asteroid),typeid(Spaceship)}, asteroid_spaceship}, + {{typeid(Asteroid), typeid(ArmedSpaceship)}, asteroid_armed_spaceship} +}; + +void collide(GameObject& first, GameObject& second) +{ + auto it = outcomes.find({ first.type(), second.type() }); + if (it == outcomes.end()) + { + it = outcomes.find({ second.type(), first.type() }); + if (it == outcomes.end()) + { + cout << "objects pass each other harmlessly\n"; + return; + } + } + it->second(); +} + +int main__(int argc, char* argv[]) +{ + ArmedSpaceship spaceship; + Asteroid asteroid; + Planet planet; + + collide(planet, spaceship); + collide(planet, asteroid); + collide(spaceship, asteroid); + collide(planet, planet); + + cout << "Member collision:\n"; + planet.collide(asteroid); + + // but this won't work + spaceship.collide(planet); + + getchar(); + return 0; +} diff --git a/Behavioral/Visitor/single_double.cpp b/Behavioral/Visitor/single_double.cpp new file mode 100644 index 0000000..5421f71 --- /dev/null +++ b/Behavioral/Visitor/single_double.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +#include "visitor.hpp" +#include "model.hpp" + +struct HtmlVisitor : Visitor +{ + void visit(const Paragraph& p) override + { + oss << "

    " << p.text << "

    \n"; + } + + void visit(const ListItem& li) override + { + oss << "
  • " << li.text << "
  • \n"; + } + + void visit(const List& l) override + { + oss << "
      \n"; + for_each(l.begin(), l.end(), [&](const ListItem& li) + { + // only acceptable if we know that li is a ListItem + this->visit(li); + + // if li was an Element, we would do + //li.accept(*this); + }); + oss << "
    \n"; + } + + string str() const override + { + return oss.str(); + } + +private: + ostringstream oss; +}; + +struct MarkdownVisitor : Visitor +{ + // dynamic_cast ifs + void visit(const Element& e) + { + if (const Paragraph* p = dynamic_cast(&e)) + { + visit(*p); + } else + { + // other cases + } + + } + + void visit(const Paragraph& p) override + { + oss << p.text << "\n"; + } + + void visit(const BoldParagraph& p) override + { + oss << "*" << p.text << "*\n"; + } + + void visit(const ListItem& li) override + { + oss << " * " << li.text << "\n"; + } + + void visit(const List& l) override + { + oss << "\n"; + for_each(l.begin(), l.end(), [&](const ListItem& li) { this->visit(li); }); + oss << "\n"; + } + + + void visit(const Div& div) override + { + oss << "
    \n"; + for (auto e : div) + { + //visit(*e); + e->accept(*this); + } + oss << "
    \n"; + } + + string str() const override + { + return oss.str(); + } + +private: + ostringstream oss; +}; + +// adding a new class requires total recompilation + +int main_(int argc, char* argv[]) +{ + BoldParagraph p{ "Here are some colors" }; + ListItem red{ "Red" }; + ListItem green{ "Green" }; + ListItem blue{ "Blue" }; + List colors{ red,green,blue }; + + // single dispatch needs 1 item of information: which element to render to text + // double dispatch needs 2 pieces of information: which element to render, and using which renderer + + vector document{ &p, &colors }; + cout << "Textual representation: " << endl; + + MarkdownVisitor v; + ostringstream oss; + //for_each(document.begin(), document.end(), [&](const Element* e) + //{ + // // v.visit(*e) won't work :), but... + // e->accept(v); + //}); + Div div{ &p, &colors }; + div.print_html(oss); + cout << oss.str() << endl; + + // everything is fine until we want another representation + + getchar(); + return 0; +} diff --git a/Behavioral/Visitor/std_visit.cpp b/Behavioral/Visitor/std_visit.cpp new file mode 100644 index 0000000..5208fde --- /dev/null +++ b/Behavioral/Visitor/std_visit.cpp @@ -0,0 +1,38 @@ +#include "Headers.hpp" + +struct AddressPrinter +{ + void operator()(const string& house_name) const { + cout << "A house called " << house_name << "\n"; + } + + void operator()(const int house_number) const { + cout << "House number " << house_number << "\n"; + } +}; + +int main(int ac, char* av[]) +{ + variant house; + //house = "Montefiore Castle"; + house = 221; + + AddressPrinter ap; + std::visit(ap, house); + + // what if you want to create a visitor in-place? + std::visit([](auto& arg) { + using T = decay_t; + + if constexpr (is_same_v) + { + cout << "A house called " << arg.c_str() << "\n"; + } + else + { + cout << "House number " << arg << "\n"; + } + }, house); + + return 0; +} \ No newline at end of file diff --git a/Behavioral/Visitor/visitor.cpp b/Behavioral/Visitor/visitor.cpp new file mode 100644 index 0000000..06101ac --- /dev/null +++ b/Behavioral/Visitor/visitor.cpp @@ -0,0 +1,150 @@ +#include +#include +#include +#include +using namespace std; +#include +#include +using namespace boost; + +struct Literal; +struct Addition; + +struct ExpressionVisitor +{ + virtual void visit(const Literal& lit) = 0; + virtual void visit(const Addition& add) = 0; +}; + +struct PrintVisitor : ExpressionVisitor +{ + void visit(const Literal& lit) override; + void visit(const Addition& addition) override; + + string str() const + { + return oss.str(); + } +private: + ostringstream oss; +}; + +struct Expression +{ + virtual ~Expression() + { + } + + virtual void print(ostringstream& oss) = 0; + virtual void accept(PrintVisitor& pv) = 0; +}; + +struct Literal : Expression +{ + void print(ostringstream& oss) override + { + oss << lexical_cast(value); + } + + explicit Literal(double value) + : value{value} + { + } + + void accept(PrintVisitor& pv) override + { + pv.visit(*this); + } + + double value; +}; + +struct Addition : Expression +{ + std::shared_ptr left, right; + + + Addition(const std::shared_ptr& left, const std::shared_ptr& right) + : left{left}, + right{right} + { + } + + void accept(PrintVisitor& pv) override + { + pv.visit(*this); + } + + void print(ostringstream& oss) override + { + oss << "("; + left->print(oss); + oss << " + "; + right->print(oss); + oss << ")"; + } +}; + +void PrintVisitor::visit(const Literal& literal) +{ + this->oss << literal.value; +} + +void PrintVisitor::visit(const Addition& addition) +{ + this->oss << "("; + addition.left->accept(*this); + this->oss << " + "; + addition.right->accept(*this); + this->oss << ")"; +} + +// dispatch - single, double, multiple + +// acyclic visitors + +// loki multimethods and https://ideone.com/8VxALs + +// https://github.com/Flast/multimethod +// also one of the answers here http://stackoverflow.com/questions/23336586/did-the-loki-multimethods-make-it-into-c11 + +std::shared_ptr lit(double value) +{ + return make_shared(value); +} + +std::shared_ptr add( + const std::shared_ptr& left, + const std::shared_ptr& right) +{ + return make_shared(left, right); +} + +void double_dispatch() +{ + PrintVisitor pv; + auto expr = add(add(lit(1), lit(2)), lit(3)); + pv.visit(*expr); + cout << pv.str() << endl; +} + +void dynamic_visitor() +{ + +} + +void static_visitor() +{ + ostringstream oss; // visitor + add(add(lit(1), lit(2)), lit(3))->print(oss); + cout << oss.str() << endl; +} + +int main_() +{ + static_visitor(); + double_dispatch(); + + getchar(); + return 0; +} diff --git a/Behavioral/Visitor/visitor.hpp b/Behavioral/Visitor/visitor.hpp new file mode 100644 index 0000000..557ac1c --- /dev/null +++ b/Behavioral/Visitor/visitor.hpp @@ -0,0 +1,24 @@ +#pragma once +#include + +struct Paragraph; +struct BoldParagraph; +struct ListItem; +struct List; +struct Div; + +struct Visitor +{ + virtual ~Visitor() = default; + + virtual void visit(const Paragraph& p) = 0; + virtual void visit(const BoldParagraph& p) = 0; + virtual void visit(const ListItem& li) = 0; + // here is the problem + virtual void visit(const List& l) = 0; + virtual void visit(const Div& div) = 0; + + // need to add another visit function whenever a new type is added + + virtual std::string str() const = 0; +}; diff --git a/Behavioral/Visitor/visitor_acyclic.cpp b/Behavioral/Visitor/visitor_acyclic.cpp new file mode 100644 index 0000000..9ab5f7e --- /dev/null +++ b/Behavioral/Visitor/visitor_acyclic.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +using namespace std; + +// cyclic visitor: based on function overloading +// works only on a stable hierarchy +// acyclic visitor: based on RTTI +// no hierarchy limitations, but slower + +template +struct Visitor +{ + virtual void visit(Visitable& obj) = 0; +}; + +struct VisitorBase // marker interface +{ + virtual ~VisitorBase() = default; +}; + +struct Expression +{ + virtual ~Expression() = default; + + virtual void accept(VisitorBase& obj) + { + using EV = Visitor; + if (auto ev = dynamic_cast(&obj)) + ev->visit(*this); + } +}; + +struct DoubleExpression : Expression{ + double value; + + DoubleExpression(double value) : value(value) {} + + virtual void accept(VisitorBase& obj) + { + using DEV = Visitor; + if (auto ev = dynamic_cast(&obj)) + ev->visit(*this); + } +}; + +struct AdditionExpression : Expression +{ + Expression *left, *right; + + AdditionExpression(Expression *left, Expression *right) : left(left), right(right) {} + + ~AdditionExpression() + { + delete left; + delete right; + } + + virtual void accept(VisitorBase& obj) + { + using AEV = Visitor; + if (auto ev = dynamic_cast(&obj)) + ev->visit(*this); + } +}; + +struct ExpressionPrinter : VisitorBase, + Visitor, + //Visitor, + Visitor +{ + void visit(Expression &obj) override + { + // fallback? + } + + // can remove double visitor without failure +// void visit(DoubleExpression &obj) override +// { +// oss << obj.value; +// } + + void visit(AdditionExpression &obj) override + { + oss << "("; + obj.left->accept(*this); + oss << "+"; + obj.right->accept(*this); + oss << ")"; + } + + string str() const { return oss.str(); } +private: + ostringstream oss; +}; + +int main() +{ + auto e = new AdditionExpression{ + new DoubleExpression{1}, + new AdditionExpression{ + new DoubleExpression{2}, + new DoubleExpression{3} + } + }; + + ExpressionPrinter ep; + ep.visit(*e); + cout << ep.str() << "\n"; + + //getchar(); + return 0; +} diff --git a/Behavioral/Visitor/visitor_double.cpp b/Behavioral/Visitor/visitor_double.cpp new file mode 100644 index 0000000..e755840 --- /dev/null +++ b/Behavioral/Visitor/visitor_double.cpp @@ -0,0 +1,152 @@ +// visitor examples for design patterns c++ book +#include +#include +#include +using namespace std; + +struct SubtractionExpression; +struct DoubleExpression; +struct AdditionExpression; + +struct ExpressionVisitor +{ + virtual void visit(DoubleExpression* de) = 0; + virtual void visit(AdditionExpression* ae) = 0; + virtual void visit(SubtractionExpression* se) = 0; +}; + +struct ExpressionPrinter : ExpressionVisitor +{ + ostringstream oss; + string str() const { return oss.str(); } + void visit(DoubleExpression* de) override; + void visit(AdditionExpression* ae) override; + void visit(SubtractionExpression* se) override; +}; + +struct ExpressionEvaluator : ExpressionVisitor +{ + double result; + void visit(DoubleExpression* de) override; + void visit(AdditionExpression* ae) override; + void visit(SubtractionExpression* se) override; +}; + +struct Expression +{ + virtual void accept(ExpressionVisitor* visitor) = 0; +}; + +struct DoubleExpression : Expression +{ + double value; + explicit DoubleExpression(const double value) + : value{ value } {} + + void accept(ExpressionVisitor* visitor) override + { + visitor->visit(this); + } +}; + +struct AdditionExpression : Expression +{ + Expression *left, *right; + + AdditionExpression(Expression* const left, Expression* const right) + : left{ left }, right{ right } {} + + ~AdditionExpression() + { + delete left; + delete right; + } + + void accept(ExpressionVisitor* visitor) override + { + visitor->visit(this); + } +}; + +struct SubtractionExpression : Expression +{ + Expression *left, *right; + + SubtractionExpression(Expression* const left, Expression* const right) + : left{ left }, right{ right } {} + + ~SubtractionExpression() + { + delete left; + delete right; + } + + void accept(ExpressionVisitor* visitor) override + { + visitor->visit(this); + } +}; + +void ExpressionPrinter::visit(DoubleExpression* de) +{ + oss << de->value; +} + +void ExpressionPrinter::visit(AdditionExpression* e) +{ + bool need_braces = dynamic_cast(e->right); + e->left->accept(this); + oss << "-"; + if (need_braces) oss << "("; + e->right->accept(this); + if (need_braces) oss << ")"; +} + +void ExpressionPrinter::visit(SubtractionExpression* se) +{ + bool need_braces = dynamic_cast(se->right); + if (need_braces) oss << "("; + se->left->accept(this); + oss << "-"; + se->right->accept(this); + if (need_braces) oss << ")"; +} + +void ExpressionEvaluator::visit(DoubleExpression* de) +{ + result = de->value; +} + +void ExpressionEvaluator::visit(AdditionExpression* ae) +{ + ae->left->accept(this); + auto temp = result; + ae->right->accept(this); + result += temp; +} + +void ExpressionEvaluator::visit(SubtractionExpression* se) +{ + se->left->accept(this); + auto temp = result; + se->right->accept(this); + result = temp - result; +} + +void main() +{ + auto e = new AdditionExpression{ + new DoubleExpression{ 1 }, + new SubtractionExpression { + new DoubleExpression{ 2 }, + new DoubleExpression{ 3 } + } + }; + ostringstream oss; + ExpressionPrinter printer; + ExpressionEvaluator evaluator; + printer.visit(e); + evaluator.visit(e); + cout << printer.str() << " = " << evaluator.result << endl; + getchar(); +} diff --git a/Behavioral/Visitor/visitor_intrusive.cpp b/Behavioral/Visitor/visitor_intrusive.cpp new file mode 100644 index 0000000..edcb946 --- /dev/null +++ b/Behavioral/Visitor/visitor_intrusive.cpp @@ -0,0 +1,59 @@ +// visitor examples for design patterns c++ book +#include +#include +#include +using namespace std; + +struct Expression +{ + virtual void print(ostringstream& oss) = 0; +}; + +struct DoubleExpression : Expression +{ + double value; + explicit DoubleExpression(const double value) + : value{value} {} + + void print(ostringstream& oss) override + { + oss << value; + } +}; + +struct AdditionExpression : Expression +{ + Expression *left, *right; + + AdditionExpression(Expression* const left, Expression* const right) + : left{left}, right{right} {} + + ~AdditionExpression() + { + delete left; + delete right; + } + + void print(ostringstream& oss) override + { + oss << "("; + left->print(oss); + oss << "+"; + right->print(oss); + oss << ")"; + } +}; + +void main_2_() +{ + auto e = new AdditionExpression{ + new DoubleExpression{1}, + new AdditionExpression{ + new DoubleExpression{2}, + new DoubleExpression{3} + } + }; + ostringstream oss; + e->print(oss); + cout << oss.str() << endl; +} \ No newline at end of file diff --git a/Behavioral/Visitor/visitor_reflective.cpp b/Behavioral/Visitor/visitor_reflective.cpp new file mode 100644 index 0000000..f08660d --- /dev/null +++ b/Behavioral/Visitor/visitor_reflective.cpp @@ -0,0 +1,82 @@ +// visitor examples for design patterns c++ book +#include +#include +#include +using namespace std; + +struct Expression +{ + virtual ~Expression() = default; +}; + +struct DoubleExpression : Expression +{ + double value; + explicit DoubleExpression(const double value) + : value{ value } {} +}; + +struct AdditionExpression : Expression +{ + Expression *left, *right; + + AdditionExpression(Expression* const left, Expression* const right) + : left{ left }, right{ right } {} + + ~AdditionExpression() + { + delete left; + delete right; + } +}; + +struct ExpressionPrinter +{ + /*void print(DoubleExpression *de, ostringstream& oss) const + { + oss << de->value; + } + void print(AdditionExpression *ae, ostringstream& oss) const + { + oss << "("; + print(ae->left, oss); + oss << "+"; + print(ae->right, oss); + oss << ")"; + }*/ + ostringstream oss; + + void print(Expression *e) + { + if (auto de = dynamic_cast(e)) + { + oss << de->value; + } + else if (auto ae = dynamic_cast(e)) + { + oss << "("; + print(ae->left); + oss << "+"; + print(ae->right); + oss << ")"; + } + } + + string str() const { return oss.str(); } +}; + +void main_3_() +{ + auto e = new AdditionExpression{ + new DoubleExpression{ 1 }, + new AdditionExpression{ + new DoubleExpression{ 2 }, + new DoubleExpression{ 3 } + } + }; + ostringstream oss; + //e->print(oss); + ExpressionPrinter ep; + ep.print(e); + cout << ep.str() << endl; +} \ No newline at end of file diff --git a/Contributing.md b/Contributing.md new file mode 100644 index 0000000..f6005ad --- /dev/null +++ b/Contributing.md @@ -0,0 +1,14 @@ +# Contributing to Apress Source Code + +Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. + +## How to Contribute + +1. Make sure you have a GitHub account. +2. Fork the repository for the relevant book. +3. Create a new branch on which to make your change, e.g. +`git checkout -b my_code_contribution` +4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. +5. Submit a pull request. + +Thank you for your contribution! \ No newline at end of file diff --git a/CppDesignPatterns.sln b/CppDesignPatterns.sln new file mode 100644 index 0000000..4b05a18 --- /dev/null +++ b/CppDesignPatterns.sln @@ -0,0 +1,330 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Creational", "Creational", "{8116FC38-D612-4434-AD65-098C874C25A1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral", "Behavioral", "{FF8ECCEC-7F3A-471B-A9D6-EF66497796E4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Structural", "Structural", "{0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChainOfResponsibility", "Behavioral\ChainOfResponsibility\ChainOfResponsibility.vcxproj", "{35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Command", "Behavioral\Command\Command.vcxproj", "{C5DCA564-9139-4274-BC7E-41A0311721B0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Interpreter", "Behavioral\Interpreter\Interpreter.vcxproj", "{1FB6D834-DFE3-404A-9619-AA0085611897}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Iterator", "Behavioral\Iterator\Iterator.vcxproj", "{ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mediator", "Behavioral\Mediator\Mediator.vcxproj", "{2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Memento", "Behavioral\Memento\Memento.vcxproj", "{0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NullObject", "Behavioral\NullObject\NullObject.vcxproj", "{D5F1806D-FE8A-4754-B8A0-334FF29272DA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Observer", "Behavioral\Observer\Observer.vcxproj", "{014C7C95-2A69-460B-8A91-AE0F67D65342}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "State", "Behavioral\State\State.vcxproj", "{84B29C64-523E-4C27-9FC6-017C0AC23FEC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Strategy", "Behavioral\Strategy\Strategy.vcxproj", "{76DDB609-2C93-41A2-BDED-5E0F2F81652B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TemplateMethod", "Behavioral\TemplateMethod\TemplateMethod.vcxproj", "{522A86A0-1065-4568-9329-9214081C7993}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Visitor", "Behavioral\Visitor\Visitor.vcxproj", "{AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Creational", "Creational\Creational\Creational.vcxproj", "{A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adapter", "Structural\Adapter\Adapter.vcxproj", "{3805785F-0030-4796-99B7-74C4083365B0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdapterVisual", "Structural\AdapterVisual\AdapterVisual.vcxproj", "{BF4C6045-746E-443C-93BB-DB2600BB14EA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bridge", "Structural\Bridge\Bridge.vcxproj", "{2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Composite", "Structural\Composite\Composite.vcxproj", "{B6DD38AF-AE6D-473D-9173-53C3D5938F0A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Decorator", "Structural\Decorator\Decorator.vcxproj", "{15566160-208E-407D-99DC-CB9A205D3C68}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Façade", "Structural\Façade\Façade.vcxproj", "{1B05BD32-32B7-46C6-8589-4723DB7B769E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Flyweight", "Structural\Flyweight\Flyweight.vcxproj", "{7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NullObject", "Structural\NullObject\NullObject.vcxproj", "{FDA83BF3-E510-4683-9868-E82ED21E802F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PingPongService", "Structural\PingPongService\PingPongService.csproj", "{CE4D9FC1-C908-4DED-9BC7-3905008FB61F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proxy", "Structural\Proxy\Proxy.vcxproj", "{34753A5F-F429-4715-B2CF-07939AD2EFD2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x64.ActiveCfg = Debug|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x64.Build.0 = Debug|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x86.ActiveCfg = Debug|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Debug|x86.Build.0 = Debug|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|Any CPU.ActiveCfg = Release|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x64.ActiveCfg = Release|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x64.Build.0 = Release|x64 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x86.ActiveCfg = Release|Win32 + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9}.Release|x86.Build.0 = Release|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x64.ActiveCfg = Debug|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x64.Build.0 = Debug|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x86.ActiveCfg = Debug|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Debug|x86.Build.0 = Debug|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|Any CPU.ActiveCfg = Release|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x64.ActiveCfg = Release|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x64.Build.0 = Release|x64 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x86.ActiveCfg = Release|Win32 + {C5DCA564-9139-4274-BC7E-41A0311721B0}.Release|x86.Build.0 = Release|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x64.ActiveCfg = Debug|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x64.Build.0 = Debug|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x86.ActiveCfg = Debug|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Debug|x86.Build.0 = Debug|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|Any CPU.ActiveCfg = Release|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x64.ActiveCfg = Release|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x64.Build.0 = Release|x64 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x86.ActiveCfg = Release|Win32 + {1FB6D834-DFE3-404A-9619-AA0085611897}.Release|x86.Build.0 = Release|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x64.ActiveCfg = Debug|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x64.Build.0 = Debug|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x86.ActiveCfg = Debug|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Debug|x86.Build.0 = Debug|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|Any CPU.ActiveCfg = Release|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x64.ActiveCfg = Release|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x64.Build.0 = Release|x64 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x86.ActiveCfg = Release|Win32 + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3}.Release|x86.Build.0 = Release|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x64.ActiveCfg = Debug|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x64.Build.0 = Debug|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x86.ActiveCfg = Debug|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Debug|x86.Build.0 = Debug|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|Any CPU.ActiveCfg = Release|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x64.ActiveCfg = Release|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x64.Build.0 = Release|x64 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x86.ActiveCfg = Release|Win32 + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16}.Release|x86.Build.0 = Release|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x64.ActiveCfg = Debug|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x64.Build.0 = Debug|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x86.ActiveCfg = Debug|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Debug|x86.Build.0 = Debug|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|Any CPU.ActiveCfg = Release|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x64.ActiveCfg = Release|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x64.Build.0 = Release|x64 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x86.ActiveCfg = Release|Win32 + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA}.Release|x86.Build.0 = Release|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x64.ActiveCfg = Debug|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x64.Build.0 = Debug|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x86.ActiveCfg = Debug|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Debug|x86.Build.0 = Debug|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|Any CPU.ActiveCfg = Release|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x64.ActiveCfg = Release|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x64.Build.0 = Release|x64 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x86.ActiveCfg = Release|Win32 + {D5F1806D-FE8A-4754-B8A0-334FF29272DA}.Release|x86.Build.0 = Release|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x64.ActiveCfg = Debug|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x64.Build.0 = Debug|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x86.ActiveCfg = Debug|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Debug|x86.Build.0 = Debug|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|Any CPU.ActiveCfg = Release|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x64.ActiveCfg = Release|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x64.Build.0 = Release|x64 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x86.ActiveCfg = Release|Win32 + {014C7C95-2A69-460B-8A91-AE0F67D65342}.Release|x86.Build.0 = Release|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x64.ActiveCfg = Debug|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x64.Build.0 = Debug|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x86.ActiveCfg = Debug|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Debug|x86.Build.0 = Debug|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|Any CPU.ActiveCfg = Release|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x64.ActiveCfg = Release|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x64.Build.0 = Release|x64 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x86.ActiveCfg = Release|Win32 + {84B29C64-523E-4C27-9FC6-017C0AC23FEC}.Release|x86.Build.0 = Release|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x64.ActiveCfg = Debug|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x64.Build.0 = Debug|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x86.ActiveCfg = Debug|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Debug|x86.Build.0 = Debug|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|Any CPU.ActiveCfg = Release|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x64.ActiveCfg = Release|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x64.Build.0 = Release|x64 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x86.ActiveCfg = Release|Win32 + {76DDB609-2C93-41A2-BDED-5E0F2F81652B}.Release|x86.Build.0 = Release|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x64.ActiveCfg = Debug|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x64.Build.0 = Debug|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x86.ActiveCfg = Debug|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Debug|x86.Build.0 = Debug|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Release|Any CPU.ActiveCfg = Release|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x64.ActiveCfg = Release|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x64.Build.0 = Release|x64 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x86.ActiveCfg = Release|Win32 + {522A86A0-1065-4568-9329-9214081C7993}.Release|x86.Build.0 = Release|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x64.ActiveCfg = Debug|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x64.Build.0 = Debug|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x86.ActiveCfg = Debug|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Debug|x86.Build.0 = Debug|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|Any CPU.ActiveCfg = Release|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x64.ActiveCfg = Release|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x64.Build.0 = Release|x64 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x86.ActiveCfg = Release|Win32 + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8}.Release|x86.Build.0 = Release|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x64.ActiveCfg = Debug|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x64.Build.0 = Debug|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x86.ActiveCfg = Debug|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x86.Build.0 = Debug|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|Any CPU.ActiveCfg = Release|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x64.ActiveCfg = Release|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x64.Build.0 = Release|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x86.ActiveCfg = Release|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x86.Build.0 = Release|Win32 + {3805785F-0030-4796-99B7-74C4083365B0}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {3805785F-0030-4796-99B7-74C4083365B0}.Debug|x64.ActiveCfg = Debug|x64 + {3805785F-0030-4796-99B7-74C4083365B0}.Debug|x64.Build.0 = Debug|x64 + {3805785F-0030-4796-99B7-74C4083365B0}.Debug|x86.ActiveCfg = Debug|Win32 + {3805785F-0030-4796-99B7-74C4083365B0}.Debug|x86.Build.0 = Debug|Win32 + {3805785F-0030-4796-99B7-74C4083365B0}.Release|Any CPU.ActiveCfg = Release|Win32 + {3805785F-0030-4796-99B7-74C4083365B0}.Release|x64.ActiveCfg = Release|x64 + {3805785F-0030-4796-99B7-74C4083365B0}.Release|x64.Build.0 = Release|x64 + {3805785F-0030-4796-99B7-74C4083365B0}.Release|x86.ActiveCfg = Release|Win32 + {3805785F-0030-4796-99B7-74C4083365B0}.Release|x86.Build.0 = Release|Win32 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Debug|x64.ActiveCfg = Debug|x64 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Debug|x64.Build.0 = Debug|x64 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Debug|x86.ActiveCfg = Debug|Win32 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Debug|x86.Build.0 = Debug|Win32 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Release|Any CPU.ActiveCfg = Release|Win32 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Release|x64.ActiveCfg = Release|x64 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Release|x64.Build.0 = Release|x64 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Release|x86.ActiveCfg = Release|Win32 + {BF4C6045-746E-443C-93BB-DB2600BB14EA}.Release|x86.Build.0 = Release|Win32 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Debug|x64.ActiveCfg = Debug|x64 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Debug|x64.Build.0 = Debug|x64 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Debug|x86.ActiveCfg = Debug|Win32 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Debug|x86.Build.0 = Debug|Win32 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Release|Any CPU.ActiveCfg = Release|Win32 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Release|x64.ActiveCfg = Release|x64 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Release|x64.Build.0 = Release|x64 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Release|x86.ActiveCfg = Release|Win32 + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3}.Release|x86.Build.0 = Release|Win32 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Debug|x64.ActiveCfg = Debug|x64 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Debug|x64.Build.0 = Debug|x64 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Debug|x86.ActiveCfg = Debug|Win32 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Debug|x86.Build.0 = Debug|Win32 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Release|Any CPU.ActiveCfg = Release|Win32 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Release|x64.ActiveCfg = Release|x64 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Release|x64.Build.0 = Release|x64 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Release|x86.ActiveCfg = Release|Win32 + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A}.Release|x86.Build.0 = Release|Win32 + {15566160-208E-407D-99DC-CB9A205D3C68}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {15566160-208E-407D-99DC-CB9A205D3C68}.Debug|x64.ActiveCfg = Debug|x64 + {15566160-208E-407D-99DC-CB9A205D3C68}.Debug|x64.Build.0 = Debug|x64 + {15566160-208E-407D-99DC-CB9A205D3C68}.Debug|x86.ActiveCfg = Debug|Win32 + {15566160-208E-407D-99DC-CB9A205D3C68}.Debug|x86.Build.0 = Debug|Win32 + {15566160-208E-407D-99DC-CB9A205D3C68}.Release|Any CPU.ActiveCfg = Release|Win32 + {15566160-208E-407D-99DC-CB9A205D3C68}.Release|x64.ActiveCfg = Release|x64 + {15566160-208E-407D-99DC-CB9A205D3C68}.Release|x64.Build.0 = Release|x64 + {15566160-208E-407D-99DC-CB9A205D3C68}.Release|x86.ActiveCfg = Release|Win32 + {15566160-208E-407D-99DC-CB9A205D3C68}.Release|x86.Build.0 = Release|Win32 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Debug|x64.ActiveCfg = Debug|x64 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Debug|x64.Build.0 = Debug|x64 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Debug|x86.ActiveCfg = Debug|Win32 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Debug|x86.Build.0 = Debug|Win32 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Release|Any CPU.ActiveCfg = Release|Win32 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Release|x64.ActiveCfg = Release|x64 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Release|x64.Build.0 = Release|x64 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Release|x86.ActiveCfg = Release|Win32 + {1B05BD32-32B7-46C6-8589-4723DB7B769E}.Release|x86.Build.0 = Release|Win32 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Debug|x64.ActiveCfg = Debug|x64 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Debug|x64.Build.0 = Debug|x64 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Debug|x86.ActiveCfg = Debug|Win32 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Debug|x86.Build.0 = Debug|Win32 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Release|Any CPU.ActiveCfg = Release|Win32 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Release|x64.ActiveCfg = Release|x64 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Release|x64.Build.0 = Release|x64 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Release|x86.ActiveCfg = Release|Win32 + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4}.Release|x86.Build.0 = Release|Win32 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Debug|x64.ActiveCfg = Debug|x64 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Debug|x64.Build.0 = Debug|x64 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Debug|x86.ActiveCfg = Debug|Win32 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Debug|x86.Build.0 = Debug|Win32 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Release|Any CPU.ActiveCfg = Release|Win32 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Release|x64.ActiveCfg = Release|x64 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Release|x64.Build.0 = Release|x64 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Release|x86.ActiveCfg = Release|Win32 + {FDA83BF3-E510-4683-9868-E82ED21E802F}.Release|x86.Build.0 = Release|Win32 + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Debug|x64.ActiveCfg = Debug|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Debug|x86.ActiveCfg = Debug|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Debug|x86.Build.0 = Debug|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Release|Any CPU.Build.0 = Release|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Release|x64.ActiveCfg = Release|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Release|x86.ActiveCfg = Release|Any CPU + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F}.Release|x86.Build.0 = Release|Any CPU + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Debug|x64.ActiveCfg = Debug|x64 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Debug|x64.Build.0 = Debug|x64 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Debug|x86.ActiveCfg = Debug|Win32 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Debug|x86.Build.0 = Debug|Win32 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Release|Any CPU.ActiveCfg = Release|Win32 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Release|x64.ActiveCfg = Release|x64 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Release|x64.Build.0 = Release|x64 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Release|x86.ActiveCfg = Release|Win32 + {34753A5F-F429-4715-B2CF-07939AD2EFD2}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {35D0B14E-D51F-43D4-8822-E1D5A3CD79D9} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {C5DCA564-9139-4274-BC7E-41A0311721B0} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {1FB6D834-DFE3-404A-9619-AA0085611897} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {ED969B3E-2698-4FC5-9268-ACCBB52A5DE3} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {2BA20722-68EB-4E4E-9FC9-7E2F0DE71D16} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {0271A4F8-851A-4380-9B3E-17DFC9DD5FCA} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {D5F1806D-FE8A-4754-B8A0-334FF29272DA} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {014C7C95-2A69-460B-8A91-AE0F67D65342} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {84B29C64-523E-4C27-9FC6-017C0AC23FEC} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {76DDB609-2C93-41A2-BDED-5E0F2F81652B} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {522A86A0-1065-4568-9329-9214081C7993} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {AE0150EE-8EDA-4C8A-8CD7-04AF0F6FADE8} = {FF8ECCEC-7F3A-471B-A9D6-EF66497796E4} + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F} = {8116FC38-D612-4434-AD65-098C874C25A1} + {3805785F-0030-4796-99B7-74C4083365B0} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {BF4C6045-746E-443C-93BB-DB2600BB14EA} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {2F2FE996-F50B-42F2-9CF8-EC5EEF438FB3} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {B6DD38AF-AE6D-473D-9173-53C3D5938F0A} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {15566160-208E-407D-99DC-CB9A205D3C68} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {1B05BD32-32B7-46C6-8589-4723DB7B769E} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {7E5A91AA-E39A-4BCC-9F71-A6B2DEBA32A4} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {FDA83BF3-E510-4683-9868-E82ED21E802F} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {CE4D9FC1-C908-4DED-9BC7-3905008FB61F} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + {34753A5F-F429-4715-B2CF-07939AD2EFD2} = {0F5F2471-05B6-4698-B9A5-FD29A3D1FFB4} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0766C411-200B-40DB-8388-69482998A9AC} + EndGlobalSection +EndGlobal diff --git a/Creational/Creational.sln b/Creational/Creational.sln new file mode 100644 index 0000000..a909133 --- /dev/null +++ b/Creational/Creational.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Creational", "Creational\Creational.vcxproj", "{A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x64.ActiveCfg = Debug|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x64.Build.0 = Debug|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x86.ActiveCfg = Debug|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Debug|x86.Build.0 = Debug|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x64.ActiveCfg = Release|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x64.Build.0 = Release|x64 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x86.ActiveCfg = Release|Win32 + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Creational/Creational.tss b/Creational/Creational.tss new file mode 100644 index 0000000..c8d4419 --- /dev/null +++ b/Creational/Creational.tss @@ -0,0 +1,11 @@ + + + + + C:\Dropbox\Courses\Pluralsight - C++ Design Patterns\Creational\Creational\Serialization.cpp + + + C:\Dropbox\Courses\Pluralsight - C++ Design Patterns\Creational\Creational\Prototype.cpp + + + \ No newline at end of file diff --git a/Creational/Creational/AbstractFactory.cpp b/Creational/Creational/AbstractFactory.cpp new file mode 100644 index 0000000..830e580 --- /dev/null +++ b/Creational/Creational/AbstractFactory.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include "HotDrink.h" +#include "DrinkFactory.h" +using namespace std; + +unique_ptr make_drink(string type) +{ + unique_ptr drink; + if (type == "tea") + { + drink = make_unique(); + drink->prepare(200); + } + else + { + drink = make_unique(); + drink->prepare(50); + } + return drink; +} + +int main53() +{ + auto d = make_drink("tea"); + + DrinkFactory df; + df.make_drink("coffee"); + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/BoostDI.cpp b/Creational/Creational/BoostDI.cpp new file mode 100644 index 0000000..d1fc746 --- /dev/null +++ b/Creational/Creational/BoostDI.cpp @@ -0,0 +1,77 @@ +#include "di.hpp" +#include +#include +#include + +using std::make_unique; +using std::make_shared; + +struct Engine +{ + float volume = 5; + int horse_power = 400; + + friend std::ostream& operator<<(std::ostream& os, const Engine& obj) + { + return os + << "volume: " << obj.volume + << " horse_power: " << obj.horse_power; + } +}; + +struct ILogger +{ + virtual ~ILogger() + { + } + + virtual void Log(const std::string& s) = 0; +}; + +struct ConsoleLogger : ILogger +{ + ConsoleLogger() + { + } + + void Log(const std::string& s) override + { + std::cout << "LOG:" << s.c_str() << std::endl; + } +}; + +struct Car +{ + std::unique_ptr engine; + std::shared_ptr logger; + + Car(std::unique_ptr engine, const std::shared_ptr& logger) + : engine{move(engine)}, + logger{logger} + { + logger->Log("making a car"); + } + + friend std::ostream& operator<<(std::ostream& os, const Car& obj) + { + return os << "car with engine: " << *obj.engine; + } +}; + +int main123() +{ + // manual + auto logger = make_shared(); + auto c = make_shared(make_unique(),logger); + + using namespace boost; + auto injector = di::make_injector( + di::bind().to() + ); + auto car = injector.create>(); + + std::cout << *car << std::endl; + + getchar(); + return 0; +} diff --git a/Creational/Creational/BoostDIDemo.hpp b/Creational/Creational/BoostDIDemo.hpp new file mode 100644 index 0000000..c065e8d --- /dev/null +++ b/Creational/Creational/BoostDIDemo.hpp @@ -0,0 +1,41 @@ +#include "di.hpp" +#include "headers.hpp" + + +struct IFoo +{ + virtual string name() = 0; +}; + +struct Foo : IFoo +{ + static int id; + Foo() { ++id; } + string name() override + { + return "foo "s + lexical_cast(id); + } +}; + +int Foo::id = 0; + +struct Bar +{ + std::shared_ptr foo; +}; + +int main() +{ + auto injector = di::make_injector( + di::bind().to().in(di::singleton) + ); + auto bar1 = injector.create>(); + auto bar2 = injector.create>(); + + cout << bar1->foo->name() << endl; + cout << bar2->foo->name() << endl; + + cout << boolalpha + << (bar1->foo.get() == bar2->foo.get()) + << endl; +} \ No newline at end of file diff --git a/Creational/Creational/Builder.cpp b/Creational/Creational/Builder.cpp new file mode 100644 index 0000000..c2a2bc7 --- /dev/null +++ b/Creational/Creational/Builder.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +using namespace std; + +struct HtmlBuilder; + +struct HtmlElement +{ + string name; + string text; + vector elements; + const size_t indent_size = 2; + + HtmlElement() {} + HtmlElement(const string& name, const string& text) + : name(name), + text(text) + { + } + + string str(int indent = 0) const + { + ostringstream oss; + string i(indent_size*indent, ' '); + oss << i << "<" << name << ">" << endl; + if (text.size() > 0) + oss << string(indent_size*(indent + 1), ' ') << text << endl; + + for (const auto& e : elements) + oss << e.str(indent + 1); + + oss << i << "" << endl; + return oss.str(); + } + + static unique_ptr build(string root_name) + { + return make_unique(root_name); + } +}; + +struct HtmlBuilder +{ + HtmlBuilder(string root_name) + { + root.name = root_name; + } + + // void to start with + HtmlBuilder& add_child(string child_name, string child_text) + { + HtmlElement e{ child_name, child_text }; + root.elements.emplace_back(e); + return *this; + } + + // pointer based + HtmlBuilder* add_child_2(string child_name, string child_text) + { + HtmlElement e{ child_name, child_text }; + root.elements.emplace_back(e); + return this; + } + + string str() { return root.str(); } + + operator HtmlElement() const { return root; } + HtmlElement root; +}; + +int demo() +{ + //

    hello

    + auto text = "hello"; + string output; + output += "

    "; + output += text; + output += "

    "; + printf("

    %s

    ", text); + + //
    • hello
    • world
    + string words[] = { "hello", "world" }; + ostringstream oss; + oss << "
      "; + for (auto w : words) + oss << "
    • " << w << "
    • "; + oss << "
    "; + printf(oss.str().c_str()); + + // easier + HtmlBuilder builder{ "ul" }; + builder.add_child("li", "hello").add_child("li", "world"); + cout << builder.str() << endl; + + + auto builder2 = HtmlElement::build("ul") + ->add_child_2("li", "hello")->add_child_2("li", "world"); + cout << builder2 << endl; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/BuilderCodingExercise.cpp b/Creational/Creational/BuilderCodingExercise.cpp new file mode 100644 index 0000000..cc0e162 --- /dev/null +++ b/Creational/Creational/BuilderCodingExercise.cpp @@ -0,0 +1,130 @@ +#include +#include +#include +using namespace std; + +struct Field +{ + string name, type; + + Field(const string& name, const string& type) + : name{name}, + type{type} + { + } + + + friend ostream& operator<<(ostream& os, const Field& obj) + { + return os << obj.type << " " << obj.name << ";"; + } +}; + +struct Class +{ + string name; + vector fields; + + friend ostream& operator<<(ostream& os, const Class& obj) + { + os << "class " << obj.name << "\n{\n"; + for (auto&& field : obj.fields) + { + os << " " << field << "\n"; + } + return os << "};\n"; + } +}; + +class CodeBuilder +{ + Class the_class; +public: + CodeBuilder(const string& class_name) + { + the_class.name = class_name; + } + + CodeBuilder& add_field(const string& name, const string& type) + { + the_class.fields.emplace_back(Field{ name, type }); + return *this; + } + + friend ostream& operator<<(ostream& os, const CodeBuilder& obj) + { + return os << obj.the_class; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + +#include +#include +#include +#include + +// trim from start (in place) +static inline void ltrim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { + return !std::isspace(ch); + })); +} + +// trim from end (in place) +static inline void rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { + return !std::isspace(ch); + }).base(), s.end()); +} + +// trim from both ends (in place) +static inline void trim(std::string &s) { + ltrim(s); + rtrim(s); +} + +// trim from start (copying) +static inline std::string ltrim_copy(std::string s) { + ltrim(s); + return s; +} + +// trim from end (copying) +static inline std::string rtrim_copy(std::string s) { + rtrim(s); + return s; +} + +namespace +{ + class Evaluate : public testing::Test + { + }; + + TEST_F(Evaluate, EmptyTest) + { + CodeBuilder cb{ "Foo" }; + ostringstream oss; + oss << cb; + auto printed = oss.str(); + trim(printed); + ASSERT_EQ("class Foo\n{\n};", printed); + } + + TEST_F(Evaluate, PersonTest) + { + auto cb = CodeBuilder{ "Person" } + .add_field("name", "string") + .add_field("age", "int"); + ostringstream oss; + oss << cb; + auto printed = oss.str(); + trim(printed); + ASSERT_EQ("class Person\n{\n string name;\n int age;\n};", printed); + } +} // namespace \ No newline at end of file diff --git a/Creational/Creational/CoffeeFactory.h b/Creational/Creational/CoffeeFactory.h new file mode 100644 index 0000000..6d60f2d --- /dev/null +++ b/Creational/Creational/CoffeeFactory.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include "HotDrink.h" +#include "HotDrinkFactory.h" + +struct HotDrink; + +struct CoffeeFactory : HotDrinkFactory +{ + unique_ptr make() const override + { + return make_unique(); + } +}; \ No newline at end of file diff --git a/Creational/Creational/CompositeBuilderClassDiagram.mdj b/Creational/Creational/CompositeBuilderClassDiagram.mdj new file mode 100644 index 0000000..55aa81e --- /dev/null +++ b/Creational/Creational/CompositeBuilderClassDiagram.mdj @@ -0,0 +1,2927 @@ +{ + "_type": "Project", + "_id": "AAAAAAFF+h6SjaM2Hec=", + "name": "Untitled", + "ownedElements": [ + { + "_type": "UMLModel", + "_id": "AAAAAAFF+qBWK6M3Z8Y=", + "_parent": { + "$ref": "AAAAAAFF+h6SjaM2Hec=" + }, + "name": "Model", + "ownedElements": [ + { + "_type": "UMLClassDiagram", + "_id": "AAAAAAFF+qBtyKM79qY=", + "_parent": { + "$ref": "AAAAAAFF+qBWK6M3Z8Y=" + }, + "name": "Main", + "visible": true, + "defaultDiagram": true, + "ownedViews": [ + { + "_type": "UMLClassView", + "_id": "AAAAAAFeir0ZwEu2aKk=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFeir0ZwEu3nzg=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "model": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFeir0ZwUu4+WY=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu3nzg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 0, + "top": -112, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeir0ZwUu59go=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu3nzg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 501, + "top": 399, + "width": 186.76708984375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "PersonBuilderBase", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeir0ZwUu6RVM=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu3nzg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 0, + "top": -112, + "width": 73.67724609375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from Model)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeir0ZwUu7jg0=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu3nzg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 0, + "top": -112, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 496, + "top": 392, + "width": 196.76708984375, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFeir0ZwUu4+WY=" + }, + "nameLabel": { + "$ref": "AAAAAAFeir0ZwUu59go=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFeir0ZwUu6RVM=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeir0ZwUu7jg0=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFeir0Zwku8gUE=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "model": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "subViews": [ + { + "_type": "UMLAttributeView", + "_id": "AAAAAAFeisE+60xjdQE=", + "_parent": { + "$ref": "AAAAAAFeir0Zwku8gUE=" + }, + "model": { + "$ref": "AAAAAAFeisE+lkxg5kw=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 501, + "top": 422, + "width": 186.76708984375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "#person: Person&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 496, + "top": 417, + "width": 196.76708984375, + "height": 23, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFeir0Zwku9KDw=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "model": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "subViews": [ + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeisYtG0yc2Yg=", + "_parent": { + "$ref": "AAAAAAFeir0Zwku9KDw=" + }, + "model": { + "$ref": "AAAAAAFeisYsvUyZ3AQ=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 501, + "top": 445, + "width": 186.76708984375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+lives(): PersonAddressBuilder", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeisZqkEylySY=", + "_parent": { + "$ref": "AAAAAAFeir0Zwku9KDw=" + }, + "model": { + "$ref": "AAAAAAFeisZqPUyihCs=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 501, + "top": 460, + "width": 186.76708984375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+works(): PersonAddressBuilder", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 496, + "top": 440, + "width": 196.76708984375, + "height": 38, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFeir0Zw0u+BsY=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "model": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 0, + "top": -56, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFeir0Zw0u/hj4=", + "_parent": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "model": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 0, + "top": -56, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 496, + "top": 392, + "width": 196.76708984375, + "height": 86, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFeir0ZwEu3nzg=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFeir0Zwku8gUE=" + }, + "operationCompartment": { + "$ref": "AAAAAAFeir0Zwku9KDw=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFeir0Zw0u+BsY=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFeir0Zw0u/hj4=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFeir3Ug0vgO5E=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFeir3UhEvh3W0=", + "_parent": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "model": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFeir3UhEviMeg=", + "_parent": { + "$ref": "AAAAAAFeir3UhEvh3W0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -208, + "top": -144, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeir3UhUvjfqU=", + "_parent": { + "$ref": "AAAAAAFeir3UhEvh3W0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 285, + "top": 551, + "width": 178.826171875, + "height": 13, + "autoResize": false, + "underline": false, + "text": "PersonBuilder", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeir3UhUvkzW8=", + "_parent": { + "$ref": "AAAAAAFeir3UhEvh3W0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -208, + "top": -144, + "width": 73.67724609375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from Model)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeir3UhUvlw14=", + "_parent": { + "$ref": "AAAAAAFeir3UhEvh3W0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -208, + "top": -144, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 280, + "top": 544, + "width": 188.826171875, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFeir3UhEviMeg=" + }, + "nameLabel": { + "$ref": "AAAAAAFeir3UhUvjfqU=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFeir3UhUvkzW8=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeir3UhUvlw14=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFeir3UhkvmUeU=", + "_parent": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "model": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "subViews": [ + { + "_type": "UMLAttributeView", + "_id": "AAAAAAFeir/LDkww21I=", + "_parent": { + "$ref": "AAAAAAFeir3UhkvmUeU=" + }, + "model": { + "$ref": "AAAAAAFeir/KxEwt+JQ=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 285, + "top": 574, + "width": 178.826171875, + "height": 13, + "autoResize": false, + "underline": false, + "text": "#person: Person", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 280, + "top": 569, + "width": 188.826171875, + "height": 23, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFeir3UhkvnwT4=", + "_parent": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "model": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 280, + "top": 592, + "width": 188.826171875, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFeir3Uh0vogVM=", + "_parent": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "model": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -104, + "top": -72, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFeir3Uh0vpO1Q=", + "_parent": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "model": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -104, + "top": -72, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 280, + "top": 544, + "width": 188.826171875, + "height": 65, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFeir3UhEvh3W0=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFeir3UhkvmUeU=" + }, + "operationCompartment": { + "$ref": "AAAAAAFeir3UhkvnwT4=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFeir3Uh0vogVM=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFeir3Uh0vpO1Q=" + } + }, + { + "_type": "UMLGeneralizationView", + "_id": "AAAAAAFeir98a0wdKx4=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeir98akwbYa8=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeir98bEwe2t8=", + "_parent": { + "$ref": "AAAAAAFeir98a0wdKx4=" + }, + "model": { + "$ref": "AAAAAAFeir98akwbYa8=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 466, + "top": 491, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeir98a0wdKx4=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeir98bEwf04Q=", + "_parent": { + "$ref": "AAAAAAFeir98a0wdKx4=" + }, + "model": { + "$ref": "AAAAAAFeir98akwbYa8=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 458, + "top": 478, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFeir98a0wdKx4=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeir98bEwg/go=", + "_parent": { + "$ref": "AAAAAAFeir98a0wdKx4=" + }, + "model": { + "$ref": "AAAAAAFeir98akwbYa8=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 481, + "top": 516, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeir98a0wdKx4=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "tail": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "lineStyle": 1, + "points": "424:543;525:478", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFeir98bEwe2t8=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFeir98bEwf04Q=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeir98bEwg/go=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFeisC1dEw4bug=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFeisC1dUw5bUI=", + "_parent": { + "$ref": "AAAAAAFeisC1dEw4bug=" + }, + "model": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFeisC1dUw60u4=", + "_parent": { + "$ref": "AAAAAAFeisC1dUw5bUI=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -288, + "top": -96, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeisC1dUw7DKQ=", + "_parent": { + "$ref": "AAAAAAFeisC1dUw5bUI=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 493, + "top": 551, + "width": 244.6005859375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "PersonAddressBuilder", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeisC1dUw8gPQ=", + "_parent": { + "$ref": "AAAAAAFeisC1dUw5bUI=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -288, + "top": -96, + "width": 73.67724609375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from Model)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeisC1dUw9i/o=", + "_parent": { + "$ref": "AAAAAAFeisC1dUw5bUI=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -288, + "top": -96, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 488, + "top": 544, + "width": 254.6005859375, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFeisC1dUw60u4=" + }, + "nameLabel": { + "$ref": "AAAAAAFeisC1dUw7DKQ=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFeisC1dUw8gPQ=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeisC1dUw9i/o=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFeisC1dkw+g64=", + "_parent": { + "$ref": "AAAAAAFeisC1dEw4bug=" + }, + "model": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 488, + "top": 569, + "width": 254.6005859375, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFeisC1dkw/TfU=", + "_parent": { + "$ref": "AAAAAAFeisC1dEw4bug=" + }, + "model": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "subViews": [ + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeisl/zU0EXYI=", + "_parent": { + "$ref": "AAAAAAFeisC1dkw/TfU=" + }, + "model": { + "$ref": "AAAAAAFeisl/gE0BXYo=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 493, + "top": 584, + "width": 244.6005859375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+at(): PersonAddressBuilder&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeismMVE0Kt4Q=", + "_parent": { + "$ref": "AAAAAAFeisC1dkw/TfU=" + }, + "model": { + "$ref": "AAAAAAFeismMBE0HFwE=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 493, + "top": 599, + "width": 244.6005859375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+with_postcode(): PersonAddressBuilder&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeisma1k0Q1Ks=", + "_parent": { + "$ref": "AAAAAAFeisC1dkw/TfU=" + }, + "model": { + "$ref": "AAAAAAFeismahk0Nw7s=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 493, + "top": 614, + "width": 244.6005859375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+in(): PersonAddressBuilder&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 488, + "top": 579, + "width": 254.6005859375, + "height": 53, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFeisC1dkxAoYw=", + "_parent": { + "$ref": "AAAAAAFeisC1dEw4bug=" + }, + "model": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -144, + "top": -48, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFeisC1d0xBH8g=", + "_parent": { + "$ref": "AAAAAAFeisC1dEw4bug=" + }, + "model": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -144, + "top": -48, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 488, + "top": 544, + "width": 254.6005859375, + "height": 88, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFeisC1dUw5bUI=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFeisC1dkw+g64=" + }, + "operationCompartment": { + "$ref": "AAAAAAFeisC1dkw/TfU=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFeisC1dkxAoYw=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFeisC1d0xBH8g=" + } + }, + { + "_type": "UMLNoteView", + "_id": "AAAAAAFeisKNyExyYEE=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 152, + "top": 544, + "width": 105, + "height": 65, + "autoResize": false, + "text": "The object that's being built", + "wordWrap": true + }, + { + "_type": "UMLNoteLinkView", + "_id": "AAAAAAFeisLcBEx5spI=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "tail": { + "$ref": "AAAAAAFeisKNyExyYEE=" + }, + "lineStyle": 0, + "points": "256:576;280:576" + }, + { + "_type": "UMLNoteView", + "_id": "AAAAAAFeisS0zN1eUwA=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 288, + "top": 392, + "width": 105, + "height": 64, + "autoResize": false, + "text": "A reference to the object that's being built", + "wordWrap": true + }, + { + "_type": "UMLNoteLinkView", + "_id": "AAAAAAFeisVCDUyPCO8=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "tail": { + "$ref": "AAAAAAFeisS0zN1eUwA=" + }, + "lineStyle": 0, + "points": "392:424;496:424" + }, + { + "_type": "UMLGeneralizationView", + "_id": "AAAAAAFeishKvUyvJCw=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeishKvEytH/k=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeishKvkywAnc=", + "_parent": { + "$ref": "AAAAAAFeishKvUyvJCw=" + }, + "model": { + "$ref": "AAAAAAFeishKvEytH/k=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 578, + "top": 503, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeishKvUyvJCw=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeishKvkyx+i0=", + "_parent": { + "$ref": "AAAAAAFeishKvUyvJCw=" + }, + "model": { + "$ref": "AAAAAAFeishKvEytH/k=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 563, + "top": 503, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFeishKvUyvJCw=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeishKvkyyRrw=", + "_parent": { + "$ref": "AAAAAAFeishKvUyvJCw=" + }, + "model": { + "$ref": "AAAAAAFeishKvEytH/k=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 607, + "top": 504, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeishKvUyvJCw=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "tail": { + "$ref": "AAAAAAFeisC1dEw4bug=" + }, + "lineStyle": 0, + "points": "593:544;593:477", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFeishKvkywAnc=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFeishKvkyx+i0=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeishKvkyyRrw=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFeishrC0zAZkU=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFeishrDEzB9jY=", + "_parent": { + "$ref": "AAAAAAFeishrC0zAZkU=" + }, + "model": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFeishrDEzCYPk=", + "_parent": { + "$ref": "AAAAAAFeishrDEzB9jY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -96, + "top": -96, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeishrDUzDEf8=", + "_parent": { + "$ref": "AAAAAAFeishrDEzB9jY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 765, + "top": 551, + "width": 178.1279296875, + "height": 13, + "autoResize": false, + "underline": false, + "text": "PersonJobBuilder", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeishrDUzEpak=", + "_parent": { + "$ref": "AAAAAAFeishrDEzB9jY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -96, + "top": -96, + "width": 73.67724609375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from Model)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeishrDUzFqQ0=", + "_parent": { + "$ref": "AAAAAAFeishrDEzB9jY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -96, + "top": -96, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 760, + "top": 544, + "width": 188.1279296875, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFeishrDEzCYPk=" + }, + "nameLabel": { + "$ref": "AAAAAAFeishrDUzDEf8=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFeishrDUzEpak=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeishrDUzFqQ0=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFeishrDUzG1x0=", + "_parent": { + "$ref": "AAAAAAFeishrC0zAZkU=" + }, + "model": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 760, + "top": 569, + "width": 188.1279296875, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFeishrDUzHvB8=", + "_parent": { + "$ref": "AAAAAAFeishrC0zAZkU=" + }, + "model": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "subViews": [ + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeis02L01to7w=", + "_parent": { + "$ref": "AAAAAAFeishrDUzHvB8=" + }, + "model": { + "$ref": "AAAAAAFeis011U1qBq4=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 765, + "top": 584, + "width": 178.1279296875, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+at(): PersonJobBuilder&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeis1M3E1zD+U=", + "_parent": { + "$ref": "AAAAAAFeishrDUzHvB8=" + }, + "model": { + "$ref": "AAAAAAFeis1Mk01wKpc=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 765, + "top": 599, + "width": 178.1279296875, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+as_a(): PersonJobBuilder&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeis1eq0155Mo=", + "_parent": { + "$ref": "AAAAAAFeishrDUzHvB8=" + }, + "model": { + "$ref": "AAAAAAFeis1eZU12jKY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 765, + "top": 614, + "width": 178.1279296875, + "height": 13, + "autoResize": false, + "underline": false, + "text": "+earning(): PersonJobBuilder&", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 760, + "top": 579, + "width": 188.1279296875, + "height": 53, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFeishrDUzIHLk=", + "_parent": { + "$ref": "AAAAAAFeishrC0zAZkU=" + }, + "model": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -48, + "top": -48, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFeishrDkzJZY0=", + "_parent": { + "$ref": "AAAAAAFeishrC0zAZkU=" + }, + "model": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -48, + "top": -48, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 760, + "top": 544, + "width": 188.1279296875, + "height": 88, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFeishrDEzB9jY=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFeishrDUzG1x0=" + }, + "operationCompartment": { + "$ref": "AAAAAAFeishrDUzHvB8=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFeishrDUzIHLk=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFeishrDkzJZY0=" + } + }, + { + "_type": "UMLGeneralizationView", + "_id": "AAAAAAFeisjFWEzrVLM=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeisjFWEzpGDo=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeisjFWUzs37s=", + "_parent": { + "$ref": "AAAAAAFeisjFWEzrVLM=" + }, + "model": { + "$ref": "AAAAAAFeisjFWEzpGDo=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 715, + "top": 516, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeisjFWEzrVLM=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeisjFWUztung=", + "_parent": { + "$ref": "AAAAAAFeisjFWEzrVLM=" + }, + "model": { + "$ref": "AAAAAAFeisjFWEzpGDo=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 707, + "top": 529, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFeisjFWEzrVLM=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeisjFWUzuLdk=", + "_parent": { + "$ref": "AAAAAAFeisjFWEzrVLM=" + }, + "model": { + "$ref": "AAAAAAFeisjFWEzpGDo=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 730, + "top": 491, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeisjFWEzrVLM=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFeir0ZwEu2aKk=" + }, + "tail": { + "$ref": "AAAAAAFeishrC0zAZkU=" + }, + "lineStyle": 1, + "points": "778:543;668:478", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFeisjFWUzs37s=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFeisjFWUztung=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeisjFWUzuLdk=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFeissYr00eZVs=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFeissYr00f570=", + "_parent": { + "$ref": "AAAAAAFeissYr00eZVs=" + }, + "model": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFeissYsE0gVd8=", + "_parent": { + "$ref": "AAAAAAFeissYr00f570=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -128, + "top": -48, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeissYsE0hoxw=", + "_parent": { + "$ref": "AAAAAAFeissYr00f570=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 301, + "top": 671, + "width": 141.25439453125, + "height": 13, + "autoResize": false, + "underline": false, + "text": "Person", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeissYsE0iqY0=", + "_parent": { + "$ref": "AAAAAAFeissYr00f570=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -128, + "top": -48, + "width": 73.67724609375, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from Model)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFeissYsE0jhuc=", + "_parent": { + "$ref": "AAAAAAFeissYr00f570=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -128, + "top": -48, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 296, + "top": 664, + "width": 151.25439453125, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFeissYsE0gVd8=" + }, + "nameLabel": { + "$ref": "AAAAAAFeissYsE0hoxw=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFeissYsE0iqY0=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeissYsE0jhuc=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFeissYsE0kXc0=", + "_parent": { + "$ref": "AAAAAAFeissYr00eZVs=" + }, + "model": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 296, + "top": 689, + "width": 151.25439453125, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFeissYsU0li0o=", + "_parent": { + "$ref": "AAAAAAFeissYr00eZVs=" + }, + "model": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "subViews": [ + { + "_type": "UMLOperationView", + "_id": "AAAAAAFeist4H01J/LE=", + "_parent": { + "$ref": "AAAAAAFeissYsU0li0o=" + }, + "model": { + "$ref": "AAAAAAFeist31E1G/S0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 301, + "top": 704, + "width": 141.25439453125, + "height": 13, + "autoResize": false, + "underline": true, + "text": "+build(): PersonBuilder", + "horizontalAlignment": 0, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 296, + "top": 699, + "width": 151.25439453125, + "height": 23, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFeissYsU0mZzE=", + "_parent": { + "$ref": "AAAAAAFeissYr00eZVs=" + }, + "model": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -64, + "top": -24, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFeissYsU0n12c=", + "_parent": { + "$ref": "AAAAAAFeissYr00eZVs=" + }, + "model": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -64, + "top": -24, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 296, + "top": 664, + "width": 151.25439453125, + "height": 58, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFeissYr00f570=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFeissYsE0kXc0=" + }, + "operationCompartment": { + "$ref": "AAAAAAFeissYsU0li0o=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFeissYsU0mZzE=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFeissYsU0n12c=" + } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFeisyqS01WW6E=", + "_parent": { + "$ref": "AAAAAAFF+qBtyKM79qY=" + }, + "model": { + "$ref": "AAAAAAFeisyqSk1UeqA=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeisyqS01XpUk=", + "_parent": { + "$ref": "AAAAAAFeisyqS01WW6E=" + }, + "model": { + "$ref": "AAAAAAFeisyqSk1UeqA=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 357, + "top": 629, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeisyqS01WW6E=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeisyqTE1Y+TU=", + "_parent": { + "$ref": "AAAAAAFeisyqS01WW6E=" + }, + "model": { + "$ref": "AAAAAAFeisyqSk1UeqA=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 342, + "top": 629, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFeisyqS01WW6E=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFeisyqTE1ZTio=", + "_parent": { + "$ref": "AAAAAAFeisyqS01WW6E=" + }, + "model": { + "$ref": "AAAAAAFeisyqSk1UeqA=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 386, + "top": 630, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFeisyqS01WW6E=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFeir3Ug0vgO5E=" + }, + "tail": { + "$ref": "AAAAAAFeissYr00eZVs=" + }, + "lineStyle": 1, + "points": "372:663;372:609", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFeisyqS01XpUk=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFeisyqTE1Y+TU=" + }, + "propertyLabel": { + "$ref": "AAAAAAFeisyqTE1ZTio=" + } + } + ] + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFeir0ZvUu0cvA=", + "_parent": { + "$ref": "AAAAAAFF+qBWK6M3Z8Y=" + }, + "name": "PersonBuilderBase", + "visibility": "public", + "attributes": [ + { + "_type": "UMLAttribute", + "_id": "AAAAAAFeisE+lkxg5kw=", + "_parent": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "name": "person", + "visibility": "protected", + "isStatic": false, + "isLeaf": false, + "type": "Person&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "isDerived": false, + "aggregation": "none", + "isID": false + } + ], + "operations": [ + { + "_type": "UMLOperation", + "_id": "AAAAAAFeisYsvUyZ3AQ=", + "_parent": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "name": "lives", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeisZcDkygN8Q=", + "_parent": { + "$ref": "AAAAAAFeisYsvUyZ3AQ=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonAddressBuilder", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + }, + { + "_type": "UMLOperation", + "_id": "AAAAAAFeisZqPUyihCs=", + "_parent": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "name": "works", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeisaJ60ypTaE=", + "_parent": { + "$ref": "AAAAAAFeisZqPUyihCs=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + } + ], + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFeir3UgkveaFw=", + "_parent": { + "$ref": "AAAAAAFF+qBWK6M3Z8Y=" + }, + "name": "PersonBuilder", + "ownedElements": [ + { + "_type": "UMLGeneralization", + "_id": "AAAAAAFeir98akwbYa8=", + "_parent": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "source": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "target": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "visibility": "public" + } + ], + "visibility": "public", + "attributes": [ + { + "_type": "UMLAttribute", + "_id": "AAAAAAFeir/KxEwt+JQ=", + "_parent": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "name": "person", + "visibility": "protected", + "isStatic": false, + "isLeaf": false, + "type": "Person", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "isDerived": false, + "aggregation": "none", + "isID": false + } + ], + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFeisC1c0w2eWI=", + "_parent": { + "$ref": "AAAAAAFF+qBWK6M3Z8Y=" + }, + "name": "PersonAddressBuilder", + "ownedElements": [ + { + "_type": "UMLGeneralization", + "_id": "AAAAAAFeishKvEytH/k=", + "_parent": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "source": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "target": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "visibility": "public" + } + ], + "visibility": "public", + "operations": [ + { + "_type": "UMLOperation", + "_id": "AAAAAAFeisl/gE0BXYo=", + "_parent": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "name": "at", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeisoZnk0UZzM=", + "_parent": { + "$ref": "AAAAAAFeisl/gE0BXYo=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonAddressBuilder&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + }, + { + "_type": "UMLOperation", + "_id": "AAAAAAFeismMBE0HFwE=", + "_parent": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "name": "with_postcode", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeispHQk0XDzw=", + "_parent": { + "$ref": "AAAAAAFeismMBE0HFwE=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonAddressBuilder&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + }, + { + "_type": "UMLOperation", + "_id": "AAAAAAFeismahk0Nw7s=", + "_parent": { + "$ref": "AAAAAAFeisC1c0w2eWI=" + }, + "name": "in", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeispr6k0a5F8=", + "_parent": { + "$ref": "AAAAAAFeismahk0Nw7s=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonAddressBuilder&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + } + ], + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFeishrCUy+G9M=", + "_parent": { + "$ref": "AAAAAAFF+qBWK6M3Z8Y=" + }, + "name": "PersonJobBuilder", + "ownedElements": [ + { + "_type": "UMLGeneralization", + "_id": "AAAAAAFeisjFWEzpGDo=", + "_parent": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "source": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "target": { + "$ref": "AAAAAAFeir0ZvUu0cvA=" + }, + "visibility": "public" + } + ], + "visibility": "public", + "operations": [ + { + "_type": "UMLOperation", + "_id": "AAAAAAFeis011U1qBq4=", + "_parent": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "name": "at", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeis5lJU2F0Eo=", + "_parent": { + "$ref": "AAAAAAFeis011U1qBq4=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonJobBuilder&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + }, + { + "_type": "UMLOperation", + "_id": "AAAAAAFeis1Mk01wKpc=", + "_parent": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "name": "as_a", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeis6HV02IwB0=", + "_parent": { + "$ref": "AAAAAAFeis1Mk01wKpc=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonJobBuilder&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + }, + { + "_type": "UMLOperation", + "_id": "AAAAAAFeis1eZU12jKY=", + "_parent": { + "$ref": "AAAAAAFeishrCUy+G9M=" + }, + "name": "earning", + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeis6iJ02LF+E=", + "_parent": { + "$ref": "AAAAAAFeis1eZU12jKY=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": "PersonJobBuilder&", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + } + ], + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFeissYrk0cq0s=", + "_parent": { + "$ref": "AAAAAAFF+qBWK6M3Z8Y=" + }, + "name": "Person", + "ownedElements": [ + { + "_type": "UMLDependency", + "_id": "AAAAAAFeisyqSk1UeqA=", + "_parent": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "source": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "target": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "visibility": "public" + } + ], + "visibility": "public", + "operations": [ + { + "_type": "UMLOperation", + "_id": "AAAAAAFeist31E1G/S0=", + "_parent": { + "$ref": "AAAAAAFeissYrk0cq0s=" + }, + "name": "build", + "visibility": "public", + "isStatic": true, + "isLeaf": false, + "parameters": [ + { + "_type": "UMLParameter", + "_id": "AAAAAAFeisw6tE1RyoU=", + "_parent": { + "$ref": "AAAAAAFeist31E1G/S0=" + }, + "visibility": "public", + "isStatic": false, + "isLeaf": false, + "type": { + "$ref": "AAAAAAFeir3UgkveaFw=" + }, + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "direction": "return" + } + ], + "concurrency": "sequential", + "isQuery": false, + "isAbstract": false + } + ], + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + } + ], + "visibility": "public" + } + ] +} \ No newline at end of file diff --git a/Creational/Creational/Creational.vcxproj b/Creational/Creational/Creational.vcxproj new file mode 100644 index 0000000..9df7e02 --- /dev/null +++ b/Creational/Creational/Creational.vcxproj @@ -0,0 +1,193 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {A2EAA3EF-D92C-41AA-A184-08A58D77FF1F} + Creational + 10.0.15063.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + $(LibraryPath) + + + $(LibraryPath) + + + + Level3 + Disabled + true + c:\gtest\include;c:\boost;%(AdditionalIncludeDirectories) + + + true + gtest.lib;%(AdditionalDependencies) + c:\gtest;c:\boost\stage\lib32;%(AdditionalLibraryDirectories) + + + + + Level3 + Disabled + true + c:\boost;c:\gtest\include + MultiThreadedDebugDLL + stdcpplatest + + + true + c:\gtest\lib;%(AdditionalLibraryDirectories) + gtest.lib;%(AdditionalDependencies) + + + copy "$(ProjectDir)capitals.txt" "$(TargetDir)capitals.txt" + + + + + Level3 + MaxSpeed + true + true + true + c:\gtest\include;c:\boost;%(AdditionalIncludeDirectories) + + + true + true + true + + + + + Level3 + MaxSpeed + true + true + true + c:\boost;c:\gtest\include + stdcpplatest + + + true + true + true + c:\gtest\lib;%(AdditionalLibraryDirectories) + gtest.lib;%(AdditionalDependencies) + + + copy "$(ProjectDir)capitals.txt" "$(TargetDir)capitals.txt" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + + + + \ No newline at end of file diff --git a/Creational/Creational/Creational.vcxproj.filters b/Creational/Creational/Creational.vcxproj.filters new file mode 100644 index 0000000..c976255 --- /dev/null +++ b/Creational/Creational/Creational.vcxproj.filters @@ -0,0 +1,140 @@ + + + + + {2d659032-6c58-4dca-929d-01e249ece131} + + + {589d56ad-b11e-4ce6-b612-41e8788c22f5} + + + {7e011512-5f92-40a0-88e0-aea774642718} + + + {3c92b113-3d5b-47e1-9108-927d3d3e9967} + + + {87c92fc6-c33a-494b-953e-720ca5429836} + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {385b14eb-9a2e-4b23-b571-ef26ec7b3f68} + + + + + Builder + + + Factory + + + Factory + + + Builder\Facets + + + Builder\Facets + + + Builder + + + Builder\Facets + + + Factory\AbstractFactory + + + Factory + + + Prototype + + + Prototype + + + Singleton + + + Singleton + + + Preliminaries + + + Preliminaries + + + Preliminaries + + + Preliminaries + + + Preliminaries + + + Preliminaries + + + Singleton + + + Prototype + + + Singleton + + + Preliminaries + + + Builder + + + + + Builder\Facets + + + Builder\Facets + + + Builder\Facets + + + Builder\Facets + + + Factory\AbstractFactory + + + Factory\AbstractFactory + + + Factory\AbstractFactory + + + Factory\AbstractFactory + + + Factory\AbstractFactory + + + + + + Singleton + + + + Singleton + + + \ No newline at end of file diff --git a/Creational/Creational/Creational.vcxproj.user b/Creational/Creational/Creational.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/Creational/Creational/Creational.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Creational/Creational/DIP.cpp b/Creational/Creational/DIP.cpp new file mode 100644 index 0000000..dc7895f --- /dev/null +++ b/Creational/Creational/DIP.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +using namespace std; + +// A. High-level modules should not depend on low-level modules. +// Both should depend on abstractions. +// B. Abstractions should not depend on details. +// Details should depend on abstractions. + +enum class Relationship +{ + parent, + child, + sibling +}; + +struct Person +{ + string name; +}; + +struct RelationshipBrowser +{ + virtual vector find_all_children_of(const string& name) = 0; +}; + +struct Relationships : RelationshipBrowser // low-level +{ + vector> relations; + + void add_parent_and_child(const Person& parent, const Person& child) + { + relations.push_back({parent, Relationship::parent, child}); + relations.push_back({child, Relationship::child, parent}); + } + + vector find_all_children_of(const string &name) override + { + vector result; + for (auto&& [first, rel, second] : relations) + { + if (first.name == name && rel == Relationship::parent) + { + result.push_back(second); + } + } + return result; + } +}; + +struct Research // high-level +{ + Research(RelationshipBrowser& browser) + { + for (auto& child : browser.find_all_children_of("John")) + { + cout << "John has a child called " << child.name << endl; + } + } +// Research(const Relationships& relationships) +// { +// auto& relations = relationships.relations; +// for (auto&& [first, rel, second] : relations) +// { +// if (first.name == "John" && rel == Relationship::parent) +// { +// cout << "John has a child called " << second.name << endl; +// } +// } +// } +}; + +int main() +{ + Person parent{"John"}; + Person child1{"Chris"}; + Person child2{"Matt"}; + + Relationships relationships; + relationships.add_parent_and_child(parent, child1); + relationships.add_parent_and_child(parent, child2); + + Research _(relationships); + + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/DrinkFactory.h b/Creational/Creational/DrinkFactory.h new file mode 100644 index 0000000..66c44f4 --- /dev/null +++ b/Creational/Creational/DrinkFactory.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "HotDrink.h" +#include "TeaFactory.h" +#include "CoffeeFactory.h" +#include +#include + +struct HotDrink; + +class DrinkFactory +{ + map> hot_factories; +public: + DrinkFactory() + { + hot_factories["coffee"] = make_unique(); + hot_factories["tea"] = make_unique(); + } + + unique_ptr make_drink(const string& name) + { + auto drink = hot_factories[name]->make(); + drink->prepare(200); // oops! + return drink; + } +}; + +class DrinkWithVolumeFactory +{ + map()>> factories; +public: + + DrinkWithVolumeFactory() + { + factories["tea"] = [] { + auto tea = make_unique(); + tea->prepare(200); + return tea; + }; + } + + unique_ptr make_drink(const string& name); +}; + +inline unique_ptr DrinkWithVolumeFactory::make_drink(const string& name) +{ + return factories[name](); +} diff --git a/Creational/Creational/Facets.cpp b/Creational/Creational/Facets.cpp new file mode 100644 index 0000000..033322c --- /dev/null +++ b/Creational/Creational/Facets.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include "Person.h" +#include "PersonBuilder.h" +#include "PersonAddressBuilder.h" +#include "PersonJobBuilder.h" + +int main__() +{ + Person p = Person::create() + .lives().at("123 London Road").with_postcode("SW1 1GB").in("London") + .works().at("PragmaSoft").as_a("Consultant").earning(10e6); + + cout << p << endl; + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/Factory.cpp b/Creational/Creational/Factory.cpp new file mode 100644 index 0000000..5c6118c --- /dev/null +++ b/Creational/Creational/Factory.cpp @@ -0,0 +1,43 @@ +#include + +enum class PointType +{ + cartesian, + polar +}; + +class Point +{ + /*Point(float a, float b, PointType type = PointType::cartesian) + { + if (type == PointType::cartesian) + { + x = a; b = y; + } + else + { + x = a*cos(b); + y = a*sin(b); + } + }*/ + + // use a factory method + Point(float x, float y) : x(x), y(y){} +public: + float x, y; + + friend class PointFactory; +}; + +class PointFactory +{ + static Point NewCartesian(float x, float y) + { + return Point{ x,y }; + } + + static Point NewPolar(float r, float theta) + { + return Point{ r*cos(theta), r*sin(theta) }; + } +}; diff --git a/Creational/Creational/FactoryCodingExercise.cpp b/Creational/Creational/FactoryCodingExercise.cpp new file mode 100644 index 0000000..0562b44 --- /dev/null +++ b/Creational/Creational/FactoryCodingExercise.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +using namespace std; + +namespace FactoryExercise { + +struct Person +{ + int id; + string name; +}; + +class PersonFactory +{ + int id{ 0 }; +public: + Person create_person(const string& name) + { + return { id++, name }; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + + +namespace +{ + class Evaluate : public testing::Test + { + }; + + TEST_F(Evaluate, SimplePersonTest) + { + PersonFactory pf; + + auto p1 = pf.create_person("Chris"); + ASSERT_EQ("Chris", p1.name); + + auto p2 = pf.create_person("Sarah"); + ASSERT_EQ(1, p2.id) << "Expected the second created person's id to be = 1"; + } +} // namespace + +} + +int main(int ac, char* av[]) +{ + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Creational/Creational/FactoryExercise.h b/Creational/Creational/FactoryExercise.h new file mode 100644 index 0000000..14a2cc2 --- /dev/null +++ b/Creational/Creational/FactoryExercise.h @@ -0,0 +1,7 @@ +#pragma once + +class FactoryExercise +{ +public: + +}; diff --git a/Creational/Creational/FactoryMethod.cpp b/Creational/Creational/FactoryMethod.cpp new file mode 100644 index 0000000..2cf5275 --- /dev/null +++ b/Creational/Creational/FactoryMethod.cpp @@ -0,0 +1,64 @@ +#define _USE_MATH_DEFINES +#include +#include + +enum class PointType +{ + cartesian, + polar +}; + +class Point +{ + /*Point(float a, float b, PointType type = PointType::cartesian) + { + if (type == PointType::cartesian) + { + x = a; b = y; + } + else + { + x = a*cos(b); + y = a*sin(b); + } + }*/ + + + Point(const float x, const float y) + : x{x}, + y{y} + { + } + +public: + float x, y; + + + friend std::ostream& operator<<(std::ostream& os, const Point& obj) + { + return os + << "x: " << obj.x + << " y: " << obj.y; + } + + static Point NewCartesian(float x, float y) + { + return{ x,y }; + } + static Point NewPolar(float r, float theta) + { + return{ r*cos(theta), r*sin(theta) }; + } +}; + +int main_z() +{ + // will not work + //Point p{ 1,2 }; + + auto p = Point::NewPolar(5, M_PI_4); + std::cout << p << std::endl; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/GroovyStyle.cpp b/Creational/Creational/GroovyStyle.cpp new file mode 100644 index 0000000..e4367ec --- /dev/null +++ b/Creational/Creational/GroovyStyle.cpp @@ -0,0 +1,93 @@ +#include +#include +#include + +namespace html { + struct Tag + { + std::string name; + std::string text; + std::vector children; + std::vector> attributes; + + friend std::ostream& operator<<(std::ostream& os, const Tag& tag) + { + os << "<" << tag.name; + + for (const auto& att : tag.attributes) + os << " " << att.first << "=\"" << att.second << "\""; + + if (tag.children.size() == 0 && tag.text.length() == 0) + { + os << "/>" << std::endl; + } + else + { + os << ">" << std::endl; + + if (tag.text.length()) + os << tag.text << std::endl; + + for (const auto& child : tag.children) + os << child; + + os << "" << std::endl; + } + + return os; + } + protected: + + Tag(const std::string& name, const std::string& text) + : name{name}, + text{text} + { + } + + + Tag(const std::string& name, const std::vector& children) + : name{name}, + children{children} + { + } + }; + + struct P : Tag + { + explicit P(const std::string& text) + : Tag{"p", text} + { + } + + P(std::initializer_list children) + : Tag("p", children) + { + } + + }; + + struct IMG : Tag + { + explicit IMG(const std::string& url) + : Tag{"img", ""} + { + attributes.emplace_back(make_pair("src", url)); + } + }; +} + +int main1() +{ + using namespace html; + + std::cout << + + P { + IMG {"http://pokemon.com/pikachu.png"} + } + + << std::endl; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/HotDrink.h b/Creational/Creational/HotDrink.h new file mode 100644 index 0000000..df52642 --- /dev/null +++ b/Creational/Creational/HotDrink.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include +using namespace std; + +struct HotDrink +{ + virtual ~HotDrink() = default; + + virtual void prepare(int volume) = 0; +}; + +struct Tea : HotDrink +{ + + void prepare(int volume) override + { + cout << "Take tea bag, boil water, pour " << volume << "ml, add some lemon" << endl; + } +}; + +struct Coffee : HotDrink +{ + void prepare(int volume) override + { + cout << "Grind some beans, boil water, pour " << volume << "ml, add cream, enjoy!" << endl; + } +}; \ No newline at end of file diff --git a/Creational/Creational/HotDrinkFactory.h b/Creational/Creational/HotDrinkFactory.h new file mode 100644 index 0000000..00b108a --- /dev/null +++ b/Creational/Creational/HotDrinkFactory.h @@ -0,0 +1,7 @@ +#pragma once +#include "HotDrink.h" + +struct HotDrinkFactory +{ + virtual unique_ptr make() const = 0; +}; \ No newline at end of file diff --git a/Creational/Creational/ISP.cpp b/Creational/Creational/ISP.cpp new file mode 100644 index 0000000..13e3e62 --- /dev/null +++ b/Creational/Creational/ISP.cpp @@ -0,0 +1,64 @@ +#include +struct Document; + +//struct IMachine +//{ +// virtual void print(Document& doc) = 0; +// virtual void fax(Document& doc) = 0; +// virtual void scan(Document& doc) = 0; +//}; +// +//struct MFP : IMachine +//{ +// void print(Document& doc) override; +// void fax(Document& doc) override; +// void scan(Document& doc) override; +//}; + +// 1. Recompile +// 2. Client does not need this +// 3. Forcing implementors to implement too much + +struct IPrinter +{ + virtual void print(Document& doc) = 0; +}; + +struct IScanner +{ + virtual void scan(Document& doc) = 0; +}; + +struct Printer : IPrinter +{ + void print(Document& doc) override; +}; + +struct Scanner : IScanner +{ + void scan(Document& doc) override; +}; + +struct IMachine: IPrinter, IScanner +{ +}; + +struct Machine : IMachine +{ + IPrinter& printer; + IScanner& scanner; + + Machine(IPrinter& printer, IScanner& scanner) + : printer{printer}, + scanner{scanner} + { + } + + void print(Document& doc) override { + printer.print(doc); + } + void scan(Document& doc) override; +}; + +// IPrinter --> Printer +// everything --> Machine \ No newline at end of file diff --git a/Creational/Creational/InnerFactory.cpp b/Creational/Creational/InnerFactory.cpp new file mode 100644 index 0000000..1698b1e --- /dev/null +++ b/Creational/Creational/InnerFactory.cpp @@ -0,0 +1,61 @@ +#include + +// do not need this for factory +enum class PointType +{ + cartesian, + polar +}; + +class Point +{ + /*Point(float a, float b, PointType type = PointType::cartesian) + { + if (type == PointType::cartesian) + { + x = a; b = y; + } + else + { + x = a*cos(b); + y = a*sin(b); + } + }*/ + + // use a factory method + Point(float x, float y) : x(x), y(y) {} + + class PointFactory + { + PointFactory() {} + public: + static Point NewCartesian(float x, float y) + { + return { x,y }; + } + static Point NewPolar(float r, float theta) + { + return{ r*cos(theta), r*sin(theta) }; + } + }; +public: + float x, y; + static PointFactory Factory; +}; + +int main_2() +{ + // will not work + // Point p{ 1,2 }; + + // nope! + // Point::PointFactory pf; + + // if factory is public, then + //auto p = Point::PointFactory::NewCartesian(3, 4); + + // at any rate, use this + auto pp = Point::Factory.NewCartesian(2, 3); + + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/LSP.cpp b/Creational/Creational/LSP.cpp new file mode 100644 index 0000000..88160b8 --- /dev/null +++ b/Creational/Creational/LSP.cpp @@ -0,0 +1,59 @@ +// Objects in a program should be replaceable with instances of their subtypes +// w/o altering the correctness of the program + +#include + +class Rectangle +{ +protected: + int width, height; +public: + Rectangle(const int width, const int height) + : width{width}, height{height} { } + + int get_width() const { return width; } + virtual void set_width(const int width) { this->width = width; } + int get_height() const { return height; } + virtual void set_height(const int height) { this->height = height; } + + int area() const { return width * height; } +}; + +class Square : public Rectangle +{ +public: + Square(int size): Rectangle(size,size) {} + void set_width(const int width) override { + this->width = height = width; + } + void set_height(const int height) override { + this->height = width = height; + } +}; + +struct RectangleFactory +{ + static Rectangle create_rectangle(int w, int h); + static Rectangle create_square(int size); +}; + +void process(Rectangle& r) +{ + int w = r.get_width(); + r.set_height(10); + + std::cout << "expected area = " << (w * 10) + << ", got " << r.area() << std::endl; +} + +int main342342() +{ + Rectangle r{ 3, 4 }; + process(r); + + Square sq{ 5 }; + process(sq); + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/MaybeMonad.cpp b/Creational/Creational/MaybeMonad.cpp new file mode 100644 index 0000000..625c3de --- /dev/null +++ b/Creational/Creational/MaybeMonad.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +struct Address { + string* house_name = nullptr; +}; + +struct Person { + Address* address = nullptr; +}; + +template struct Maybe; +template Maybe maybe(T* context) +{ + return Maybe(context); +} + +template +struct Maybe { + T* context; + + Maybe(T *context) : context(context) { } + + template + auto With(TFunc evaluator) + { + /*if (context == nullptr) + return Maybe::type>(nullptr); + return maybe(evaluator(context));*/ + return context != nullptr ? maybe(evaluator(context)) : nullptr; + }; + + template + auto Do(TFunc action) + { + if (context != nullptr) action(context); + return *this; + } +}; + +void print_house_name(Person* p) +{ + // if (p != nullptr && p->address != nullptr && p->address->house_name != nullptr) + // cout << *p->address->house_name << endl; + auto z = maybe(p) + .With([](auto x) { return x->address; }) + .With([](auto x) { return x->house_name; }) + .Do([](auto x) { cout << *x << endl; }); +} + + + +int main_57576() +{ + Person p; + p.address = new Address; + p.address->house_name = new string("name"); + print_house_name(&p); + + delete p.address->house_name; + delete p.address; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/Monostate.cpp b/Creational/Creational/Monostate.cpp new file mode 100644 index 0000000..b34aae7 --- /dev/null +++ b/Creational/Creational/Monostate.cpp @@ -0,0 +1,16 @@ +#include + +class Printer +{ + static int id; +public: + int get_id() const { return id; } + void set_id(int value) { id = value; } +}; + +int main_73468() +{ + Printer p; + + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/OCP.cpp b/Creational/Creational/OCP.cpp new file mode 100644 index 0000000..342098c --- /dev/null +++ b/Creational/Creational/OCP.cpp @@ -0,0 +1,159 @@ +// open closed principle + +// open for extension, closed for modification + +#include +#include +#include +using namespace std; + +enum class Color { red, green, blue }; +enum class Size { small, medium, large }; + +struct Product +{ + string name; + Color color; + Size size; +}; + +struct ProductFilter +{ + typedef vector Items; + + Items by_color(Items items, const Color color) + { + Items result; + for (auto& i : items) + if (i->color == color) + result.push_back(i); + return result; + } + + Items by_size(Items items, const Size size) + { + Items result; + for (auto& i : items) + if (i->size == size) + result.push_back(i); + return result; + } + + Items by_size_and_color(Items items, const Size size, const Color color) + { + Items result; + for (auto& i : items) + if (i->size == size && i->color == color) + result.push_back(i); + return result; + } +}; + +template struct AndSpecification; + +template struct Specification +{ + virtual bool is_satisfied(T* item) = 0; + + // new: breaks OCP if you add it post-hoc + /*AndSpecification operator&&(Specification&& other) + { + return AndSpecification(*this, other); + }*/ +}; + +// new: +template AndSpecification operator&& + (Specification&& first, Specification&& second) +{ + return { first, second }; +} + +template struct Filter +{ + virtual vector filter(vector items, + Specification& spec) = 0; +}; + +struct BetterFilter : Filter +{ + vector filter(vector items, + Specification &spec) override + { + vector result; + for (auto& p : items) + if (spec.is_satisfied(p)) + result.push_back(p); + return result; + } +}; + +struct ColorSpecification : Specification +{ + Color color; + + ColorSpecification(Color color) : color(color) {} + + bool is_satisfied(Product *item) override { + return item->color == color; + } +}; + +struct SizeSpecification : Specification +{ + Size size; + + explicit SizeSpecification(const Size size) + : size{ size } + { + } + + + bool is_satisfied(Product* item) override { + return item->size == size; + } +}; + +template struct AndSpecification : Specification +{ + Specification& first; + Specification& second; + + AndSpecification(Specification &first, Specification &second) + : first(first), second(second) {} + + bool is_satisfied(T *item) override { + return first.is_satisfied(item) && second.is_satisfied(item); + } +}; + +// new: + +int main() +{ + Product apple{"Apple", Color::green, Size::small}; + Product tree{"Tree", Color::green, Size::large}; + Product house{"House", Color::blue, Size::large}; + + const vector all { &apple, &tree, &house }; + + BetterFilter bf; + ColorSpecification green(Color::green); + auto green_things = bf.filter(all, green); + for (auto& x : green_things) + cout << x->name << " is green\n"; + + + SizeSpecification large(Size::large); + AndSpecification green_and_large(green, large); + + //auto big_green_things = bf.filter(all, green_and_large); + + auto spec = ColorSpecification{Color::green} && + SizeSpecification{Size::large}; + for (auto& x : bf.filter(all, spec)) + cout << x->name << " is green and large\n"; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/Person.cpp b/Creational/Creational/Person.cpp new file mode 100644 index 0000000..2388c09 --- /dev/null +++ b/Creational/Creational/Person.cpp @@ -0,0 +1,7 @@ +#include "Person.h" +#include "PersonBuilder.h" + +PersonBuilder Person::create() +{ + return PersonBuilder{}; +} \ No newline at end of file diff --git a/Creational/Creational/Person.h b/Creational/Creational/Person.h new file mode 100644 index 0000000..c0e3c12 --- /dev/null +++ b/Creational/Creational/Person.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include + +class PersonBuilder; + +class Person +{ + // address + std::string street_address, post_code, city; + + // employment + std::string company_name, position; + int annual_income = 0; + + Person() + { + std::cout << "Person created\n"; + } + +public: + ~Person() + { + std::cout << "Person destroyed\n"; + } + + static PersonBuilder create(); + + Person(Person&& other) + : street_address{move(other.street_address)}, + post_code{move(other.post_code)}, + city{move(other.city)}, + company_name{move(other.company_name)}, + position{move(other.position)}, + annual_income{other.annual_income} + { + } + + Person& operator=(Person&& other) + { + if (this == &other) + return *this; + street_address = move(other.street_address); + post_code = move(other.post_code); + city = move(other.city); + company_name = move(other.company_name); + position = move(other.position); + annual_income = other.annual_income; + return *this; + } + + friend std::ostream& operator<<(std::ostream& os, const Person& obj) + { + return os + << "street_address: " << obj.street_address + << " post_code: " << obj.post_code + << " city: " << obj.city + << " company_name: " << obj.company_name + << " position: " << obj.position + << " annual_income: " << obj.annual_income; + } + + friend class PersonBuilder; + friend class PersonAddressBuilder; + friend class PersonJobBuilder; +}; diff --git a/Creational/Creational/PersonAddressBuilder.h b/Creational/Creational/PersonAddressBuilder.h new file mode 100644 index 0000000..582ae68 --- /dev/null +++ b/Creational/Creational/PersonAddressBuilder.h @@ -0,0 +1,30 @@ +#pragma once +#include + +class PersonAddressBuilder : public PersonBuilderBase +{ + typedef PersonAddressBuilder Self; +public: + explicit PersonAddressBuilder(Person& person) + : PersonBuilderBase{person} + { + } + + Self& at(std::string street_address) + { + person.street_address = street_address; + return *this; + } + + Self& with_postcode(std::string post_code) + { + person.post_code = post_code; + return *this; + } + + Self& in(std::string city) + { + person.city = city; + return *this; + } +}; \ No newline at end of file diff --git a/Creational/Creational/PersonBuilder.cpp b/Creational/Creational/PersonBuilder.cpp new file mode 100644 index 0000000..d546bde --- /dev/null +++ b/Creational/Creational/PersonBuilder.cpp @@ -0,0 +1,13 @@ +#include "PersonBuilder.h" +#include "PersonAddressBuilder.h" +#include "PersonJobBuilder.h" + +PersonAddressBuilder PersonBuilderBase::lives() const +{ + return PersonAddressBuilder{ person }; +} + +PersonJobBuilder PersonBuilderBase::works() const +{ + return PersonJobBuilder{ person }; +} diff --git a/Creational/Creational/PersonBuilder.h b/Creational/Creational/PersonBuilder.h new file mode 100644 index 0000000..4174e3b --- /dev/null +++ b/Creational/Creational/PersonBuilder.h @@ -0,0 +1,35 @@ +#pragma once +#include "Person.h" + +class PersonAddressBuilder; +class PersonJobBuilder; + +class PersonBuilderBase +{ +protected: + Person& person; + explicit PersonBuilderBase(Person& person) + : person{ person } + { + } +public: + operator Person() const + { + return std::move(person); + } + + // builder facets + + PersonAddressBuilder lives() const; + PersonJobBuilder works() const; +}; + +class PersonBuilder : public PersonBuilderBase +{ + Person p; +public: + PersonBuilder(): PersonBuilderBase{p} + { + } + +}; \ No newline at end of file diff --git a/Creational/Creational/PersonJobBuilder.h b/Creational/Creational/PersonJobBuilder.h new file mode 100644 index 0000000..8306d2d --- /dev/null +++ b/Creational/Creational/PersonJobBuilder.h @@ -0,0 +1,30 @@ +#pragma once +#include "PersonBuilder.h" + +class PersonJobBuilder : public PersonBuilderBase +{ + typedef PersonJobBuilder Self; +public: + explicit PersonJobBuilder(Person& person) + : PersonBuilderBase { person } + { + } + + Self& at(std::string company_name) + { + person.company_name = company_name; + return *this; + } + + Self& as_a(std::string position) + { + person.position = position; + return *this; + } + + Self& earning(int annual_income) + { + person.annual_income = annual_income; + return *this; + } +}; \ No newline at end of file diff --git a/Creational/Creational/Prototype.cpp b/Creational/Creational/Prototype.cpp new file mode 100644 index 0000000..48d8eac --- /dev/null +++ b/Creational/Creational/Prototype.cpp @@ -0,0 +1,217 @@ +#include +#include +#include +#include +#include +#include "Person.h" +using namespace std; +#include +#include +#include + +struct Address +{ + string street; + string city; + int suite; + + + Address(const string& street, const string& city, const int suite) + : street{street}, + city{city}, + suite{suite} + { + } + + /*Address(const Address& other) + : street{other.street}, + city{other.city}, + suite{other.suite} + { + }*/ + + friend ostream& operator<<(ostream& os, const Address& obj) + { + return os + << "street: " << obj.street + << " city: " << obj.city + << " suite: " << obj.suite; + } +}; + + +struct Contact +{ + string name; + Address* address; + + Contact& operator=(const Contact& other) + { + if (this == &other) + return *this; + name = other.name; + address = other.address; + return *this; + } + + Contact() : name(nullptr), address(nullptr) + {} // required for serialization + + Contact(string name, Address* address) + : name{name}, address{address} + { + //this->address = new Address{ *address }; + } + + Contact(const Contact& other) + : name{other.name} + //, address{ new Address{*other.address} } + { + address = new Address( + other.address->street, + other.address->city, + other.address->suite + ); + } + + +private: + friend class boost::serialization::access; + + template + void save(archive& ar, const unsigned version) const + { + ar << name; + ar << address; + } + + template + void load(archive& ar, const unsigned version) + { + ar >> name; + ar >> address; + } + + BOOST_SERIALIZATION_SPLIT_MEMBER() + +public: + ~Contact() + { + delete address; + } + + + friend ostream& operator<<(ostream& os, const Contact& obj) + { + return os + << "name: " << obj.name + << " works at " << *obj.address; // note the star here + } +}; + +struct EmployeeFactory +{ + static Contact main; + static Contact aux; + + static unique_ptr NewMainOfficeEmployee(string name, int suite) + { + //static Contact p{ "", new Address{ "123 East Dr", "London", 0 } }; + return NewEmployee(name, suite, main); + } + + static unique_ptr NewAuxOfficeEmployee(string name, int suite) + { + return NewEmployee(name, suite, aux); + } + +private: + static unique_ptr NewEmployee(string name, int suite, Contact& proto) + { + auto result = make_unique(proto); + result->name = name; + result->address->suite = suite; + return result; + } +}; + +//Contact EmployeeFactory::main{ "", new Address{ "123 East Dr", "London", 0 } }; +//Contact EmployeeFactory::aux{ "", new Address{ "123B East Dr", "London", 0 } }; + +int main_3423() +{ + // this is tedious + // Contact john{ "John Doe", new Address{"123 East Dr", "London"} }; + // Contact jane{ "Jane Doe", new Address{"123 East Dr", "London"} }; + + auto addr = new Address{ "123 East Dr", "London", 0 /* ? */ }; + + //Contact john{ "John Doe", addr }; + //john.address->suite = 123; + //Contact jane{ "Jane Doe", addr }; + //jane.address->suite = 124; + + //Contact jane2{ jane }; // shallow copy + //jane2.address->suite = 555; + + + + // + //std::cout << jane2 << std::endl; + + // whenever an address is needed, make a copy + /*Contact john{ "John Doe", new Address{*addr} }; + john.address->suite = 123; + + Contact jane{ "Jane Doe", new Address{*addr} }; + jane.address->suite = 125; + + cout << john << "\n" << jane << endl;*/ + + // much better. let's list employees + //Contact employee{ "Unknown", new Address{"628 Happy St", "Joy", 0} }; + + //// we can use this prototype to create john and jane + //Contact john{ employee }; + //john.name = "John Doe"; + //john.address->suite = 123; + + //Contact jane{ employee }; + //jane.name = "Jane Doe"; + //jane.address->suite = 125; + + //cout << john << "\n" << jane << "\n"; + + //delete addr; + + // 4. Boost Serialization + + auto clone = [](const Contact& c) + { + // 1. Serialize the contact + ostringstream oss; + boost::archive::text_oarchive oa(oss); + oa << c; + string s = oss.str(); + + // 2. Deserialize the contact + istringstream iss(oss.str()); + boost::archive::text_iarchive ia(iss); + Contact result; + ia >> result; + return result; + }; + + // contact john = ... + // contact jane = clone(john) + + //auto john = EmployeeFactory::NewAuxOfficeEmployee("John Doe", 123); + //auto jane = EmployeeFactory::NewMainOfficeEmployee("Jane Doe", 125); + + //cout << *john << "\n" << *jane << "\n"; // note the stars here + + delete addr; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/PrototypeCodingExercise.cpp b/Creational/Creational/PrototypeCodingExercise.cpp new file mode 100644 index 0000000..a96e4a9 --- /dev/null +++ b/Creational/Creational/PrototypeCodingExercise.cpp @@ -0,0 +1,69 @@ +struct Point +{ + int x{ 0 }, y{ 0 }; + + Point(){} + + Point(const int x, const int y) : x{x}, y{y} {} +}; + +struct Line +{ + Point *start, *end; + + Line(Point* const start, Point* const end) + : start(start), end(end) + { + } + + ~Line() + { + delete start; + delete end; + } + + Line deep_copy() const + { + return Line{ + new Point(start->x, start->y), + new Point(end->x, end->y) + }; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + + +namespace +{ + class Evaluate : public testing::Test + { + }; + + TEST_F(Evaluate, SimpleTest) + { + Line line1{ + new Point{3,3}, + new Point{10,10} + }; + + auto line2 = line1.deep_copy(); + line1.start->x = line1.start->y = + line1.end->y = line1.end->y = 0; + + ASSERT_EQ(3, line2.start->x); + ASSERT_EQ(3, line2.start->y); + ASSERT_EQ(10, line2.end->x); + ASSERT_EQ(10, line2.end->y); + } +} // namespace + +int main(int ac, char* av[]) +{ + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Creational/Creational/SRP.cpp b/Creational/Creational/SRP.cpp new file mode 100644 index 0000000..9b2beaa --- /dev/null +++ b/Creational/Creational/SRP.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +using namespace std; + +struct Journal +{ + string title; + vector entries; + + explicit Journal(const string& title) + : title{title} + { + } + + void add(const string& entry); + + // persistence is a separate concern + void save(const string& filename); +}; + +void Journal::add(const string& entry) +{ + static int count = 1; + entries.push_back(boost::lexical_cast(count++) + + ": " + entry); +} + +void Journal::save(const string& filename) +{ + ofstream ofs(filename); + for (auto& s : entries) + ofs << s << endl; +} + +struct PersistenceManager +{ + static void save(const Journal& j, const string& filename) + { + ofstream ofs(filename); + for (auto& s : j.entries) + ofs << s << endl; + } +}; + +void main() +{ + Journal journal{"Dear Diary"}; + journal.add("I ate a bug"); + journal.add("I cried today"); + + //journal.save("diary.txt"); + + PersistenceManager pm; + pm.save(journal, "diary.txt"); +} \ No newline at end of file diff --git a/Creational/Creational/Serialization.cpp b/Creational/Creational/Serialization.cpp new file mode 100644 index 0000000..114ed74 --- /dev/null +++ b/Creational/Creational/Serialization.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include "Person.h" +using namespace std; +#include +#include +#include + +struct Address +{ + string street; + string city; + int suite; + + + friend ostream& operator<<(ostream& os, const Address& obj) + { + return os + << "street: " << obj.street + << " city: " << obj.city + << " suite: " << obj.suite; + } + +private: + friend class boost::serialization::access; + + template void serialize(Ar& ar, const unsigned int version) + { + ar & street; + ar & city; + ar & suite; + } +}; + +struct Contact +{ + string name; + Address* address = nullptr; + + friend ostream& operator<<(ostream& os, const Contact& obj) + { + return os + << "name: " << obj.name + << " address: " << *obj.address; + } + +private: + friend class boost::serialization::access; + + template void serialize(Ar& ar, const unsigned int version) + { + ar & name; + ar & address; // no * + } +}; + +int main_() +{ + Contact john; + john.name = "John Doe"; + john.address = new Address{ "123 East Dr", "London", 123 }; + + auto clone = [](const Contact& c) + { + ostringstream oss; + boost::archive::text_oarchive oa(oss); + oa << c; + string s = oss.str(); + + istringstream iss(oss.str()); + boost::archive::text_iarchive ia(iss); + Contact result; + ia >> result; + return result; + }; + + Contact jane = clone(john); + jane.name = "Jane Doe"; + jane.address->street = "123B West Dr"; + jane.address->suite = 300; + + cout << john << endl << jane << endl; + + getchar(); + return 0; +} \ No newline at end of file diff --git a/Creational/Creational/Singleton.h b/Creational/Creational/Singleton.h new file mode 100644 index 0000000..77e2ee0 --- /dev/null +++ b/Creational/Creational/Singleton.h @@ -0,0 +1,109 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +class Database +{ +public: + virtual int get_population(const std::string& name) = 0; +}; + +class SingletonDatabase : public Database +{ + SingletonDatabase() + { + std::cout << "Initializing database" << std::endl; + + std::ifstream ifs("capitals.txt"); + + std::string s, s2; + while (getline(ifs, s)) + { + getline(ifs, s2); + int pop = boost::lexical_cast(s2); + capitals[s] = pop; + } + //instance_count++; + } + + std::map capitals; + +public: + //static int instance_count; + + SingletonDatabase(SingletonDatabase const&) = delete; + void operator=(SingletonDatabase const&) = delete; + + static SingletonDatabase& get() + { + static SingletonDatabase db; + return db; + } + + int get_population(const std::string& name) override + { + return capitals[name]; + } + + /* + static SingletonDatabase* get_instance() + { + if (!instance) + instance = new SingletonDatabase; + return instance; // atexit + } + */ +}; + +//int SingletonDatabase::instance_count = 0; + +class DummyDatabase : public Database +{ + std::map capitals; +public: + + + DummyDatabase() + { + capitals["alpha"] = 1; + capitals["beta"] = 2; + capitals["gamma"] = 3; + } + + int get_population(const std::string& name) override { + return capitals[name]; + } +}; + +struct SingletonRecordFinder +{ + int total_population(std::vector names) + { + int result = 0; + for (auto& name : names) + result += SingletonDatabase::get().get_population(name); + return result; + } +}; + +struct ConfigurableRecordFinder +{ + explicit ConfigurableRecordFinder(Database& db) + : db{db} + { + } + + int total_population(std::vector names) const + { + int result = 0; + for (auto& name : names) + result += db.get_population(name); + return result; + } + + Database& db; +}; \ No newline at end of file diff --git a/Creational/Creational/SingletonCodingExercise.cpp b/Creational/Creational/SingletonCodingExercise.cpp new file mode 100644 index 0000000..b51e371 --- /dev/null +++ b/Creational/Creational/SingletonCodingExercise.cpp @@ -0,0 +1,43 @@ +#include +using namespace std; + +struct SingletonTester +{ + template + bool is_singleton(function factory) + { + T* _1 = factory(); + T* _2 = factory(); + return _1 == _2; + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + + +namespace +{ + class Evaluate : public testing::Test + { + }; + + TEST_F(Evaluate, SimpleTest) + { + SingletonTester tester; + ASSERT_TRUE(tester.is_singleton( + [&]() -> SingletonTester* { return &tester; })) + << "Expected a singleton in this case; provided lambda is yielding the same object over and over."; + ASSERT_FALSE(tester.is_singleton([]() { return new SingletonTester{}; })); + } +} // namespace + + +//int main(int ac, char* av[]) +//{ +// testing::InitGoogleTest(&ac, av); +// return RUN_ALL_TESTS(); +//} diff --git a/Creational/Creational/SingletonTests.cpp b/Creational/Creational/SingletonTests.cpp new file mode 100644 index 0000000..0a898af --- /dev/null +++ b/Creational/Creational/SingletonTests.cpp @@ -0,0 +1,32 @@ +#include "Singleton.hpp" +#include + +//TEST(DatabaseTests, IsSingletonTest) +//{ +// auto& db = SingletonDatabase::get(); +// auto& db2 = SingletonDatabase::get(); +// ASSERT_EQ(1, db.instance_count); +// ASSERT_EQ(1, db2.instance_count); +//} + +TEST(RecordFinderTests, SingletonTotalPopulationTest) +{ + SingletonRecordFinder rf; + std::vector names{ "Seoul", "Mexico City" }; + int tp = rf.total_population(names); + EXPECT_EQ(17500000 + 17400000, tp); +} + +TEST(RecordFinderTests, DependantTotalPopulationTest) +{ + DummyDatabase db{}; + ConfigurableRecordFinder rf{ db }; + EXPECT_EQ(4, rf.total_population( + std::vector{"alpha", "gamma"})); +} + +int dsfmain(int ac, char* av[]) +{ + testing::InitGoogleTest(&ac, av); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Creational/Creational/TeaFactory.h b/Creational/Creational/TeaFactory.h new file mode 100644 index 0000000..77fde37 --- /dev/null +++ b/Creational/Creational/TeaFactory.h @@ -0,0 +1,9 @@ +#pragma once +#include "HotDrinkFactory.h" + +struct TeaFactory : HotDrinkFactory +{ + unique_ptr make() const override { + return make_unique(); + } +}; \ No newline at end of file diff --git a/Creational/Creational/UnknownExercise.txt b/Creational/Creational/UnknownExercise.txt new file mode 100644 index 0000000..7721ff7 --- /dev/null +++ b/Creational/Creational/UnknownExercise.txt @@ -0,0 +1,196 @@ +#include +#include +using namespace std; + +struct Game; +struct StatQuery; + +enum class Statistic +{ + Attack, + Defense +}; + +struct StatQuery +{ + Statistic statistic; + int result = 0; +}; + +class Creature +{ +protected: + Game& game; + int baseAttack, baseDefense; + +public: + Creature(Game& game, const int baseAttack, const int baseDefense) + : game{game}, + baseAttack{baseAttack}, + baseDefense{baseDefense} + { + } + + virtual int attack() const { return baseAttack; } + virtual int defense() const { return baseDefense; } + + virtual void query(const void* source, StatQuery& query) const = 0; +}; + +struct Game +{ + vector creatures; +}; + +class Goblin : public Creature +{ + int doQuery(const Statistic s) const + { + StatQuery q{s}; + for (const auto& c : game.creatures) + { + c->query(this, q); + } + return q.result; + } + +public: + + Goblin(Game& game, const int baseAttack, const int baseDefense) + : Creature{game, baseAttack, baseDefense} + { + } + + Goblin(Game& game) + : Creature{game, 1, 1} + { + } + + int attack() const override + { + return doQuery(Statistic::Attack); + } + + int defense() const override + { + return doQuery(Statistic::Defense); + } + + void query(const void* source, StatQuery& query) const override + { + if (source == this) + { + switch (query.statistic) + { + case Statistic::Attack: + query.result += baseAttack; + break; + case Statistic::Defense: + query.result += baseDefense; + break; + } + } + else + { + if (query.statistic == Statistic::Defense) + { + query.result++; + } + } + } +}; + +class GoblinKing : public Goblin +{ +public: + explicit GoblinKing(Game& game) + : Goblin{game, 3, 3} + { + } + + void query(const void* source, StatQuery& query) const override + { + if (source != this && query.statistic == Statistic::Attack) + { + query.result++; + } + else + { + Goblin::query(source, query); + } + } +}; + +#include "gtest/gtest.h" + +//#include "helpers/iohelper.h" + +//#include "exercise.cpp" + + +namespace +{ + class Evaluate : public testing::Test + { + public: + Game game; + protected: + Evaluate() + { + // You can do set-up work for each test here. + } + + virtual ~Evaluate() + { + // You can do clean-up work that doesn't throw exceptions here. + } + + // Objects declared here can be used by all tests in the test case for Foo. + }; + + TEST_F(Evaluate, SingleGoblinTest) + { + Goblin goblin{game}; + game.creatures.push_back(&goblin); + ASSERT_EQ(1, goblin.attack()) << "Single goblin's attack must be = 1"; + ASSERT_EQ(1, goblin.defense()) << "Single goblin's defense must be = 1"; + } + + TEST_F(Evaluate, TwoGoblinTest) + { + Goblin goblin{ game }, goblin2{ game }; + game.creatures.push_back(&goblin); + game.creatures.push_back(&goblin2); + + ASSERT_EQ(1, goblin.attack()) << "2 goblins in play, expecting Goblin's attack to be = 1"; + ASSERT_EQ(2, goblin.defense()) << "2 goblins in play, expecting Goblin's defense to be = 2"; + + ASSERT_EQ(1, goblin2.attack()) << "2 goblins in play, expecting Goblin's attack to be = 1"; + ASSERT_EQ(2, goblin2.defense()) << "2 goblins in play, expecting Goblin's defense to be = 2"; + } + + TEST_F(Evaluate, GoblinCohortTest) + { + Goblin goblin{ game }, goblin2{ game }; + GoblinKing king{ game }; + game.creatures.push_back(&goblin); + game.creatures.push_back(&goblin2); + game.creatures.push_back(&king); + + ASSERT_EQ(2, goblin.attack()); + ASSERT_EQ(3, goblin.defense()); + + ASSERT_EQ(2, goblin2.attack()); + ASSERT_EQ(3, goblin2.defense()); + + ASSERT_EQ(3, king.attack()); + ASSERT_EQ(5, king.defense()); + } +} // namespace + + +//int main(int ac, char* av[]) +//{ +// testing::InitGoogleTest(&ac, av); +// return RUN_ALL_TESTS(); +//} diff --git a/Creational/Creational/capitals.txt b/Creational/Creational/capitals.txt new file mode 100644 index 0000000..ca4a516 --- /dev/null +++ b/Creational/Creational/capitals.txt @@ -0,0 +1,20 @@ +Tokyo +33200000 +New York +17800000 +Sao Paulo +17700000 +Seoul +17500000 +Mexico City +17400000 +Osaka +16425000 +Manila +14750000 +Mumbai +14350000 +Delhi +14300000 +Jakarta +14250000 \ No newline at end of file diff --git a/Creational/Creational/di.h b/Creational/Creational/di.h new file mode 100644 index 0000000..04cd2e3 --- /dev/null +++ b/Creational/Creational/di.h @@ -0,0 +1,3103 @@ +// +// Copyright (c) 2012-2017 Kris Jusiak (kris at jusiak dot net) +// +// 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) +// +#pragma once +#if (__cplusplus < 201305L && _MSC_VER < 1900) +#error "[Boost].DI requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)" +#else +#define BOOST_DI_VERSION 1'1'0 +#define BOOST_DI_NAMESPACE_BEGIN \ + namespace boost { \ + namespace di { \ + inline namespace v1_1_0 { +#define BOOST_DI_NAMESPACE_END \ + } \ + } \ + } +#if !defined(BOOST_DI_CFG_DIAGNOSTICS_LEVEL) +#define BOOST_DI_CFG_DIAGNOSTICS_LEVEL 1 +#endif +#if defined(BOOST_DI_CFG_FWD) +BOOST_DI_CFG_FWD +#endif +#define __BOOST_DI_COMPILER(arg, ...) __BOOST_DI_COMPILER_IMPL(arg, __VA_ARGS__) +#define __BOOST_DI_COMPILER_IMPL(arg, ...) arg##__VA_ARGS__ +#if defined(__clang__) +#define __CLANG__ __BOOST_DI_COMPILER(__clang_major__, __clang_minor__) +#define __BOOST_DI_UNUSED __attribute__((unused)) +#define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] +#define __BOOST_DI_TYPE_WKND(T) +#define __BOOST_DI_ACCESS_WKND private +#elif defined(__GNUC__) +#define __GCC__ +#define __BOOST_DI_UNUSED __attribute__((unused)) +#define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] +#define __BOOST_DI_TYPE_WKND(T) +#define __BOOST_DI_ACCESS_WKND private +#elif defined(_MSC_VER) +#define __MSVC__ +#define __has_include(...) 0 +#define __BOOST_DI_UNUSED +#define __BOOST_DI_DEPRECATED(...) __declspec(deprecated(__VA_ARGS__)) +#define __BOOST_DI_TYPE_WKND(T) (T &&) +#define __BOOST_DI_ACCESS_WKND public +#endif +#if !defined(__has_builtin) +#define __has_builtin(...) 0 +#endif +#if !defined(__has_extension) +#define __has_extension(...) 0 +#endif +#if defined(__CLANG__) +#if (!BOOST_DI_CFG_DIAGNOSTICS_LEVEL) +#pragma clang diagnostic error "-Wdeprecated-declarations" +#else +#pragma clang diagnostic warning "-Wdeprecated-declarations" +#endif +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wundefined-inline" +#pragma clang diagnostic error "-Wundefined-internal" +#pragma clang diagnostic ignored "-Wmissing-field-initializers" +#elif defined(__GCC__) +#pragma GCC diagnostic error "-Wdeprecated-declarations" +#pragma GCC diagnostic push +#if (__GNUC__ < 6) +#pragma GCC diagnostic error "-Werror" +#endif +#elif defined(__MSVC__) +#pragma warning(disable : 4503) +#pragma warning(disable : 4822) +#pragma warning(disable : 4505) +#endif +#if __has_include(<__config>) +#include <__config> +#endif +#if defined(_LIBCPP_VERSION) + _LIBCPP_BEGIN_NAMESPACE_STD +#else + namespace std { +#endif + template + class shared_ptr; + template + class weak_ptr; + template + class unique_ptr; + template + struct char_traits; + template + class tuple; + template + class vector; + template + class set; + template + class move_iterator; +#if defined(_LIBCPP_VERSION) + _LIBCPP_END_NAMESPACE_STD +#else +} +#endif +namespace std { + template + class initializer_list; +} +namespace boost { + template + class shared_ptr; +} +BOOST_DI_NAMESPACE_BEGIN +struct _ { + _(...) {} +}; +namespace aux { + using swallow = int[]; + template + using owner = T; + template + struct valid { + using type = int; + }; + template + using valid_t = typename valid::type; + template + struct type {}; + struct none_type {}; + template + struct non_type {}; + template + struct always { + static constexpr auto value = true; + }; + template + struct never { + static constexpr auto value = false; + }; + template + struct identity { + using type = T; + }; + template + struct type_list { + using type = type_list; + }; + template + struct bool_list { + using type = bool_list; + }; + template + struct pair { + using type = pair; + using first = T1; + using second = T2; + }; + template + struct inherit : Ts... { + using type = inherit; + }; + template + struct join { + using type = type_list<>; + }; + template + struct join { + using type = T; + }; + template + struct join, type_list, Ts...> : join, Ts...> {}; + template + struct join, type_list, type_list, type_list, type_list, type_list, + type_list, type_list, type_list, type_list, type_list, type_list, + type_list, type_list, type_list, type_list, type_list, Us...> + : join, + Us...> {}; + template + using join_t = typename join::type; + template + struct index_sequence { + using type = index_sequence; + }; +#if __has_builtin(__make_integer_seq) + template + struct integer_sequence; + template + struct integer_sequence { + using type = index_sequence; + }; + template + struct make_index_sequence_impl { + using type = typename __make_integer_seq::type; + }; +#else + template + struct make_index_sequence_impl; + template <> + struct make_index_sequence_impl<0> : index_sequence<> {}; + template <> + struct make_index_sequence_impl<1> : index_sequence<0> {}; + template <> + struct make_index_sequence_impl<2> : index_sequence<0, 1> {}; + template <> + struct make_index_sequence_impl<3> : index_sequence<0, 1, 2> {}; + template <> + struct make_index_sequence_impl<4> : index_sequence<0, 1, 2, 3> {}; + template <> + struct make_index_sequence_impl<5> : index_sequence<0, 1, 2, 3, 4> {}; + template <> + struct make_index_sequence_impl<6> : index_sequence<0, 1, 2, 3, 4, 5> {}; + template <> + struct make_index_sequence_impl<7> : index_sequence<0, 1, 2, 3, 4, 5, 6> {}; + template <> + struct make_index_sequence_impl<8> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7> {}; + template <> + struct make_index_sequence_impl<9> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8> {}; + template <> + struct make_index_sequence_impl<10> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8, 9> {}; +#endif + template + using make_index_sequence = typename make_index_sequence_impl::type; +} +template +struct named {}; +struct no_name { + constexpr auto operator()() const noexcept { return ""; } +}; +template +struct ctor_traits; +template +struct self {}; +struct ignore_policies {}; +namespace core { + template + struct any_type_fwd; + template + struct any_type_ref_fwd; + template + struct any_type_1st_fwd; + template + struct any_type_1st_ref_fwd; + struct dependency_base {}; + struct injector_base {}; + template + struct dependency__ : T { + using T::try_create; + using T::is_referable; + using T::create; + }; + template + struct injector__ : T { + using T::try_create; + using T::create_impl; + using T::create_successful_impl; +#if defined(__MSVC__) + template + using is_creatable = typename T::template is_creatable; +#else + using T::is_creatable; +#endif + }; + template + struct array; + struct deduced {}; + template + class dependency; +} +namespace scopes { + class deduce; + class instance; + class singleton; + class unique; +} +#define __BOOST_DI_REQUIRES(...) typename ::boost::di::v1_1_0::aux::enable_if<__VA_ARGS__, int>::type +#define __BOOST_DI_REQUIRES_MSG(...) typename ::boost::di::v1_1_0::aux::concept_check<__VA_ARGS__>::type +namespace aux { + template + T&& declval(); + template + struct integral_constant { + using type = integral_constant; + static constexpr T value = V; + }; + using true_type = integral_constant; + using false_type = integral_constant; + template + struct conditional { + using type = T; + }; + template + struct conditional { + using type = F; + }; + template + using conditional_t = typename conditional::type; + template + struct enable_if {}; + template + struct enable_if { + using type = T; + }; + template + using enable_if_t = typename enable_if::type; + template + struct concept_check { + static_assert(T::value, "constraint not satisfied"); + }; + template <> + struct concept_check { + using type = int; + }; + template + struct remove_reference { + using type = T; + }; + template + struct remove_reference { + using type = T; + }; + template + struct remove_reference { + using type = T; + }; + template + using remove_reference_t = typename remove_reference::type; + template + struct remove_pointer { + using type = T; + }; + template + struct remove_pointer { + using type = T; + }; + template + using remove_pointer_t = typename remove_pointer::type; + template + struct remove_smart_ptr { + using type = T; + }; + template + struct remove_smart_ptr> { + using type = T; + }; + template + struct remove_smart_ptr> { + using type = T; + }; + template + struct remove_smart_ptr> { + using type = T; + }; + template + struct remove_smart_ptr> { + using type = T; + }; + template + using remove_smart_ptr_t = typename remove_smart_ptr::type; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + struct remove_qualifiers { + using type = T; + }; + template + using remove_qualifiers_t = typename remove_qualifiers::type; + template + struct remove_extent { + using type = T; + }; + template + struct remove_extent { + using type = T; + }; + template + using remove_extent_t = typename remove_extent::type; + template + struct deref_type { + using type = T; + }; + template + struct deref_type> { + using type = remove_qualifiers_t::type>; + }; + template + struct deref_type> { + using type = remove_qualifiers_t::type>; + }; + template + struct deref_type> { + using type = remove_qualifiers_t::type>; + }; + template + struct deref_type> { + using type = remove_qualifiers_t::type>; + }; + template + struct deref_type> { + using type = core::array::type>>; + }; + template + struct deref_type> { + using type = core::array::type>>; + }; + template + using decay_t = typename deref_type>::type; + template + struct is_same : false_type {}; + template + struct is_same : true_type {}; + template + struct is_base_of : integral_constant {}; + template + struct is_class : integral_constant {}; + template + struct is_abstract : integral_constant {}; + template + struct is_polymorphic : integral_constant {}; + template + using is_valid_expr = true_type; +#if __has_extension(is_constructible) && !((__clang_major__ == 3) && (__clang_minor__ == 5)) + template + using is_constructible = integral_constant; +#else + template + decltype(void(T(declval()...)), true_type{}) test_is_constructible(int); + template + false_type test_is_constructible(...); + template + struct is_constructible : decltype(test_is_constructible(0)) {}; +#endif + template + using is_constructible_t = typename is_constructible::type; + template + decltype(void(T{ declval()... }), true_type{}) test_is_braces_constructible(int); + template + false_type test_is_braces_constructible(...); + template + using is_braces_constructible = decltype(test_is_braces_constructible(0)); + template + using is_braces_constructible_t = typename is_braces_constructible::type; +#if defined(__MSVC__) + template + struct is_copy_constructible : integral_constant {}; + template + struct is_default_constructible : integral_constant {}; +#else + template + using is_copy_constructible = is_constructible; + template + using is_default_constructible = is_constructible; +#endif +#if defined(__CLANG__) || defined(__MSVC__) + template + struct is_convertible : integral_constant {}; +#else + struct test_is_convertible__ { + template + static void test(T); + }; + template (declval()))> + true_type test_is_convertible(int); + template + false_type test_is_convertible(...); + template + using is_convertible = decltype(test_is_convertible(0)); +#endif + template > + using is_narrowed = integral_constant::value && !is_class::value && !is_same::value>; + template + struct is_array : false_type {}; + template + struct is_array : true_type {}; + template + true_type is_complete_impl(int); + template + false_type is_complete_impl(...); + template + struct is_complete : decltype(is_complete_impl(0)) {}; + template + is_base_of is_a_impl(int); + template + false_type is_a_impl(...); + template + struct is_a : decltype(is_a_impl(0)) {}; + template + struct is_unique_impl; + template + struct not_unique : false_type { + using type = not_unique; + }; + template <> + struct not_unique<> : true_type { + using type = not_unique; + }; + template + struct is_unique_impl : not_unique<> {}; + template + struct is_unique_impl + : conditional_t, T1>::value, not_unique, is_unique_impl>, Ts...>> {}; + template + using is_unique = is_unique_impl; + template + struct unique; + template + struct unique, T, Ts...> : conditional_t, inherit...>>::value, + unique, Ts...>, unique, Ts...>> {}; + template + struct unique> : type_list {}; + template + using unique_t = typename unique, Ts...>::type; + template + decltype(::boost::di::v1_1_0::aux::declval().operator()(::boost::di::v1_1_0::aux::declval()...), + ::boost::di::v1_1_0::aux::true_type()) + is_callable_with_impl(int); + template + ::boost::di::v1_1_0::aux::false_type is_callable_with_impl(...); + template + struct is_callable_with : decltype(is_callable_with_impl(0)) {}; + struct callable_base_impl { + void operator()(...) {} + }; + template + struct callable_base : callable_base_impl, aux::conditional_t::value, T, aux::none_type> {}; + template + aux::false_type is_callable_impl(T*, aux::non_type* = 0); + aux::true_type is_callable_impl(...); + template + struct is_callable : decltype(is_callable_impl((callable_base*)0)) {}; + template + struct function_traits; + template + struct function_traits { + using result_type = R; + using args = type_list; + }; + template + struct function_traits { + using result_type = R; + using args = type_list; + }; + template + struct function_traits { + using result_type = R; + using args = type_list; + }; + template + struct function_traits { + using result_type = R; + using args = type_list; + }; + template + using function_traits_t = typename function_traits::args; +} +namespace core { + template ::type> + struct bindings_impl; + template + struct bindings_impl { + using type = typename T::deps; + }; + template + struct bindings_impl { + using type = aux::type_list; + }; +#if defined(__MSVC__) + template + struct bindings : aux::join_t::type...> {}; + template + using bindings_t = typename bindings::type; +#else + template + using bindings_t = aux::join_t::type...>; +#endif +} +namespace concepts { + template + struct type_ { + template + struct named { + struct is_bound_more_than_once : aux::false_type {}; + }; + struct is_bound_more_than_once : aux::false_type {}; + struct is_neither_a_dependency_nor_an_injector : aux::false_type {}; + struct has_disallowed_qualifiers : aux::false_type {}; + struct is_abstract : +#if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL >= 2) + // clang-format off + decltype( + T{} + ), + // clang-format on +#endif + aux::false_type{ + }; + template + struct is_not_related_to : aux::false_type {}; + }; + template + struct any_of : aux::false_type {}; + template + struct is_supported : aux::is_same::value...>, + aux::bool_list<(aux::is_constructible::value && + (aux::is_a::value || + aux::is_a::value))...>> {}; + template + struct get_not_supported; + template + struct get_not_supported { + using type = T; + }; + template + struct get_not_supported + : aux::conditional::value || aux::is_a::value, + typename get_not_supported::type, T> {}; + template + struct is_unique; + template + struct unique_dependency : aux::type {}; + template + struct unique_dependency::value)> + : aux::pair, typename T::priority> {}; + template + struct is_unique> : aux::is_unique::type...> {}; + template + struct get_is_unique_error_impl : aux::true_type {}; + template + struct get_is_unique_error_impl, TPriority>>> { + using type = typename type_::template named::is_bound_more_than_once; + }; + template + struct get_is_unique_error_impl, TPriority>>> { + using type = typename type_::is_bound_more_than_once; + }; + template + struct get_is_unique_error_impl> { + using type = typename type_::is_bound_more_than_once; + }; + template + struct get_is_unique_error; + template + struct get_is_unique_error> + : get_is_unique_error_impl::type...>::type> {}; + template + using boundable_bindings = + aux::conditional_t::value, typename get_is_unique_error>::type, + typename type_::type>::is_neither_a_dependency_nor_an_injector>; + template + using get_any_of_error = aux::conditional_t< + aux::is_same::value...>, aux::bool_list::value...>>::value, + aux::true_type, any_of>; + template + struct is_related { + static constexpr auto value = true; + }; + template + struct is_related { + static constexpr auto value = + aux::is_callable::value || + (aux::is_base_of::value || (aux::is_convertible::value && !aux::is_narrowed::value)); + }; + template + struct is_abstract { + static constexpr auto value = false; + }; + template + struct is_abstract { + static constexpr auto value = aux::is_abstract::value; + }; + auto boundable_impl(any_of<> &&)->aux::true_type; + template + auto boundable_impl(any_of &&) + ->aux::conditional_t>::value, decltype(boundable_impl(aux::declval>())), + typename type_::has_disallowed_qualifiers>; + template + using boundable_impl__ = aux::conditional_t< + is_related::value && aux::is_complete::value, I, T>::value, + aux::conditional_t::value, T>::value, typename type_::is_abstract, aux::true_type>, + typename type_::template is_not_related_to>; + template + auto boundable_impl(I&&, T &&)->aux::conditional_t>::value, boundable_impl__, + typename type_::has_disallowed_qualifiers>; + template + auto boundable_impl(I&&, T&&, aux::valid<> &&) + ->aux::conditional_t::value && aux::is_complete::value, I, T>::value, aux::true_type, + typename type_::template is_not_related_to>; + template + auto boundable_impl(I*[], T &&)->aux::conditional_t>::value, boundable_impl__, + typename type_::has_disallowed_qualifiers>; + template + auto boundable_impl(I[], T &&)->aux::conditional_t>::value, boundable_impl__, + typename type_::has_disallowed_qualifiers>; + template + auto boundable_impl(aux::type_list &&)->boundable_bindings; + template + auto boundable_impl(concepts::any_of&&, T &&) + ->get_any_of_error(), aux::declval()))...>; + template + auto boundable_impl(aux::type &&) -> typename get_is_unique_error_impl::type>::type; + aux::true_type boundable_impl(...); + template + struct boundable__ { + using type = decltype(boundable_impl(aux::declval()...)); + }; + template + using boundable = typename boundable__::type; +} +namespace type_traits { + struct stack {}; + struct heap {}; + template + struct memory_traits { + using type = stack; + }; + template + struct memory_traits { + using type = heap; + }; + template + struct memory_traits { + using type = typename memory_traits::type; + }; + template + struct memory_traits> { + using type = heap; + }; + template + struct memory_traits> { + using type = heap; + }; + template + struct memory_traits> { + using type = heap; + }; + template + struct memory_traits> { + using type = heap; + }; + template + struct memory_traits::value)> { + using type = heap; + }; + template + using memory_traits_t = typename memory_traits::type; +} +namespace concepts { + template + struct scope { + struct is_referable {}; + struct try_create {}; + struct create {}; + template + struct requires_ : aux::false_type {}; + }; + template + struct provider__ { + template + aux::conditional_t::value, T, T*> try_get(const TMemory& = {}) const; + template + T* get(const TMemory& = {}) const { + return nullptr; + } + }; + template + typename scope::template requires_::is_referable, typename scope<_, _>::try_create, + typename scope<_, _>::create> + scopable_impl(...); + template + auto scopable_impl(T &&) + ->aux::is_valid_expr::template is_referable<_>, + decltype(T::template scope<_, _>::template try_create<_, _>(provider__<_>{})), + decltype(aux::declval>().template create<_, _>(provider__<_>{}))>; + template + struct scopable__ { + using type = decltype(scopable_impl(aux::declval())); + }; + template + using scopable = typename scopable__::type; +} +#if !defined(BOOST_DI_CFG_CTOR_LIMIT_SIZE) +#define BOOST_DI_CFG_CTOR_LIMIT_SIZE 10 +#endif +namespace type_traits { + template + struct is_injectable : ::boost::di::v1_1_0::aux::false_type {}; + template + struct is_injectable> + : ::boost::di::v1_1_0::aux::true_type {}; + struct direct {}; + struct uniform {}; + template + using get = T; + template