├── .gitignore ├── Concurrency ├── ConcurrentWrapper │ ├── ConcurrentWrapper.h │ ├── Makefile │ ├── concurrent_string.cpp │ └── concurrent_string2.cpp ├── ConcurrentWrapper2 │ ├── Concurrent.h │ ├── Makefile │ └── concurrent_vector.cpp └── Queue │ ├── LICENSE.txt │ ├── Makefile │ ├── Queue.h │ └── producer_consumer1.cpp ├── Patterns ├── Observer │ ├── EventType.h │ ├── LICENSE.txt │ ├── Makefile │ ├── README │ ├── Subject.h │ ├── example1.cpp │ └── example2.cpp └── ValuePtr │ ├── Makefile │ ├── example0.cpp │ └── value_ptr.hpp ├── README.md └── WantSpeed ├── .gitignore ├── results ├── binop1_clang.txt ├── binop1_gcc.txt ├── binop2_clang.txt ├── binop2_gcc.txt ├── binop_no_move1_clang.txt ├── binop_no_move1_gcc.txt ├── binop_no_move2_clang.txt ├── binop_no_move2_gcc.txt └── results.txt └── src ├── Bar.h ├── Bar_no_move.h ├── Foo.h ├── Foo_no_move.h ├── Makefile ├── case1.cpp ├── case1_no_move.cpp ├── case2.cpp ├── case2_no_move.cpp ├── case3.cpp ├── case3_no_move.cpp ├── case4.cpp └── case4_no_move.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper/ConcurrentWrapper.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// A concurrent wrapper for serializing asynchronous access to a shared resource. 3 | /// This is a working version of the concurrent class presented in this excellent presentation 4 | /// on C++ concurrency by Herb Sutter: 5 | /// http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism 6 | /// 7 | /// Tweaked to compile with g++ 4.7.2. 8 | /// 9 | /// Wraps a shared resource such that callers can request operations on the resource asynchronously. 10 | /// Each request is treated as an atomic transaction, and the caller side is not blocked. 11 | /// 12 | /// Internally uses concurrent queue developed for the concurrent queue blog 13 | /// http://juanchopanzacpp.wordpress.com/2013/02/26/concurrent-queue-c11/ 14 | /// 15 | /// Example useage: 16 | /// 17 | /// @code 18 | /// ConcurrentWrapper cs; 19 | /// 20 | /// //Thread 1: just print the string 21 | /// cs([](const std::string& s){ std::cout << s;}); 22 | /// 23 | /// // Thread 2: 24 | /// void foo(std::string& s); 25 | /// void bar(std::string& s); 26 | /// // run bar, then foo on the shared resource 27 | /// cs([] (std::string& s) { bar(s); foo(s);}); 28 | /// 29 | /// // Thread 3: make string uppercase 30 | /// cs([](std::string& s){ for (auto& c : s) c = static_cast(std::toupper(c));)} ); 31 | /// 32 | /// 33 | 34 | #include 35 | #include 36 | #include "Queue/Queue.h" 37 | 38 | template 39 | class ConcurrentWrapper 40 | { 41 | public: 42 | 43 | ConcurrentWrapper(T resource = T{}) 44 | : 45 | resource_{resource}, 46 | done_{false} 47 | { 48 | worker_ = std::thread([this]{ while (!done_) queue_.pop()();} ); 49 | } 50 | 51 | ~ConcurrentWrapper() 52 | { 53 | queue_.push([this]{done_ = true;}); 54 | worker_.join(); 55 | } 56 | 57 | template 58 | void operator()(F f) const 59 | { 60 | queue_.push([=]{f(resource_);}); 61 | } 62 | 63 | private: 64 | 65 | mutable Queue> queue_; 66 | mutable T resource_; 67 | std::thread worker_; 68 | bool done_; 69 | 70 | }; 71 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper/Makefile: -------------------------------------------------------------------------------- 1 | CXX := /usr/bin/g++-4.7 2 | #CXX := clang++ 3 | CPPFLAGS := -I.. 4 | CXXFLAGS := -Wall -Wextra -pedantic-errors -std=c++11 -O2 -pthread 5 | 6 | DEPS = ConcurrentWrapper.h ../Queue/Queue.h 7 | 8 | % : %.cpp $(DEPS) 9 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@ 10 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper/concurrent_string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ConcurrentWrapper.h" 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | ConcurrentWrapper cs{"Start\n"}; 10 | 11 | std::vector> v; 12 | 13 | for (int i = 0; i < 5; ++i) 14 | { 15 | v.push_back( 16 | std::async(std::launch::async, 17 | [&,i] { 18 | cs([&i](std::string& s) { 19 | s += std::to_string(i) + std::to_string(i)+ std::to_string(i) ; 20 | s += "\n"; 21 | }); 22 | cs([](const std::string& s) { std::cout << s;}); 23 | } 24 | ) 25 | ); 26 | } 27 | 28 | for (auto& fut : v) fut.wait(); 29 | std::cout << "Done\n"; 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper/concurrent_string2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ConcurrentWrapper.h" 4 | #include 5 | #include 6 | #include 7 | 8 | void uppercase(char& c) 9 | { 10 | c = static_cast(std::toupper(c)); 11 | } 12 | 13 | void lowercase(char& c) 14 | { 15 | c = static_cast(std::tolower(c)); 16 | } 17 | 18 | 19 | int main() 20 | { 21 | ConcurrentWrapper cs{"QqWwEeRrTtYyUuIiOoPpAaSsDdFfGgHhJjKkLl\n"}; 22 | 23 | std::vector> v1; 24 | std::vector> v2; 25 | std::vector> v3; 26 | 27 | for (int i = 0; i < 5; ++i) 28 | { 29 | v1.push_back( 30 | std::async(std::launch::async, 31 | [&cs,i] { 32 | cs([&i](std::string& s) { 33 | for (auto& c : s) uppercase(c); 34 | }); 35 | cs([](const std::string& s) { std::cout << s;}); 36 | } 37 | ) 38 | ); 39 | v2.push_back( 40 | std::async(std::launch::async, 41 | [&cs,i] { 42 | cs([&i](std::string& s) { 43 | for (auto& c : s) lowercase(c); 44 | }); 45 | cs([](const std::string& s) { std::cout << s;}); 46 | } 47 | ) 48 | ); 49 | 50 | } 51 | 52 | for (auto& fut : v1) fut.wait(); 53 | for (auto& fut : v2) fut.wait(); 54 | std::cout << "Done\n"; 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper2/Concurrent.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// A concurrent wrapper for serializing asynchronous access to a shared resource. 3 | /// This is a working version of the concurrent class presented in this excellent presentation 4 | /// on C++ concurrency by Herb Sutter: 5 | /// http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism 6 | /// 7 | /// This is an extension of the concurrent wrapper presented in this blog: 8 | /// http://juanchopanzacpp.wordpress.com/2013/03/01/concurrent-object-wrapper-c11/ 9 | /// 10 | /// Tested on GCC 4.7.3. 11 | //? 12 | /// Currently does not compile on gcc 4.8 due to a compiler bug related 13 | /// to decltype of member variables used in a trailing return type. 14 | /// This is expected to be fixed in GCC 4.8.1. 15 | /// 16 | /// Wraps a shared resource such that callers can request operations on the resource asynchronously. 17 | /// Each request is treated as an atomic transaction, and the caller side is not blocked. 18 | /// 19 | /// Internally uses concurrent queue developed for the concurrent queue blog 20 | /// http://juanchopanzacpp.wordpress.com/2013/02/26/concurrent-queue-c11/ 21 | /// 22 | /// Example useage: 23 | /// 24 | /// @code 25 | /// Concurrent> cv; 26 | /// 27 | /// //1: Resize the vector, fill with sequence 28 | /// auto f1 = cv([](std::vector& v)->size_t{ v.resize(10); 29 | /// std::iota(v.begin(), v.end(), 0); 30 | /// return v.size(); 31 | /// }); 32 | /// 33 | /// //2. Calculate the sum of elements 34 | /// auto f2 = cv([](const std::vector& v){ return std::accumulate(v.begin(), v.end(), 0);}); 35 | /// 36 | /// //3: Call some user defined functions 37 | /// int foo(std::vector& v); 38 | /// void bar(std::vector& v); 39 | /// // run bar, then foo on the shared resource 40 | /// auto f3 = cs([] (std::vector& v)->int { bar(v); 41 | /// return foo(v); 42 | /// }); 43 | /// 44 | /// //4 get the results when needed 45 | /// std::cout << f1.get() << " " << f2.get() " " << f3.get() << std::endl; 46 | /// 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include "Queue/Queue.h" 53 | 54 | namespace 55 | { 56 | template 57 | void promise_set_value(std::promise& prom, Fun& f, T& t) 58 | { 59 | prom.set_value(f(t)); 60 | } 61 | 62 | template 63 | void promise_set_value(std::promise& prom, Fun& f, T& t) 64 | { 65 | f(t); 66 | prom.set_value(); 67 | } 68 | 69 | } // anonymous namespace 70 | 71 | template 72 | class Concurrent 73 | { 74 | public: 75 | 76 | Concurrent(T resource = T{}) 77 | : 78 | resource_{resource}, 79 | done_{false} 80 | { 81 | worker_ = std::thread([this]{ while (!done_) queue_.pop()();} ); 82 | } 83 | 84 | ~Concurrent() 85 | { 86 | queue_.push([this]{done_ = true;}); 87 | worker_.join(); 88 | } 89 | 90 | private: 91 | 92 | mutable Queue> queue_; 93 | mutable T resource_; 94 | std::thread worker_; 95 | bool done_; 96 | 97 | public: 98 | template 99 | auto operator()(F f) const -> std::future 100 | { 101 | auto prom = std::make_shared>(); 102 | auto fut = prom->get_future(); 103 | queue_.push([=]{ 104 | try { promise_set_value(*prom, f, resource_); } 105 | catch(std::exception&) { prom->set_exception(std::current_exception()); } 106 | } 107 | ); 108 | return fut; 109 | } 110 | 111 | 112 | }; 113 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper2/Makefile: -------------------------------------------------------------------------------- 1 | CXX := /usr/bin/g++-4.7 2 | #CXX := clang++ 3 | CPPFLAGS := -I.. 4 | CXXFLAGS := -Wall -Wextra -pedantic-errors -std=c++11 -O2 -pthread 5 | 6 | DEPS = Concurrent.h ../Queue/Queue.h 7 | 8 | % : %.cpp $(DEPS) 9 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@ 10 | -------------------------------------------------------------------------------- /Concurrency/ConcurrentWrapper2/concurrent_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Concurrent.h" 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | std::ostream& operator<<(std::ostream& os, const std::vector& v) 10 | { 11 | os << "[ "; 12 | for (const auto& i : v) os << i << " "; 13 | return os << "]"; 14 | } 15 | 16 | int main() 17 | { 18 | Concurrent> cv{std::vector(10)}; 19 | auto f1 = cv([](std::vector& v){ 20 | return std::accumulate(v.begin(), v.end(), 0); 21 | }); 22 | 23 | auto f2 = cv([](std::vector& v)->bool{ 24 | std::iota(v.begin(), v.end(), 0); 25 | return true; 26 | }); 27 | auto f3 = cv([](std::vector& v){ 28 | return std::accumulate(v.begin(), v.end(), 0); 29 | }); 30 | 31 | auto f4 = cv([](std::vector& v){ 32 | return v.size(); 33 | }); 34 | 35 | auto f5 = cv([](std::vector&){}); 36 | 37 | std::cout << std::boolalpha; 38 | std::cout << f1.get() << std::endl; 39 | std::cout << f2.get() << std::endl; 40 | std::cout << f3.get() << std::endl; 41 | std::cout << f4.get() << std::endl; 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Concurrency/Queue/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Juan Palacios 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Concurrency/Queue/Makefile: -------------------------------------------------------------------------------- 1 | STD :=c++0x 2 | CPPFLAGS := -Iinclude 3 | CXXFLAGS := -Wall -Wextra -pedantic-errors -std=$(STD) -O2 -pthread 4 | 5 | producer_consumer1 : Queue.h 6 | 7 | -------------------------------------------------------------------------------- /Concurrency/Queue/Queue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 Juan Palacios juan.palacios.puyana@gmail.com 3 | // Subject to the BSD 2-Clause License 4 | // - see < http://opensource.org/licenses/BSD-2-Clause> 5 | // 6 | 7 | #ifndef CONCURRENT_QUEUE_ 8 | #define CONCURRENT_QUEUE_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | template 16 | class Queue 17 | { 18 | public: 19 | 20 | T pop() 21 | { 22 | std::unique_lock mlock(mutex_); 23 | while (queue_.empty()) 24 | { 25 | cond_.wait(mlock); 26 | } 27 | auto val = queue_.front(); 28 | queue_.pop(); 29 | return val; 30 | } 31 | 32 | void pop(T& item) 33 | { 34 | std::unique_lock mlock(mutex_); 35 | while (queue_.empty()) 36 | { 37 | cond_.wait(mlock); 38 | } 39 | item = queue_.front(); 40 | queue_.pop(); 41 | } 42 | 43 | void push(const T& item) 44 | { 45 | std::unique_lock mlock(mutex_); 46 | queue_.push(item); 47 | mlock.unlock(); 48 | cond_.notify_one(); 49 | } 50 | Queue()=default; 51 | Queue(const Queue&) = delete; // disable copying 52 | Queue& operator=(const Queue&) = delete; // disable assignment 53 | 54 | private: 55 | std::queue queue_; 56 | std::mutex mutex_; 57 | std::condition_variable cond_; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /Concurrency/Queue/producer_consumer1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 Juan Palacios juan.palacios.puyana@gmail.com 3 | // Subject to the BSD 2-Clause License 4 | // - see < http://opensource.org/licenses/BSD-2-Clause> 5 | // 6 | 7 | #include "Queue.h" 8 | #include 9 | #include 10 | 11 | const int nbConsumers = 4; 12 | const int nbToConsume = 3; 13 | const int nbToProduce = nbToConsume * nbConsumers; 14 | 15 | void print(std::string x) { 16 | static std::mutex mutex; 17 | std::unique_lock locker(mutex); 18 | std::cout << x << "\n"; 19 | } 20 | 21 | 22 | void produce(Queue& q) { 23 | for (int i = 1; i <= nbToProduce; ++i) { 24 | std::ostringstream tmp; 25 | tmp << "--> " << i; 26 | print(tmp.str()); 27 | q.push(i); 28 | } 29 | } 30 | 31 | void consume(Queue& q, unsigned int id) { 32 | for (int i = 0; i < nbToConsume; ++i) { 33 | auto item = q.pop(); 34 | std::ostringstream tmp; 35 | tmp << " " << item << " --> C" << id; 36 | print(tmp.str()); 37 | } 38 | } 39 | 40 | #include 41 | int main() 42 | { 43 | Queue q; 44 | 45 | // Start the producer thread. 46 | std::thread prod1(std::bind(produce, std::ref(q))); 47 | 48 | // Start the consumer threads. 49 | std::vector consumers; 50 | for (int i = 0 ; i < nbConsumers ; ++i) { 51 | std::thread consumer(std::bind(&consume, std::ref(q), i + 1)); 52 | consumers.push_back(std::move(consumer)); 53 | } 54 | 55 | prod1.join(); 56 | 57 | for (auto& consumer : consumers) { 58 | consumer.join(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Patterns/Observer/EventType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 Juan Palacios juan.palacios.puyana@gmail.com 3 | // Subject to the BSD 2-Clause License 4 | // - see < http://opensource.org/licenses/BSD-2-Clause> 5 | // 6 | 7 | #ifndef EVENTTYPE_H_ 8 | #define EVENTTYPE_H_ 9 | 10 | enum class EventType { GREEN, RED, BLUE, YELLOW, ORANGE }; 11 | 12 | #endif 13 | 14 | 15 | -------------------------------------------------------------------------------- /Patterns/Observer/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Juan Palacios 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Patterns/Observer/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS := -Wall -Wextra -Werror -pedantic-errors -std=c++0x -O2 2 | example1 : Subject.h 3 | example2 : Subject.h 4 | -------------------------------------------------------------------------------- /Patterns/Observer/README: -------------------------------------------------------------------------------- 1 | Code examples for observer pattern in C++11 blog entry, 2 | 3 | http://juanchopanzacpp.wordpress.com/2013/02/24/simple-observer-pattern-implementation-c11/ 4 | 5 | Requirements: 6 | 7 | * a reasonably C++11 compliant compiler. Tested with g++ 4.7.2 and a 4.8 snapshot, on various linux distrobutions. 8 | * gnu make (optional, for building) 9 | 10 | Runnable examples are called exampleN.cpp, where N is positive integer. To build using make: 11 | 12 | > make example 13 | -------------------------------------------------------------------------------- /Patterns/Observer/Subject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 Juan Palacios juan.palacios.puyana@gmail.com 3 | // Subject to the BSD 2-Clause License 4 | // - see < http://opensource.org/licenses/BSD-2-Clause> 5 | // 6 | 7 | #ifndef SUBJECT_H_ 8 | #define SUBJECT_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include // for std::forward 14 | 15 | template 16 | class Subject 17 | { 18 | public: 19 | Subject()=default; 20 | template 21 | void registerObserver(const Event& event, Observer&& observer) 22 | { 23 | observers_[event].push_back(std::forward(observer)); 24 | } 25 | template 26 | void registerObserver(Event&& event, Observer&& observer) 27 | { 28 | observers_[std::move(event)].push_back(std::forward(observer)); 29 | } 30 | 31 | void notify(const Event& event) const 32 | { 33 | for (const auto& obs : observers_.at(event)) obs(); 34 | } 35 | // disallow copying and assigning 36 | Subject(const Subject&)=delete; 37 | Subject& operator=(const Subject&)=delete; 38 | 39 | private: 40 | std::map>> observers_; 41 | }; 42 | 43 | #endif // SUBJECT_H_ 44 | -------------------------------------------------------------------------------- /Patterns/Observer/example1.cpp: -------------------------------------------------------------------------------- 1 | #include "Subject.h" // Our Subject class 2 | #include "EventType.h" // Our EventType enumeration 3 | #include // for std::function and std::bind 4 | #include 5 | 6 | void foo(int i) 7 | { 8 | std::cout << "foo( " << i << " )\n"; 9 | } 10 | 11 | void bar() 12 | { 13 | std::cout << "bar()\n"; 14 | } 15 | 16 | int main() 17 | { 18 | 19 | Subject s; 20 | s.registerObserver(EventType::GREEN, bar); 21 | s.registerObserver(EventType::ORANGE, std::bind(foo, 42)); 22 | s.registerObserver(EventType::RED, std::bind(foo, 12345)); 23 | 24 | s.notify(EventType::GREEN); 25 | s.notify(EventType::RED); 26 | s.notify(EventType::ORANGE); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Patterns/Observer/example2.cpp: -------------------------------------------------------------------------------- 1 | #include "Subject.h" // Our Subject class 2 | #include // for std::function and std::bind 3 | #include 4 | #include 5 | 6 | void foo(int i) 7 | { 8 | std::cout << "foo( " << i << " )\n"; 9 | } 10 | 11 | void bar() 12 | { 13 | std::cout << "bar()\n"; 14 | } 15 | 16 | int main() 17 | { 18 | 19 | Subject s; 20 | s.registerObserver("GREEN", bar); 21 | s.registerObserver("ORANGE", std::bind(foo, 42)); 22 | s.registerObserver("RED", std::bind(foo, 12345)); 23 | const std::string msg("Hello, RED!"); 24 | s.registerObserver("RED", [&msg]{std::cout << msg << std::endl;}); 25 | 26 | s.notify("GREEN"); 27 | s.notify("RED"); 28 | s.notify("ORANGE"); 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Patterns/ValuePtr/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -Wall -Wextra -Wuninitialized -pedantic-errors -std=c++11 -O -ggdb 2 | 3 | example0: value_ptr.hpp 4 | -------------------------------------------------------------------------------- /Patterns/ValuePtr/example0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "value_ptr.hpp" 3 | 4 | struct foo 5 | { 6 | foo() { std::cout << "foo()\n"; } 7 | foo(const foo&) { std::cout << "foo(const foo&)\n"; } 8 | foo& operator=(const foo&) { 9 | std::cout << "foo& operator=(const foo&)\n"; 10 | return *this; 11 | } 12 | virtual void hello() const { std::cout << "hello from foo\n"; } 13 | virtual ~foo() { std::cout << "~foo()\n"; } 14 | virtual foo* clone() { return new foo(*this); } 15 | }; 16 | 17 | struct bar : foo 18 | { 19 | bar() { std::cout << "bar()\n"; } 20 | bar(const bar& b) : foo(b) { std::cout << "bar(const bar&)\n"; } 21 | bar& operator=(const bar&) { 22 | std::cout << "bar& operator=(const bar&)\n"; 23 | return *this; 24 | } 25 | virtual void hello() const { std::cout << "hello from bar\n"; } 26 | virtual ~bar() { std::cout << "~bar()\n"; } 27 | virtual foo* clone() { return new bar(*this); } 28 | }; 29 | 30 | int main() 31 | { 32 | value_ptr a(new foo); 33 | value_ptr b(new bar); 34 | 35 | a->hello(); 36 | b->hello(); 37 | 38 | std::cout << "assigning b to a\n"; 39 | a = b; 40 | std::cout << "assigned b to a\n"; 41 | a->hello(); 42 | b->hello(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Patterns/ValuePtr/value_ptr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CPPBLOG_VALUE_PTR_HPP_ 2 | #define CPPBLOG_VALUE_PTR_HPP_ 3 | // 4 | // Copyright (c) 2015 Juan Palacios juan.palacios.puyana@gmail.com 5 | // Subject to the BSD 2-Clause License 6 | // - see < http://opensource.org/licenses/BSD-2-Clause> 7 | // 8 | 9 | #include // C++03 std::swap 10 | 11 | namespace blg 12 | { 13 | /// A trivial (and incomplete) C++03 value pointer example. 14 | /// 15 | /// Requires T to have a T* T::clone() member function. 16 | /// Intended for polymorphic types where value semantics are required. 17 | /// 18 | template 19 | struct value_ptr 20 | { 21 | typedef T* pointer; 22 | typedef T& reference; 23 | 24 | explicit value_ptr(pointer p) : ptr_(p) {} 25 | 26 | value_ptr(const value_ptr& other) : ptr_(other->clone()) {} 27 | 28 | value_ptr& operator=(value_ptr rhs) { 29 | swap(rhs); 30 | return *this; 31 | } 32 | 33 | ~value_ptr() { delete ptr_; } 34 | 35 | reference operator*() const { return *get(); } 36 | 37 | pointer operator->() const { return get(); } 38 | 39 | pointer get() const { return ptr_; } 40 | 41 | pointer release() 42 | { 43 | pointer old = ptr_; 44 | ptr_ = NULL; 45 | return old; 46 | } 47 | 48 | void reset(pointer p = pointer()) 49 | { 50 | std::swap(p, ptr_); 51 | delete p; 52 | } 53 | 54 | void swap(value_ptr& other) { std::swap(ptr_, other.ptr_); } 55 | 56 | private: 57 | pointer ptr_; 58 | }; 59 | 60 | } // namespace blg 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cppblog 2 | ======= 3 | 4 | Contains working code samples from my C++ blog, http://juanchopanzacpp.wordpress.com/. These examples might be slightly more elaborate than those from the blog, but the functionality is the same. C++11 support is assumed, and the samples have been tested with the latest versions of g++. 5 | -------------------------------------------------------------------------------- /WantSpeed/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | -------------------------------------------------------------------------------- /WantSpeed/results/binop1_clang.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Copy constructor 5 | ============================= 6 | Destructor 7 | Destructor 8 | Destructor 9 | ========== Bar ============== 10 | Default constructor 11 | Default constructor 12 | Copy constructor 13 | Move copy constructor 14 | Destructor 15 | ============================= 16 | Destructor 17 | Destructor 18 | Destructor 19 | -------------------------------------------------------------------------------- /WantSpeed/results/binop1_gcc.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Copy constructor 5 | ============================= 6 | Destructor 7 | Destructor 8 | Destructor 9 | ========== Bar ============== 10 | Default constructor 11 | Default constructor 12 | Copy constructor 13 | Move copy constructor 14 | Destructor 15 | ============================= 16 | Destructor 17 | Destructor 18 | Destructor 19 | -------------------------------------------------------------------------------- /WantSpeed/results/binop2_clang.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Default constructor 5 | Copy constructor 6 | Copy constructor 7 | Destructor 8 | ============================= 9 | Destructor 10 | Destructor 11 | Destructor 12 | Destructor 13 | ========== Bar ============== 14 | Default constructor 15 | Default constructor 16 | Default constructor 17 | Copy constructor 18 | Move copy constructor 19 | Move copy constructor 20 | Destructor 21 | Destructor 22 | ============================= 23 | Destructor 24 | Destructor 25 | Destructor 26 | Destructor 27 | -------------------------------------------------------------------------------- /WantSpeed/results/binop2_gcc.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Default constructor 5 | Copy constructor 6 | Copy constructor 7 | Destructor 8 | ============================= 9 | Destructor 10 | Destructor 11 | Destructor 12 | Destructor 13 | ========== Bar ============== 14 | Default constructor 15 | Default constructor 16 | Default constructor 17 | Copy constructor 18 | Move copy constructor 19 | Move copy constructor 20 | Destructor 21 | Destructor 22 | ============================= 23 | Destructor 24 | Destructor 25 | Destructor 26 | Destructor 27 | -------------------------------------------------------------------------------- /WantSpeed/results/binop_no_move1_clang.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Copy constructor 5 | ============================= 6 | Destructor 7 | Destructor 8 | Destructor 9 | ========== Bar ============== 10 | Default constructor 11 | Default constructor 12 | Copy constructor 13 | Copy constructor 14 | Destructor 15 | ============================= 16 | Destructor 17 | Destructor 18 | Destructor 19 | -------------------------------------------------------------------------------- /WantSpeed/results/binop_no_move1_gcc.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Copy constructor 5 | ============================= 6 | Destructor 7 | Destructor 8 | Destructor 9 | ========== Bar ============== 10 | Default constructor 11 | Default constructor 12 | Copy constructor 13 | Copy constructor 14 | Destructor 15 | ============================= 16 | Destructor 17 | Destructor 18 | Destructor 19 | -------------------------------------------------------------------------------- /WantSpeed/results/binop_no_move2_clang.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Default constructor 5 | Copy constructor 6 | Copy constructor 7 | Destructor 8 | ============================= 9 | Destructor 10 | Destructor 11 | Destructor 12 | Destructor 13 | ========== Bar ============== 14 | Default constructor 15 | Default constructor 16 | Default constructor 17 | Copy constructor 18 | Copy constructor 19 | Copy constructor 20 | Destructor 21 | Destructor 22 | ============================= 23 | Destructor 24 | Destructor 25 | Destructor 26 | Destructor 27 | -------------------------------------------------------------------------------- /WantSpeed/results/binop_no_move2_gcc.txt: -------------------------------------------------------------------------------- 1 | ========== Foo ============== 2 | Default constructor 3 | Default constructor 4 | Default constructor 5 | Copy constructor 6 | Copy constructor 7 | Destructor 8 | ============================= 9 | Destructor 10 | Destructor 11 | Destructor 12 | Destructor 13 | ========== Bar ============== 14 | Default constructor 15 | Default constructor 16 | Default constructor 17 | Copy constructor 18 | Copy constructor 19 | Copy constructor 20 | Destructor 21 | Destructor 22 | ============================= 23 | Destructor 24 | Destructor 25 | Destructor 26 | Destructor 27 | -------------------------------------------------------------------------------- /WantSpeed/results/results.txt: -------------------------------------------------------------------------------- 1 | ================================================================================================ 2 | 3 | Tesf of the effect of passing a parameter that is returned 4 | from a function or operator by value vs. passing by const reference. 5 | Inspired by the implementation 6 | 7 | T operator+(T lhs, const T& rhs) 8 | { 9 | lhs += rhs; 10 | return lhs; 11 | } 12 | 13 | 14 | Tested binary operators: 15 | 16 | Trad : T operator+(const& T lhs, const& T rhs); 17 | ByValue : T operator+(T lhs, const T& rhs); 18 | 19 | Trad makes local copy of lhs. Both use operator+= . 20 | 21 | Tested with G++ 4.8.2 and CLANG 3.4, both macports on Mac OSX. 22 | 23 | ================================================================================================ 24 | 25 | Case 1. 26 | 27 | Expressions of type 28 | T a, b; 29 | T c = a + b; 30 | T with (without) move copy and assignment. 31 | 32 | | Default Ctor | Copy Ctor | Move Copy Ctor | Destrictor | 33 | |---------------------------------------------------------- 34 | Trad (no move) | 2 (2) | 1 (1) | 0 (0) | 3 (3) | 35 | ByValue (no move) | 2 (2) | 1 (2) | 1 (0) | 4 (4) | 36 | 37 | ================================================================================================ 38 | 39 | Case 2. 40 | 41 | Expressions of type 42 | T a, b, c; 43 | T d = a + b + c; 44 | T with (without) move copy and assignment. 45 | 46 | | Default Ctor | Copy Ctor | Move Copy Ctor | Destrictor | 47 | |---------------------------------------------------------- 48 | Trad (no move) | 3 (3) | 2 (2) | 0 (0) | 5 (5) | 49 | ByValue (no move) | 3 (3) | 1 (3) | 2 (0) | 6 (6) | 50 | 51 | ================================================================================================ 52 | 53 | Case 3. 54 | 55 | Expressions of type 56 | T c = T() + T(); 57 | T with (without) move copy and assignment. 58 | 59 | | Default Ctor | Copy Ctor | Move Copy Ctor | Destrictor | 60 | |---------------------------------------------------------- 61 | Trad (no move) | 2 (2) | 1 (1) | 0 (0) | 3 (3) | 62 | ByValue (no move) | 2 (2) | 0 (1) | 1 (0) | 3 (3) | 63 | 64 | ================================================================================================ 65 | 66 | Case 4. 67 | 68 | Expressions of type 69 | T t = T() + T() + T() 70 | T with (without) move copy and assignment. 71 | 72 | | Default Ctor | Copy Ctor | Move Copy Ctor | Destrictor | 73 | |---------------------------------------------------------- 74 | Trad (no move) | 3 (3) | 2 (2) | 0 (0) | 5 (5) | 75 | ByValue (no move) | 3 (3) | 0 (2) | 2 (0) | 5 (5) | 76 | 77 | 78 | -------------------------------------------------------------------------------- /WantSpeed/src/Bar.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | struct Bar 5 | { 6 | Bar() { std::cout << "Default constructor\n"; } 7 | ~Bar() { std::cout << "Destructor\n"; } 8 | Bar(const Bar&) 9 | { 10 | std::cout << "Copy constructor\n"; 11 | } 12 | Bar(Bar&&) 13 | { 14 | std::cout << "Move copy constructor\n"; 15 | } 16 | Bar& operator=(const Bar&) 17 | { 18 | std::cout << "Assignment operator"; 19 | return *this; 20 | } 21 | Bar& operator=(Bar&&) 22 | { 23 | std::cout << "Move assignment operator\n"; 24 | return *this; 25 | } 26 | 27 | Bar& operator+=(const Bar&) 28 | { 29 | return *this; 30 | } 31 | }; 32 | 33 | 34 | Bar operator+(Bar lhs, const Bar& rhs) 35 | { 36 | lhs += rhs; 37 | return lhs; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /WantSpeed/src/Bar_no_move.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Bar 4 | { 5 | Bar() { std::cout << "Default constructor\n"; } 6 | ~Bar() { std::cout << "Destructor\n"; } 7 | Bar(const Bar&) 8 | { 9 | std::cout << "Copy constructor\n"; 10 | } 11 | 12 | Bar& operator=(const Bar&) 13 | { 14 | std::cout << "Assignment operator"; 15 | return *this; 16 | } 17 | 18 | Bar& operator+=(const Bar&) 19 | { 20 | return *this; 21 | } 22 | }; 23 | 24 | 25 | Bar operator+(Bar lhs, const Bar& rhs) 26 | { 27 | lhs += rhs; 28 | return lhs; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /WantSpeed/src/Foo.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo 4 | { 5 | Foo() { std::cout << "Default constructor\n"; } 6 | ~Foo() { std::cout << "Destructor\n"; } 7 | Foo(const Foo&) 8 | { 9 | std::cout << "Copy constructor\n"; 10 | } 11 | Foo(Foo&&) 12 | { 13 | std::cout << "Move copy constructor\n"; 14 | } 15 | Foo& operator=(const Foo&) 16 | { 17 | std::cout << "Assignment operator"; 18 | return *this; 19 | } 20 | Foo& operator=(Foo&&) 21 | { 22 | std::cout << "Move assignment operator\n"; 23 | return *this; 24 | } 25 | 26 | Foo& operator+=(const Foo&) 27 | { 28 | return *this; 29 | } 30 | }; 31 | 32 | 33 | Foo operator+(const Foo& lhs, const Foo& rhs) 34 | { 35 | Foo res = lhs; 36 | res += rhs; 37 | return res; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /WantSpeed/src/Foo_no_move.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Foo 4 | { 5 | Foo() { std::cout << "Default constructor\n"; } 6 | ~Foo() { std::cout << "Destructor\n"; } 7 | Foo(const Foo&) 8 | { 9 | std::cout << "Copy constructor\n"; 10 | } 11 | 12 | Foo& operator=(const Foo&) 13 | { 14 | std::cout << "Assignment operator"; 15 | return *this; 16 | } 17 | 18 | Foo& operator+=(const Foo&) 19 | { 20 | return *this; 21 | } 22 | }; 23 | 24 | 25 | Foo operator+(const Foo& lhs, const Foo& rhs) 26 | { 27 | Foo res = lhs; 28 | res += rhs; 29 | return res; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /WantSpeed/src/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS += -Wall -Wextra -Wconversion -Wno-missing-field-initializers -pedantic-errors -std=c++11 -O2 2 | 3 | case%_no_move : case%_no_move.cpp Bar_no_move.h Foo_no_move.h Makefile 4 | $(CXX) $(CXXFLAGS) $< -o $@ 5 | 6 | case% : case%.cpp Bar.h Foo.h Makefile 7 | $(CXX) $(CXXFLAGS) $< -o $@ 8 | 9 | -------------------------------------------------------------------------------- /WantSpeed/src/case1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar.h" 3 | #include "Foo.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo a, b; 11 | 12 | Foo c = a + b; 13 | 14 | std::cout << "=============================\n"; 15 | 16 | } 17 | 18 | 19 | void bar() 20 | { 21 | std::cout << "========== Bar ==============\n"; 22 | 23 | Bar a, b; 24 | 25 | Bar c = a + b; 26 | 27 | std::cout << "=============================\n"; 28 | 29 | } 30 | 31 | int main() 32 | { 33 | foo(); 34 | bar(); 35 | } 36 | -------------------------------------------------------------------------------- /WantSpeed/src/case1_no_move.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar_no_move.h" 3 | #include "Foo_no_move.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo a, b; 11 | 12 | Foo c = a + b; 13 | 14 | std::cout << "=============================\n"; 15 | 16 | } 17 | 18 | 19 | void bar() 20 | { 21 | std::cout << "========== Bar ==============\n"; 22 | 23 | Bar a, b; 24 | 25 | Bar c = a + b; 26 | 27 | std::cout << "=============================\n"; 28 | 29 | } 30 | 31 | int main() 32 | { 33 | foo(); 34 | bar(); 35 | } 36 | -------------------------------------------------------------------------------- /WantSpeed/src/case2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar.h" 3 | #include "Foo.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo a, b, c; 11 | 12 | Foo d = a + b + c; 13 | 14 | std::cout << "=============================\n"; 15 | 16 | } 17 | 18 | 19 | void bar() 20 | { 21 | std::cout << "========== Bar ==============\n"; 22 | 23 | Bar a, b, c; 24 | 25 | Bar d = a + b + c; 26 | 27 | std::cout << "=============================\n"; 28 | 29 | } 30 | 31 | int main() 32 | { 33 | foo(); 34 | bar(); 35 | } 36 | -------------------------------------------------------------------------------- /WantSpeed/src/case2_no_move.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar_no_move.h" 3 | #include "Foo_no_move.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo a, b, c; 11 | 12 | Foo d = a + b + c; 13 | 14 | std::cout << "=============================\n"; 15 | 16 | } 17 | 18 | 19 | void bar() 20 | { 21 | std::cout << "========== Bar ==============\n"; 22 | 23 | Bar a, b, c; 24 | 25 | Bar d = a + b + c; 26 | 27 | std::cout << "=============================\n"; 28 | 29 | } 30 | 31 | int main() 32 | { 33 | foo(); 34 | bar(); 35 | } 36 | -------------------------------------------------------------------------------- /WantSpeed/src/case3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar.h" 3 | #include "Foo.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo foo = Foo() + Foo(); 11 | 12 | std::cout << "=============================\n"; 13 | 14 | } 15 | 16 | 17 | void bar() 18 | { 19 | std::cout << "========== Bar ==============\n"; 20 | 21 | Bar b = Bar() + Bar(); 22 | 23 | std::cout << "=============================\n"; 24 | 25 | } 26 | 27 | int main() 28 | { 29 | foo(); 30 | bar(); 31 | } 32 | -------------------------------------------------------------------------------- /WantSpeed/src/case3_no_move.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar_no_move.h" 3 | #include "Foo_no_move.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo f = Foo() + Foo(); 11 | 12 | std::cout << "=============================\n"; 13 | 14 | } 15 | 16 | 17 | void bar() 18 | { 19 | std::cout << "========== Bar ==============\n"; 20 | 21 | Bar b = Bar() + Bar(); 22 | 23 | std::cout << "=============================\n"; 24 | 25 | } 26 | 27 | int main() 28 | { 29 | foo(); 30 | bar(); 31 | } 32 | -------------------------------------------------------------------------------- /WantSpeed/src/case4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar.h" 3 | #include "Foo.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo f = Foo() + Foo() + Foo(); 11 | 12 | std::cout << "=============================\n"; 13 | 14 | } 15 | 16 | 17 | void bar() 18 | { 19 | std::cout << "========== Bar ==============\n"; 20 | 21 | Bar b = Bar() + Bar() + Bar(); 22 | 23 | std::cout << "=============================\n"; 24 | 25 | } 26 | 27 | int main() 28 | { 29 | foo(); 30 | bar(); 31 | } 32 | -------------------------------------------------------------------------------- /WantSpeed/src/case4_no_move.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bar_no_move.h" 3 | #include "Foo_no_move.h" 4 | 5 | 6 | void foo() 7 | { 8 | std::cout << "========== Foo ==============\n"; 9 | 10 | Foo f = Foo() + Foo() + Foo(); 11 | 12 | std::cout << "=============================\n"; 13 | 14 | } 15 | 16 | 17 | void bar() 18 | { 19 | std::cout << "========== Bar ==============\n"; 20 | 21 | Bar b = Bar() + Bar() + Bar(); 22 | 23 | std::cout << "=============================\n"; 24 | 25 | } 26 | 27 | int main() 28 | { 29 | foo(); 30 | bar(); 31 | } 32 | --------------------------------------------------------------------------------