aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSvenson Han Göthel <[email protected]>2024-02-25 21:21:12 +0100
committerSvenson Han Göthel <[email protected]>2024-02-25 21:21:12 +0100
commit46b3474888f9e6a8051fccb4a19d7f2082e62ded (patch)
treeb42ab72e06d95b8ee8c1e5cd391744d3cba88399 /src
parent7a0938f88c7d4a96e560c701c5c5cad2ca610215 (diff)
parent79c1d779f4e10d04b158dc66745141550419e1f2 (diff)
Merge remote-tracking branch 'origin'
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/lesson20_oop_type.cpp282
-rw-r--r--src/lesson21_oop_inherit.cpp121
-rw-r--r--src/lesson22_oop_virtl01.cpp112
-rw-r--r--src/lesson23_oop_virtl02.cpp (renamed from src/lesson25_oop_virtl01.cpp)6
-rw-r--r--src/lesson24_oop_virtl03.cpp295
-rw-r--r--src/lesson40_algo01.cpp83
7 files changed, 897 insertions, 4 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6df62f9..de97e60 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,7 +3,7 @@ include_directories(
)
# These examples use the standard separate compilation
-file(GLOB_RECURSE SOURCES_IDIOMATIC_EXAMPLES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "lesson*.cpp")
+file(GLOB_RECURSE SOURCES_IDIOMATIC_EXAMPLES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "lesson*.cpp" "example*.cpp")
string( REPLACE ".cpp" "" BASENAMES_IDIOMATIC_EXAMPLES "${SOURCES_IDIOMATIC_EXAMPLES}" )
diff --git a/src/lesson20_oop_type.cpp b/src/lesson20_oop_type.cpp
new file mode 100644
index 0000000..fef1402
--- /dev/null
+++ b/src/lesson20_oop_type.cpp
@@ -0,0 +1,282 @@
+//============================================================================
+// Author : Sven Göthel
+// Copyright : 2024 Göthel Software e.K.
+// License : MIT
+// Description : C++ Lesson 2.0 OOP (integer class with operation overloading)
+//============================================================================
+
+#include <limits>
+#include <string>
+#include <memory>
+#include <cassert>
+#include <iostream>
+
+class sint_t {
+ private:
+ int64_t store;
+
+ public:
+ /** Default constructor (ctor) */
+ sint_t() noexcept
+ : store(0) { }
+
+ /** Copy ctor */
+ sint_t(const sint_t& o) noexcept
+ : store(o.store) { }
+
+ /** Destructor (dtor) */
+ ~sint_t() noexcept {}
+
+ /** Explicit conversion ctor: int64_t -> my_int_t */
+ explicit sint_t(const int64_t& o) noexcept
+ : store( o ) { }
+
+ //
+ // Logical operations
+ //
+
+ bool is_zero() const noexcept { return 0 == store; }
+
+ /** Explicit bool operator, returns `true` iff this is not zero, otherwise false. */
+ explicit operator bool() const noexcept { return !is_zero(); }
+
+ /** Not-bool operator, returns `true` iff this is zero, otherwise false. */
+ bool operator !() const noexcept { return is_zero(); }
+
+ //
+ // Comparison operations
+ //
+
+ /** Compare function returns 0 if equal, -1 if *this < b and 1 if *this > b. */
+ int compare(const sint_t& b) const noexcept {
+ return store == b.store ? 0 : ( store < b.store ? -1 : 1);
+ }
+
+ /** Two way comparison operator */
+ bool operator==(const sint_t& b) {
+ return store == b.store;
+ }
+
+ /** Three way std::strong_ordering comparison operator */
+ std::strong_ordering operator<=>(const sint_t& b) {
+ return store == b.store ? std::strong_ordering::equal : ( store < b.store ? std::strong_ordering::less : std::strong_ordering::greater);
+ }
+
+ //
+ // Assignment operations, including arithmetic assignments
+ //
+
+ /** Assignment */
+ sint_t& operator=(const sint_t& r) noexcept {
+ if( this != &r ) {
+ store = r.store;
+ }
+ return *this;
+ }
+
+ /** Addition assignment */
+ sint_t& operator+=(const sint_t& rhs ) noexcept {
+ store += rhs.store;
+ return *this;
+ }
+
+ /** Subtraction assignment */
+ sint_t& operator-=(const sint_t& rhs ) noexcept {
+ store -= rhs.store;
+ return *this;
+ }
+
+ /** Multiplication assignment */
+ sint_t& operator*=(const sint_t& rhs ) noexcept {
+ store *= rhs.store;
+ return *this;
+ }
+
+ /** Division assignment */
+ sint_t& operator/=(const sint_t& rhs ) noexcept {
+ store /= rhs.store;
+ return *this;
+ }
+
+ /** Remainder assignment */
+ sint_t& operator%=(const sint_t& rhs ) noexcept {
+ store %= rhs.store;
+ return *this;
+ }
+
+ //
+ // Unary arithmetic operations
+ //
+
+ /** Returns the signum, i.e. `-1` if negative, `0` if zero and `+1` if positive */
+ int signum() const noexcept { return 0 == store ? 0 : ( 0 > store ? -1 : +1 ); }
+
+ /** Returns `true` if positive, otherwise `false`. */
+ bool positive() const noexcept { return 0 <= store; }
+
+ /**
+ * Set signum of this integer
+ * @param new_signum new sign() to set, ignored if this instance is_zero()
+ */
+ void set_sign(const int new_signum) noexcept {
+ if( !is_zero() && new_signum != 0 ) {
+ store = std::abs(store) * new_signum;
+ }
+ }
+
+ /** Returns opposite of positive(), ignoring signum() `0` */
+ int reversed_sign() const noexcept {
+ if( positive() ) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ /** Flips the sign of this instance, returns *this */
+ sint_t& flip_sign() noexcept {
+ set_sign(reversed_sign());
+ return *this;
+ }
+
+ /** Unary positive operator, returns new instance of this. */
+ sint_t operator+() const noexcept { return sint_t(*this); }
+
+ /** Unary negation operator, returns new negative instance of this. */
+ sint_t operator-() const noexcept { return sint_t(*this).flip_sign(); }
+
+ /** Pre-increment unary operation */
+ sint_t& operator++() noexcept { ++store; return *this; }
+
+ /** Pre-decrement unary operation */
+ sint_t& operator--() noexcept { --store; return *this; }
+
+ /** Post-increment unary operation */
+ sint_t operator++(int) noexcept { sint_t x(*this); ++(*this); return x; }
+
+ /** Post-decrement unary operation */
+ sint_t operator--(int) noexcept { sint_t x(*this); --(*this); return x; }
+
+ //
+ // Misc operations
+ //
+
+ std::string to_string() const noexcept { return std::to_string(store); }
+};
+
+sint_t operator+(const sint_t& lhs, const sint_t& rhs ) noexcept {
+ sint_t r(lhs);
+ r += rhs;
+ return r;
+}
+
+sint_t operator-(const sint_t& lhs, const sint_t& rhs ) noexcept {
+ return sint_t(lhs) -= rhs;
+}
+
+sint_t operator*(const sint_t& lhs, const sint_t& rhs ) noexcept {
+ return sint_t(lhs) *= rhs;
+}
+
+sint_t operator/(const sint_t& lhs, const sint_t& rhs ) noexcept {
+ return sint_t(lhs) /= rhs;
+}
+
+std::ostream& operator<<(std::ostream& out, const sint_t& v) {
+ return out << v.to_string();
+}
+
+int main(int, char*[]) {
+ sint_t zero(0), ten(10), twenty(20), thirty(30), one(1), two(2);
+ std::cout << "zero = " << zero << std::endl;
+ std::cout << "ten = " << ten << std::endl;
+ std::cout << "twenty = " << twenty << std::endl;
+ std::cout << "thirty = " << thirty << std::endl;
+
+ //
+ // Logical operations
+ //
+ assert( !zero );
+ assert( ten );
+ assert( twenty );
+ assert( thirty );
+
+ //
+ // Comparison operations
+ //
+ assert( ten < twenty );
+ assert( ten <= ten );
+ assert( ten <= twenty );
+ assert( ten == ten );
+ assert( twenty > ten );
+ assert( twenty >= ten );
+ assert( twenty >= twenty );
+
+ //
+ // Assignment operations, including arithmetic assignments
+ //
+ {
+ sint_t t; t = ten;
+ assert( t == ten );
+ }
+ {
+ sint_t t(ten); t += twenty;
+ assert( t == thirty );
+ }
+ {
+ sint_t t(ten); t += twenty;
+ assert( t == thirty );
+ }
+ {
+ sint_t t(ten); t *= two;
+ assert( t == twenty );
+ }
+ {
+ sint_t t(twenty); t /= two;
+ assert( t == ten );
+ }
+ {
+ sint_t t(thirty); t %= twenty;
+ assert( t == ten );
+ }
+
+ //
+ // Unary arithmetic operations
+ //
+ sint_t minus_ten(-10), nine(9), eleven(11);
+ assert( ten == +ten );
+ assert( minus_ten == -ten );
+ assert( ten == -minus_ten );
+
+ {
+ sint_t t(ten);
+ assert( eleven == ++t );
+ assert( eleven == t );
+ }
+ {
+ sint_t t(ten);
+ assert( nine == --t );
+ assert( nine == t );
+ }
+ {
+ sint_t t(ten);
+ assert( ten == t++ );
+ assert( eleven == t );
+ }
+ {
+ sint_t t(ten);
+ assert( ten == t-- );
+ assert( nine == t );
+ }
+
+ //
+ // Binary arithmetic operations
+ //
+ assert( one + ten == eleven );
+ assert( eleven - one == ten );
+
+ assert( two * ten == twenty );
+ assert( twenty / two == ten );
+
+ return 0;
+}
diff --git a/src/lesson21_oop_inherit.cpp b/src/lesson21_oop_inherit.cpp
new file mode 100644
index 0000000..2bb4409
--- /dev/null
+++ b/src/lesson21_oop_inherit.cpp
@@ -0,0 +1,121 @@
+//============================================================================
+// Author : Sven Göthel
+// Copyright : 2024 Göthel Software e.K.
+// License : MIT
+// Description : C++ Lesson 2.1 OOP (simple class inheritance w/o virtual functions)
+//============================================================================
+
+#include <limits>
+#include <string>
+#include <memory>
+#include <cassert>
+#include <iostream>
+
+class creature_t {
+ protected:
+ typedef std::string (*to_string_func_t)(const creature_t&) noexcept;
+
+ private:
+ to_string_func_t m_to_string;
+ int m_init_lifetime_left;
+ int m_lifetime_left;
+
+ protected:
+ /** Custom constructor (ctor) */
+ creature_t(to_string_func_t to_string_func, int lifetime_left) noexcept
+ : m_to_string(to_string_func),
+ m_init_lifetime_left(lifetime_left),
+ m_lifetime_left(lifetime_left) {}
+
+ /** Copy ctor */
+ creature_t(const creature_t& o) noexcept = default;
+
+ public:
+ /** Destructor (dtor) */
+ ~creature_t() noexcept = default;
+
+ int total_lifetime() const noexcept { return m_init_lifetime_left; }
+ int lifetime_left() const noexcept { return m_lifetime_left; }
+ int age() const noexcept { return total_lifetime() - lifetime_left(); }
+ bool alive() const noexcept { return lifetime_left() > 0; }
+ std::string lifesign() const noexcept { return alive() ? "☀" : "✝"; }
+
+ /** Subtract given years of life and return whether there is lifetime left */
+ bool tick(int years) noexcept {
+ if( m_lifetime_left > years ) {
+ m_lifetime_left -= years;
+ return true;
+ } else {
+ m_lifetime_left = 0;
+ return false;
+ }
+ }
+
+ std::string to_substring() const noexcept {
+ return "age "+std::to_string(age())+"/"+std::to_string(total_lifetime());
+ }
+
+ std::string to_string() const noexcept {
+ return m_to_string(*this);
+ }
+};
+
+std::ostream& operator<<(std::ostream& out, const creature_t& v) {
+ return out << v.to_string();
+}
+
+class plant_t : public creature_t {
+ public:
+ /** Custom constructor (ctor) */
+ plant_t(int lifetime_left) noexcept
+ : creature_t(to_string_impl, lifetime_left) {}
+
+ /** Copy ctor */
+ plant_t(const plant_t& o) noexcept
+ : creature_t(o) { }
+
+ private:
+ static std::string to_string_impl(const creature_t& t) noexcept {
+ return "plant"+t.lifesign()+"["+t.to_substring()+"]";
+ }
+};
+
+class animal_t : public creature_t {
+ public:
+ /** Custom constructor (ctor) */
+ animal_t(int lifetime_left) noexcept
+ : creature_t(to_string_impl, lifetime_left) {}
+
+ /** Copy ctor */
+ animal_t(const creature_t& o) noexcept
+ : creature_t(o) { }
+
+ private:
+ static std::string to_string_impl(const creature_t& t) noexcept {
+ return "animal"+t.lifesign()+"["+t.to_substring()+"]";
+ }
+};
+
+int main(int, char*[]) {
+ plant_t p1(3);
+ animal_t a1(80);
+
+ std::cout << "00.p1 = " << p1 << std::endl;
+ std::cout << "00.a1 = " << a1 << std::endl;
+
+ creature_t& c1p1 = p1, &c2a1 = a1;
+ std::cout << "00.c1p1 = " << c1p1 << std::endl;
+ std::cout << "00.c2a1 = " << c2a1 << std::endl;
+
+ p1.tick(1);
+ a1.tick(1);
+ std::cout << "01.p1 = " << p1 << std::endl;
+ std::cout << "01.a1 = " << a1 << std::endl;
+
+ p1.tick(2);
+ a1.tick(79);
+ std::cout << "03.p1 = " << p1 << std::endl;
+ std::cout << "79.a1 = " << a1 << std::endl;
+
+ return 0;
+}
diff --git a/src/lesson22_oop_virtl01.cpp b/src/lesson22_oop_virtl01.cpp
new file mode 100644
index 0000000..32ec17a
--- /dev/null
+++ b/src/lesson22_oop_virtl01.cpp
@@ -0,0 +1,112 @@
+//============================================================================
+// Author : Sven Göthel
+// Copyright : 2024 Göthel Software e.K.
+// License : MIT
+// Description : C++ Lesson 2.2 OOP (inheritance w/ virtual functions)
+//============================================================================
+
+#include <limits>
+#include <string>
+#include <memory>
+#include <cassert>
+#include <iostream>
+
+class creature_t {
+ private:
+ int m_init_lifetime_left;
+ int m_lifetime_left;
+
+ protected:
+ /** Custom constructor (ctor) */
+ creature_t(int lifetime_left) noexcept
+ : m_init_lifetime_left(lifetime_left),
+ m_lifetime_left(lifetime_left) {}
+
+ /** Copy ctor */
+ creature_t(const creature_t& o) noexcept = default;
+
+ public:
+ /** Virtual destructor (dtor) */
+ virtual ~creature_t() noexcept = default;
+
+ int total_lifetime() const noexcept { return m_init_lifetime_left; }
+ int lifetime_left() const noexcept { return m_lifetime_left; }
+ int age() const noexcept { return total_lifetime() - lifetime_left(); }
+ bool alive() const noexcept { return lifetime_left() > 0; }
+ std::string lifesign() const noexcept { return alive() ? "☀" : "✝"; }
+
+ /** Subtract given years of life and return whether there is lifetime left */
+ bool tick(int years) noexcept {
+ if( m_lifetime_left > years ) {
+ m_lifetime_left -= years;
+ return true;
+ } else {
+ m_lifetime_left = 0;
+ return false;
+ }
+ }
+
+ /** Fully virtual to_string() method to be implemented in children classes */
+ virtual std::string to_string() const noexcept = 0;
+
+ protected:
+ std::string to_substring() const noexcept {
+ return "age "+std::to_string(age())+"/"+std::to_string(total_lifetime());
+ }
+};
+
+std::ostream& operator<<(std::ostream& out, const creature_t& v) {
+ return out << v.to_string();
+}
+
+class plant_t : public creature_t {
+ public:
+ /** Custom constructor (ctor) */
+ plant_t(int lifetime_left) noexcept
+ : creature_t(lifetime_left) {}
+
+ /** Copy ctor */
+ plant_t(const plant_t& o) noexcept
+ : creature_t(o) { }
+
+ /** Virtual to_string() override */
+ virtual std::string to_string() const noexcept override { return "plant"+lifesign()+"["+creature_t::to_substring()+"]"; }
+};
+
+class animal_t : public creature_t {
+ public:
+ /** Custom constructor (ctor) */
+ animal_t(int lifetime_left) noexcept
+ : creature_t(lifetime_left) {}
+
+ /** Copy ctor */
+ animal_t(const creature_t& o) noexcept
+ : creature_t(o) { }
+
+ /** Virtual to_string() override */
+ virtual std::string to_string() const noexcept override { return "animal"+lifesign()+"["+creature_t::to_substring()+"]"; }
+};
+
+int main(int, char*[]) {
+ plant_t p1(3);
+ animal_t a1(80);
+
+ std::cout << "00.p1 = " << p1 << std::endl;
+ std::cout << "00.a1 = " << a1 << std::endl;
+
+ creature_t& c1p1 = p1, &c2a1 = a1;
+ std::cout << "00.c1p1 = " << c1p1 << std::endl;
+ std::cout << "00.c2a1 = " << c2a1 << std::endl;
+
+ p1.tick(1);
+ a1.tick(1);
+ std::cout << "01.p1 = " << p1 << std::endl;
+ std::cout << "01.a1 = " << a1 << std::endl;
+
+ p1.tick(2);
+ a1.tick(79);
+ std::cout << "03.p1 = " << p1 << std::endl;
+ std::cout << "79.a1 = " << a1 << std::endl;
+
+ return 0;
+}
diff --git a/src/lesson25_oop_virtl01.cpp b/src/lesson23_oop_virtl02.cpp
index d97b8f0..cebe9c9 100644
--- a/src/lesson25_oop_virtl01.cpp
+++ b/src/lesson23_oop_virtl02.cpp
@@ -1,8 +1,8 @@
//============================================================================
-// Author : Sven Gothel
-// Copyright : 2022 Gothel Software e.K.
+// Author : Sven Göthel
+// Copyright : 2022 Göthel Software e.K.
// License : MIT
-// Description : C++ Lesson 2.5 OOP (virtual funcation call in ctor/dtor)
+// Description : C++ Lesson 2.3 OOP (inheritance w/ virtual function call in ctor/dtor)
//============================================================================
#include <iostream>
diff --git a/src/lesson24_oop_virtl03.cpp b/src/lesson24_oop_virtl03.cpp
new file mode 100644
index 0000000..0d4499c
--- /dev/null
+++ b/src/lesson24_oop_virtl03.cpp
@@ -0,0 +1,295 @@
+//============================================================================
+// Author : Sven Göthel
+// Copyright : 2024 Göthel Software e.K.
+// License : MIT
+// Description : C++ Lesson 2.4 OOP (inheritance w/ virtual lifecycle managment)
+//============================================================================
+
+#include <limits>
+#include <string>
+#include <memory>
+#include <vector>
+#include <atomic>
+#include <cassert>
+#include <iostream>
+
+class creature_t {
+ private:
+ static std::atomic_uint64_t next_instance;
+ uint64_t m_id;
+ int m_init_lifetime_left;
+ int m_init_childs_left;
+ int m_lifetime_left;
+ int m_childs_left;
+
+ protected:
+ /** Custom constructor (ctor) */
+ creature_t(int lifetime_left, int childs_left) noexcept
+ : m_id(++next_instance),
+ m_init_lifetime_left(lifetime_left), m_init_childs_left(childs_left),
+ m_lifetime_left(lifetime_left), m_childs_left(childs_left) {}
+
+ /** Copy ctor, actually creating a new life (asexual) w/ a new instance id() */
+ creature_t(const creature_t& o) noexcept
+ : m_id(++next_instance),
+ m_init_lifetime_left(o.m_init_lifetime_left), m_init_childs_left(o.m_init_childs_left),
+ m_lifetime_left(o.m_init_lifetime_left), m_childs_left(o.m_init_childs_left) {}
+
+ /** Copy ctor, actually creating a new life (sexual) w/ a new instance id() */
+ creature_t(const creature_t& a, const creature_t& b) noexcept
+ : m_id(++next_instance),
+ m_init_lifetime_left((a.m_init_lifetime_left+b.m_init_lifetime_left)/2),
+ m_init_childs_left((a.m_init_childs_left+b.m_init_childs_left)/2),
+ m_lifetime_left((a.m_init_lifetime_left+b.m_init_lifetime_left)/2),
+ m_childs_left((a.m_init_childs_left+b.m_init_childs_left)/2) {}
+
+ /** Move ctor */
+ creature_t(creature_t&& o) noexcept
+ : m_id(o.m_id), m_init_lifetime_left(o.m_lifetime_left), m_init_childs_left(o.m_childs_left),
+ m_lifetime_left(o.m_lifetime_left), m_childs_left(o.m_childs_left)
+ {
+ o.m_id = 0;
+ o.m_childs_left = 0;
+ o.m_lifetime_left = 0;
+ }
+
+ public:
+ /** Virtual destructor (dtor) */
+ virtual ~creature_t() noexcept = default;
+
+ /** reproduction type */
+ enum class repro_t {
+ /** asexual reproduction only */
+ asexual,
+ /** sexual reproduction only */
+ sexual,
+ /** asexual and sexual reproduction */
+ dual
+ };
+ /** Returns the reproduction type */
+ virtual repro_t repro_type() const noexcept = 0;
+
+ protected:
+ /** Fully virtual copy-ctor function (asexual) on this super class */
+ virtual std::shared_ptr<creature_t> new_instance() noexcept = 0;
+
+ /** Fully virtual copy-ctor function (sexual) on this super class */
+ virtual std::shared_ptr<creature_t> new_instance(const creature_t& o) noexcept = 0;
+
+ public:
+ /** create one offspring (asexual) if childs_left() > 0 and repro_type() is not repro_t::sexual, otherwise returns nullptr. */
+ std::shared_ptr<creature_t> procreate() noexcept {
+ if( repro_t::sexual != repro_type() &&
+ m_childs_left > 0 )
+ {
+ --m_childs_left;
+ return new_instance();
+ } else {
+ return nullptr;
+ }
+ }
+
+ /** create one offspring (sexual) if childs_left() > 0 and repro_type() is not repro_t::asexual, otherwise returns nullptr. */
+ std::shared_ptr<creature_t> procreate(creature_t& o) noexcept {
+ if( repro_t::asexual != repro_type() &&
+ m_childs_left > 0 && o.childs_left() > 0 )
+ {
+ --m_childs_left;
+ --o.m_childs_left;
+ return new_instance(o);
+ } else {
+ return nullptr;
+ }
+ }
+
+ /** returns the unique creature id */
+ uint64_t id() const noexcept { return m_id; }
+
+ int total_lifetime() const noexcept { return m_init_lifetime_left; }
+ int lifetime_left() const noexcept { return m_lifetime_left; }
+ int age() const noexcept { return total_lifetime() - lifetime_left(); }
+ bool alive() const noexcept { return lifetime_left() > 0; }
+ std::string lifesign() const noexcept { return alive() ? "☀" : "✝"; }
+
+ int total_childs() const noexcept { return m_init_childs_left; }
+ int childs_left() const noexcept { return m_childs_left; }
+ int children() const noexcept { return total_childs() - childs_left(); }
+
+ /** Subtract given years of life and return whether there is lifetime left */
+ bool tick(int years) noexcept {
+ if( m_lifetime_left > years ) {
+ m_lifetime_left -= years;
+ return true;
+ } else {
+ m_lifetime_left = 0;
+ return false;
+ }
+ }
+
+ /** Fully virtual to_string() method to be implemented in children classes */
+ virtual std::string to_string() const noexcept = 0;
+
+ protected:
+ std::string to_substring() const noexcept {
+ return "id "+std::to_string(id())+", age "+std::to_string(age())+"/"+std::to_string(total_lifetime())+", childs "+std::to_string(children())+"/"+std::to_string(total_childs());
+ }
+};
+std::atomic_uint64_t creature_t::next_instance;
+
+typedef std::shared_ptr<creature_t> shared_creature_t;
+
+std::ostream& operator<<(std::ostream& out, const creature_t& v) {
+ return out << v.to_string();
+}
+
+/**
+ * A plant_t creature_t type supporting both, asexual and sexual procreation.
+ */
+class plant_t : public creature_t {
+ public:
+ /** Custom constructor (ctor) */
+ plant_t(int lifetime_left, int childs_left) noexcept
+ : creature_t(lifetime_left, childs_left) {}
+
+ /** Move ctor */
+ plant_t(plant_t&& o) noexcept
+ : creature_t(std::move(o)) {}
+
+ virtual repro_t repro_type() const noexcept override { return repro_t::dual; }
+
+ /** Virtual to_string() override */
+ virtual std::string to_string() const noexcept override { return "plant"+lifesign()+"["+creature_t::to_substring()+"]"; }
+
+ protected:
+ /** Copy ctor, actually creating a new life (asexual) w/ a new instance id() */
+ plant_t(const plant_t& o) noexcept
+ : creature_t(o) { }
+
+ /** Copy ctor, actually creating a new life (sexual) w/ a new instance id() */
+ plant_t(const plant_t& a, const plant_t& b) noexcept
+ : creature_t(a, b) { }
+
+ /** Virtual new_copy() (asexual) override */
+ virtual std::shared_ptr<creature_t> new_instance() noexcept override {
+ return std::shared_ptr<plant_t>( new plant_t(*this) );
+ }
+
+ /** Virtual new_instance() (sexual) override */
+ virtual std::shared_ptr<creature_t> new_instance(const creature_t& o) noexcept override {
+ return std::shared_ptr<plant_t>( new plant_t(*this, *static_cast<const plant_t*>(&o)) );
+ }
+};
+
+/**
+ * An animal_t creature_t type supporting sexual procreation only
+ */
+class animal_t : public creature_t {
+ public:
+ /** Custom constructor (ctor) */
+ animal_t(int lifetime_left, int childs_left) noexcept
+ : creature_t(lifetime_left, childs_left) {}
+
+ /** Move ctor */
+ animal_t(animal_t&& o) noexcept
+ : creature_t(std::move(o)) {}
+
+ virtual repro_t repro_type() const noexcept override { return repro_t::sexual; }
+
+ /** Virtual to_string() override */
+ virtual std::string to_string() const noexcept override { return "animal"+lifesign()+"["+creature_t::to_substring()+"]"; }
+
+ protected:
+ /** Copy ctor, actually creating a new life (asexual) w/ a new instance id() */
+ animal_t(const animal_t& o) noexcept
+ : creature_t(o) { }
+
+ /** Copy ctor, actually creating a new life (sexual) w/ a new instance id() */
+ animal_t(const animal_t& a, const animal_t& b) noexcept
+ : creature_t(a, b) { }
+
+ /** Virtual new_copy() (asexual) override - returns nullptr */
+ virtual std::shared_ptr<creature_t> new_instance() noexcept override {
+ return std::shared_ptr<animal_t>();
+ }
+ /** Virtual new_instance() (sexual) override */
+ virtual std::shared_ptr<creature_t> new_instance(const creature_t& o) noexcept override {
+ return std::shared_ptr<animal_t>( new animal_t(*this, *static_cast<const animal_t*>(&o)) );
+ }
+};
+
+int main(int, char*[]) {
+ plant_t p1(3, 1000);
+ animal_t a1(80, 6), a2(40, 3);
+
+ std::cout << "00.p1 = " << p1 << std::endl;
+ std::cout << "00.a1 = " << a1 << std::endl;
+ std::cout << "00.a2 = " << a2 << std::endl;
+
+ creature_t& c1p1 = p1, &c2a1 = a1;
+ std::cout << "00.c1p1 = " << c1p1 << std::endl;
+ std::cout << "00.c2a1 = " << c2a1 << std::endl;
+
+ p1.tick(1);
+ a1.tick(1);
+ a2.tick(2);
+ std::cout << "01.p1 = " << p1 << std::endl;
+ std::cout << "01.a1 = " << a1 << std::endl;
+ std::cout << "01.a2 = " << a2 << std::endl;
+
+ shared_creature_t p2 = p1.procreate();
+ assert( nullptr != p2 );
+ std::cout << "00.p2 = " << *p2 << std::endl;
+ {
+ // casting shared_ptr<super-class> to shared_ptr<sub-class> is possible, if you must
+ std::shared_ptr<plant_t> p2_plant = std::static_pointer_cast<plant_t>( p2 );
+ assert( nullptr != p2_plant );
+ }
+ {
+ shared_creature_t a12 = a1.procreate(); // only sexual procreation supported for this animal_t
+ assert( nullptr == a12 );
+ }
+ shared_creature_t a12 = a1.procreate(a2);
+ assert( nullptr != a12 );
+ std::cout << "00.a12 = " << *a12 << std::endl;
+
+ p1.tick(2);
+ a1.tick(79);
+ std::cout << "03.p1 = " << p1 << std::endl;
+ std::cout << "79.a1 = " << a1 << std::endl;
+
+ p2->tick(3);
+ std::cout << "03.p2 = " << *p2 << std::endl;
+ {
+ std::vector<shared_creature_t> a12childs;
+ {
+ shared_creature_t c;
+ while( nullptr != ( c = a12->procreate(a1) ) ) {
+ a12childs.push_back(c);
+ }
+ assert( 0 < a12childs.size() );
+ }
+ std::cout << "00.a12 = " << *a12 << ", created "+std::to_string(a12childs.size()) << std::endl;
+ for(shared_creature_t c : a12childs) {
+ std::cout << "00.a12.c = " << *c << std::endl;
+ }
+ a12->tick(60);
+ std::cout << "60.a12 = " << *a12 << std::endl;
+ }
+
+ {
+ // animal_t a3(80, 4);
+ // animal_t a3b(a3); // error, copy-ctor is non-public
+ }
+ {
+ animal_t a3(80, 4);
+ animal_t a3b(std::move(a3));
+ std::cout << "00.a3 = " << a3 << " -> " << a3b << std::endl;
+ }
+ {
+ animal_t a3(80, 4);
+ animal_t a3b = std::move(a3);
+ std::cout << "00.a3 = " << a3 << " -> " << a3b << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/lesson40_algo01.cpp b/src/lesson40_algo01.cpp
new file mode 100644
index 0000000..a701166
--- /dev/null
+++ b/src/lesson40_algo01.cpp
@@ -0,0 +1,83 @@
+//============================================================================
+// Author : Svenson Han Göthel and Sven Göthel
+// Version : 0.1
+// Copyright : MIT
+// Description : C++ Lesson 4.0 Simple algorithms using C++
+//============================================================================
+
+#include <cstdio>
+#include <iostream>
+#include <cmath>
+#include <vector>
+
+#include <limits>
+
+/**
+ * Lesson 4.0
+ *
+ * Implementing simple algorithms
+ */
+
+int binary_search(const std::vector<int>& array, int target) {
+ int l = 0;
+ int h = array.size()-1;
+ int i;
+ while( l <= h ) {
+ i = ( l + h ) / 2;
+ if ( array[i] < target ) {
+ l = i + 1;
+ } else if ( array[i] > target ) {
+ h = i - 1;
+ } else {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool test_binsearch(const std::vector<int>& array, int target, int exp, int& has) {
+ has = binary_search(array, target);
+ if( exp != has ) {
+ printf("Error-1: has %d != exp %d\n", has, exp);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+int main(int, const char**) {
+ int error_counter = 0;
+ {
+ std::vector<int> array = { 1, 3, 4, 5, 6, 9, 11 };
+ for(size_t i=0; i < array.size(); ++i) {
+ const int target = array[i];
+ int idx;
+ if( !test_binsearch(array, target, i, idx) ) {
+ std::cout << "ERROR: array[" << i << "] = " << target << " found at " << idx << std::endl;
+ ++error_counter;
+ } else {
+ std::cout << "OK : array[" << i << "] = " << target << " found at " << idx << std::endl;
+ }
+ }
+ {
+ std::vector<int> targets2 = { 0, 2, 7, 8, 10, 12 };
+ for(size_t i=0; i < targets2.size(); ++i) {
+ const int target = targets2[i];
+ int idx;
+ if( !test_binsearch(array, target, -1, idx) ) {
+ std::cout << "ERROR: " << target << " found at " << idx << std::endl;
+ ++error_counter;
+ } else {
+ std::cout << "OK : " << target << " not found, idx " << idx << std::endl;
+ }
+ }
+ }
+ }
+ if( 0 == error_counter ) {
+ std::cout << "No error" << std::endl;
+ return 0;
+ } else {
+ std::cout << error_counter << " error(s)" << std::endl;
+ return 1;
+ }
+}