diff --git a/code/include/print_tuple.hh b/code/include/print_tuple.hh
new file mode 100644
index 0000000000000000000000000000000000000000..7ea143f130ef4df6ff44b98a06b99cf54eb0130b
--- /dev/null
+++ b/code/include/print_tuple.hh
@@ -0,0 +1,26 @@
+#pragma once
+#include <tuple>
+#include <iostream>
+#include <iomanip>
+
+template <class ... Args>
+std::ostream & operator<<(std::ostream & strm, const std::tuple<Args...> & t)
+{
+    using namespace std;
+    auto print_one = [&strm](const auto & onearg) -> ostream & {
+        using bare_type = remove_cv_t<remove_reference_t<decltype(onearg)>>;
+        if constexpr (is_same_v<bare_type, string>)
+            strm << quoted(onearg);
+        else
+            strm << onearg;
+        return strm;
+    };
+    auto print_components = [&](const auto & ... args){
+       ((print_one(args) << ", "), ...);
+    };
+    strm << "[";
+    apply(print_components, t);
+    return strm <<"]";
+}
+
+
diff --git a/day3/ProgrammingInCXX_d3.pdf b/day3/ProgrammingInCXX_d3.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..d968dd99417b38ecadc820da270582d189a5ddd6
Binary files /dev/null and b/day3/ProgrammingInCXX_d3.pdf differ
diff --git a/day3/examples/fold_xpr_demo.cc b/day3/examples/fold_xpr_demo.cc
new file mode 100644
index 0000000000000000000000000000000000000000..17d4fd723b5e7392c9b721ead70304451fa34348
--- /dev/null
+++ b/day3/examples/fold_xpr_demo.cc
@@ -0,0 +1,26 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+template <typename... Args>
+auto add_up(Args... args)
+{
+    return (args + ...);
+}
+
+template <typename T, typename... Args>
+void push_back(std::vector<T> &v, Args ... args) {
+    (v.push_back(args), ...);
+}
+
+auto main() -> int
+{
+    using namespace std;
+    string firstname{ "Steve" }, lastname{ "Rogers" };
+    cout << add_up(1, 2, 3, 4, 5) << "\n";
+    cout << add_up(firstname, " ", lastname) << "\n";
+
+    std::vector<double> q{0.0};
+    push_back(q, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8);
+    for (auto d : q) cout << d << "\n";
+}
diff --git a/day3/examples/fold_xpr_demo2.cc b/day3/examples/fold_xpr_demo2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6750d6471068be3bd18f4b1d77b3296fce7e4297
--- /dev/null
+++ b/day3/examples/fold_xpr_demo2.cc
@@ -0,0 +1,25 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+auto add_up(auto... args)
+{
+    return (args + ...);
+}
+
+template <typename T>
+void push_back(std::vector<T> &v, auto ... args) {
+    (v.push_back(args), ...);
+}
+
+auto main() -> int
+{
+    using namespace std;
+    string firstname{ "Steve" }, lastname{ "Rogers" };
+    cout << add_up(1, 2, 3, 4, 5) << "\n";
+    cout << add_up(firstname, " ", lastname) << "\n";
+
+    std::vector<double> q{0.0};
+    push_back(q, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8);
+    for (auto d : q) cout << d << "\n";
+}
diff --git a/day3/examples/fold_xpr_demo3.cc b/day3/examples/fold_xpr_demo3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2c7f4c3ae73a6c92eba1cfac75b920ae7e5ce257
--- /dev/null
+++ b/day3/examples/fold_xpr_demo3.cc
@@ -0,0 +1,20 @@
+#include <vector>
+#include <iostream>
+#include <algorithm>
+#include <ranges>
+#include <string>
+#include "print_tuple.hh"
+
+auto max_of_multiple(auto ... containers)
+{
+    return std::make_tuple(std::ranges::max(containers) ...);
+}
+
+auto main() -> int
+{
+    std::vector v1{8.2, 84., 9.1, 33.1, 9.33, 8.2, 8.3};
+    std::vector v2{9,1,2,8,3,1,4,2,0,8,1};
+    std::vector<std::string> v3{"Compact", "code", "with", "fold", "expressions"};
+    std::cout << max_of_multiple(v1, v2, v3) << "\n";
+}
+
diff --git a/day3/examples/fold_xpr_demo4.cc b/day3/examples/fold_xpr_demo4.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bd916005dc0a2f313464584596f9d86ec006d03f
--- /dev/null
+++ b/day3/examples/fold_xpr_demo4.cc
@@ -0,0 +1,32 @@
+#include <vector>
+#include <iostream>
+#include <ranges>
+#include <algorithm>
+#include "range_output.hh"
+
+auto conv(const std::vector<double>& inp, auto ... shift)
+{
+    namespace sr = std::ranges;
+    namespace sv = std::views;
+    std::vector<double> out(inp.size(), 0.);
+    auto res_exp = sv::iota(0, static_cast<int>(inp.size())) 
+        | sv::transform([inp, shift...](auto index){
+            auto S = inp.size();
+            return (inp[(index + shift) > 0 ? (index + shift) % S : S + (index + shift) % S] + ...) 
+                    / (sizeof ... (shift));
+        }); 
+
+    sr::copy(res_exp, out.begin());
+    return out;
+}
+
+auto main() -> int
+{
+    std::vector v(21UL, 0.);
+    v[10] = 1.0;
+    for (auto i = 0UL; i < 10; ++i) {
+        v = conv(v, 0, 1, 2);
+        std::cout << "After round " << i << ", v = " << output::comma_separated << v << "\n";
+    }
+}
+
diff --git a/day3/examples/foldex.cc b/day3/examples/foldex.cc
new file mode 100644
index 0000000000000000000000000000000000000000..956591ee5a4bc59e404e797d659804783da8e3bf
--- /dev/null
+++ b/day3/examples/foldex.cc
@@ -0,0 +1,26 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+template <typename... Args>
+auto add_up(Args... args)
+{
+    return (args + ...);
+}
+
+template <typename T, typename... Args>
+void push_back(std::vector<T> &v, Args ... args) {
+    (v.push_back(args), ...);
+}
+
+int main()
+{
+    using namespace std;
+    string firstname{ "Steve" }, lastname{ "Rogers" };
+    cout << add_up(1, 2, 3, 4, 5) << "\n";
+    cout << add_up(firstname, " ", lastname) << "\n";
+
+    std::vector<double> q{0.0};
+    push_back(q, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8);
+    for (auto d : q) cout << d << "\n";
+}
diff --git a/day3/examples/foldex_3.cc b/day3/examples/foldex_3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fad515b1b5f2fbab22200fcf6f81443e606fc6be
--- /dev/null
+++ b/day3/examples/foldex_3.cc
@@ -0,0 +1,13 @@
+// examples/foldex_3.cc
+#include <algorithm>
+template <class First, class... Args>
+auto min(First first, Args... args)
+{
+    First retval = first;
+    ((retval = std::min(retval, args)), ...);
+    return retval;
+}
+int main()
+{
+    return min(8, 3, 4, 7, 2, 7) + min(2, 3, 9, 1);
+}
diff --git a/day3/examples/gcd_w_concepts.cc b/day3/examples/gcd_w_concepts.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fc739673145381c813c1dca8b703dc25122c7a27
--- /dev/null
+++ b/day3/examples/gcd_w_concepts.cc
@@ -0,0 +1,17 @@
+#include <type_traits>
+#include <iostream>
+
+template <class T>
+concept Integral = std::is_integral_v<T>;
+
+constexpr auto gcd(Integral auto a, Integral auto b) {
+    if (b == 0) return a;
+    else return gcd(b, a % b);
+}
+auto main() -> int
+{    
+    // Wont compile, until both the following arguments
+    // are changed into integral types.
+    std::cout << gcd(149935, 47295.) << "\n";
+}
+
diff --git a/day3/examples/generic_func1.cc b/day3/examples/generic_func1.cc
new file mode 100644
index 0000000000000000000000000000000000000000..def161da752c0ab975437934a4755a4b7e324ec2
--- /dev/null
+++ b/day3/examples/generic_func1.cc
@@ -0,0 +1,25 @@
+#include <iostream>
+#include <string>
+
+auto f(auto i1, auto i2)
+{
+    return i1 + i2;
+}
+
+// Same as above, but enforce that the parameters have the same type
+template <class T>
+auto g(T i1, T i2)
+{
+    return i1 + i2;
+}
+
+int main()
+{
+    using namespace std::string_literals;
+    std::cout << f(1, 2) << "\n";
+    std::cout << f(1.2, 2.2) << "\n";
+    std::cout << f("1"s, "2"s) << "\n";
+    //std::cout << f("1"s, 2) << "\n"; // Does not work
+    std::cout << g("1"s, 2) << "\n"; // Does not work, but better errors
+}
+
diff --git a/day3/examples/generic_func2.cc b/day3/examples/generic_func2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4610e8bccfdc9e96fba1636f215c93f0013cae6e
--- /dev/null
+++ b/day3/examples/generic_func2.cc
@@ -0,0 +1,24 @@
+#include <iostream>
+#include <string>
+
+// Same as above, but enforce that the parameters have the same type
+template <class T>
+auto f(T i1, T i2)
+{
+    return i1 + i2;
+}
+
+int main()
+{
+    using namespace std::string_literals;
+    std::cout << f("1", "2") << "\n"; 
+    // Does not work, because it's an invalid use for the function f, we wrote that for things which are addable.
+    // How did we try to indicate this intention of "addability" of the arguments ?
+    // Answer : We didn't!
+    // If the function had been 50 lines instead of 1, the real error would be very hard to
+    // decipher. There is an assumption regarding incoming arguments in our function template,
+    // and we did not specify that assumption anywhere. How does one indicate such constraints ?
+    // Answer(C++20) : concepts
+    // Answer(C++ < C++20) : std::enable_if, type_traits and some acrobatic programming.
+}
+
diff --git a/day3/examples/generic_func3.cc b/day3/examples/generic_func3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d152a8cf1486ae6eec10405532aba040bcd2aa8d
--- /dev/null
+++ b/day3/examples/generic_func3.cc
@@ -0,0 +1,22 @@
+#include <iostream>
+#include <string>
+#include <concepts>
+
+template <class T>
+concept Addable = requires(T a, T b) {
+    { a + b } -> std::convertible_to<T>;
+};
+
+auto f(Addable auto i1, Addable auto i2)
+{
+    return i1 + i2;
+}
+
+int main()
+{
+    using namespace std::string_literals;
+    std::cout << f(1, 2) << "\n"; 
+    std::cout << f("1"s, "2"s) << "\n"; 
+    std::cout << f("1", "2") << "\n"; 
+}
+
diff --git a/day3/examples/generic_func4.cc b/day3/examples/generic_func4.cc
new file mode 100644
index 0000000000000000000000000000000000000000..79b252948079ab42c380b3211cdb3d8e75f19d56
--- /dev/null
+++ b/day3/examples/generic_func4.cc
@@ -0,0 +1,31 @@
+#include <iostream>
+#include <string>
+
+template <class T>
+concept Addable = requires(T a, T b) {
+    { a + b } ;
+};
+
+
+template <class T> concept NotAddable = not Addable<T>;
+
+auto f(Addable auto i1, Addable auto i2)
+{
+    std::cout << "(using version of function f with Addable parameters) ... ";
+    return i1 + i2;
+}
+
+auto f(NotAddable auto i1, NotAddable auto i2)
+{
+    std::cout << "(using version of function f with NotAddable parameters) ... ";
+    return i1;
+}
+
+int main()
+{
+    using namespace std::string_literals;
+    std::cout << "f(1, 2) --> " << f(1, 2) << "\n"; 
+    std::cout << R"(f("1"s, "2"s) --> )" << f("1"s, "2"s) << "\n"; 
+    std::cout << R"(f("1", "2") --> )" << f("1", "2") << "\n"; 
+}
+
diff --git a/day3/examples/ipsum.txt b/day3/examples/ipsum.txt
new file mode 100644
index 0000000000000000000000000000000000000000..532d31a7cbdf7eb870f9a634f9055d03e604ddba
--- /dev/null
+++ b/day3/examples/ipsum.txt
@@ -0,0 +1,24 @@
+Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque 
+laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi 
+architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas 
+sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione 
+voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit 
+amet consectetur adipisci[ng] velit, sed quia non numquam [do] eius modi tempora 
+inci[di]dunt, ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima 
+veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid 
+ex ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in ea voluptate 
+velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo 
+voluptas nulla pariatur?
+
+At vero eos et accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium 
+voluptatum deleniti atque corrupti, quos dolores et quas molestias excepturi sint, 
+obcaecati cupiditate non provident, similique sunt in culpa, qui officia deserunt 
+mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et 
+expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio, cumque 
+nihil impedit, quo minus id, quod maxime placeat, facere possimus, omnis voluptas 
+assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis 
+debitis aut rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint et 
+molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut 
+reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores 
+repellat ...
+
diff --git a/day3/examples/lambda_captures.cc b/day3/examples/lambda_captures.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2cb21b4124df8a5199425ca61019fd80e661eed8
--- /dev/null
+++ b/day3/examples/lambda_captures.cc
@@ -0,0 +1,18 @@
+#include "Vbose.hh"
+
+auto main() -> int
+{
+
+    std::cout << "Declaring lambda function {\n";
+    Vbose locvar{ "dinosaur" };
+    auto lambda = [=](int i) {
+        std::cout << "\nIn lambda function, captured value of locvar is : "
+                  << locvar.getval() << "\n";
+        return i * i * i;
+    };
+    std::cout << "Declaring lambda function }\n";
+
+    std::cout << "Calling lambda function {\n";
+    std::cout << 5 << " -> " << lambda(5) << "\n";
+    std::cout << "Calling lambda function }\n";
+}
diff --git a/day3/examples/mutable_lambdas.cc b/day3/examples/mutable_lambdas.cc
new file mode 100644
index 0000000000000000000000000000000000000000..95be9dc59bb654b20e05216f417f5dc0d965ca2c
--- /dev/null
+++ b/day3/examples/mutable_lambdas.cc
@@ -0,0 +1,27 @@
+#include <algorithm>
+#include <iostream>
+#include <vector>
+#include <utility>
+
+int main()
+{
+    using namespace std;
+    vector<unsigned long> v, w;
+    generate_n(back_inserter(v), 100, [i = 0UL]() mutable {
+        ++i;
+        return i * i;
+    });
+    // v = [1, 4, 9, 16 ... ]
+    std::cout << " v = \n";
+    for (auto el : v)
+        std::cout << el << "\n";
+    generate_n(back_inserter(w), 50, [ i = 0UL, j = 1UL ]() mutable {
+        i = std::exchange(j, j + i);
+        return i;
+    });
+    // w = [1, 1, 2, 3, 5, 8, 11 ...]
+
+    std::cout << " w = \n";
+    for (auto el : w)
+        std::cout << el << "\n";
+}
diff --git a/day3/examples/no_textsub.cc b/day3/examples/no_textsub.cc
new file mode 100644
index 0000000000000000000000000000000000000000..64e5097e3156445db8f2e1b7b83e0614e94634a4
--- /dev/null
+++ b/day3/examples/no_textsub.cc
@@ -0,0 +1,12 @@
+template <unsigned N> constexpr unsigned fact = N * fact<N-1>;
+template <> constexpr unsigned fact<0> = 1U;
+static_assert(fact<7> == 5040);
+template <class A, class B>
+constexpr auto are_same = false;
+template <class A>
+constexpr auto are_same<A, A> = true;
+//static_assert(are_same<int, unsigned int>);
+using Integer = int;
+static_assert(are_same<int, Integer>);
+auto main() -> int {}
+
diff --git a/day3/examples/overload_w_concepts.cc b/day3/examples/overload_w_concepts.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ab44329122eab83ba248ea1e6eaed4b87ca1a760
--- /dev/null
+++ b/day3/examples/overload_w_concepts.cc
@@ -0,0 +1,29 @@
+// examples/overload_w_concepts.cc
+#include <iostream>
+#include <type_traits>
+#include <string>
+#include <boost/type_index.hpp>
+
+template <class N> concept Number = std::is_floating_point_v<N> || std::is_integral_v<N>;
+template <class N> concept NotNumber = not Number<N>; 
+
+using namespace boost::typeindex;
+auto proc(Number auto&& x) -> void
+{
+    std::cout << "Called proc for numbers with " << x << " of typeid " << type_id_runtime(x) << "\n";
+}
+auto proc(NotNumber auto&& x) -> void
+{
+    std::cout << "Called proc for non-numbers with " << x << " of typeid " << type_id_runtime(x) << "\n";
+}
+
+auto main() -> int
+{
+    using namespace std::string_literals;
+    proc(-1);
+    proc(88UL);
+    proc("0118 999 88191 9119725 3");
+    proc(3.141);
+    proc("eighty"s);
+}
+
diff --git a/day3/examples/print_tuple.cc b/day3/examples/print_tuple.cc
new file mode 100644
index 0000000000000000000000000000000000000000..20378aa1d6c9011b3f558b4363a1390a5e508d40
--- /dev/null
+++ b/day3/examples/print_tuple.cc
@@ -0,0 +1,33 @@
+#include <iostream>
+#include <string>
+#include <tuple>
+
+template <int idx, int MAX, typename... Args>
+struct PRINT_TUPLE {
+    static void print(std::ostream& strm, const std::tuple<Args...>& t)
+    {
+        strm << std::get<idx>(t) << (idx + 1 == MAX ? "" : ", ");
+        PRINT_TUPLE<idx + 1, MAX, Args...>::print(strm, t);
+    }
+};
+
+template <int MAX, typename... Args>
+struct PRINT_TUPLE<MAX, MAX, Args...> {
+    static void print(std::ostream& strm, const std::tuple<Args...>& t)
+    {
+    }
+};
+
+template <typename... Args>
+std::ostream& operator<<(std::ostream& strm, const std::tuple<Args...>& t)
+{
+    strm << "[";
+    PRINT_TUPLE<0, sizeof...(Args), Args...>::print(strm, t);
+    return strm << "]";
+}
+
+//int main()
+//{
+//    std::tuple<int, std::string, double, int, double > t{23,"abc",3.141, 3, 2.718};
+//    std::cout << t << "\n";
+//}
diff --git a/day3/examples/print_tuple_cxx17.cc b/day3/examples/print_tuple_cxx17.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d45bfc0c5676caa45461ab225495ee1c0992fdfb
--- /dev/null
+++ b/day3/examples/print_tuple_cxx17.cc
@@ -0,0 +1,32 @@
+#include <iostream>
+#include <string>
+#include <tuple>
+
+template <int idx, int MAX, typename... Args>
+struct PRINT_TUPLE {
+    static void print(std::ostream& strm, const std::tuple<Args...>& t)
+    {
+        if
+            constexpr(idx < MAX)
+            {
+                strm << std::get<idx>(t);
+                if
+                    constexpr((idx + 1) < MAX) strm << ", ";
+                PRINT_TUPLE<idx + 1, MAX, Args...>::print(strm, t);
+            }
+    }
+};
+
+template <typename... Args>
+auto operator<<(std::ostream& strm, const std::tuple<Args...>& t) -> std::ostream&
+{
+    strm << "[";
+    PRINT_TUPLE<0, sizeof...(Args), Args...>::print(strm, t);
+    return strm << "]";
+}
+
+auto main() -> int
+{
+    std::tuple<int, std::string, double, int, double> t{ 23, "abc", 3.141, 3, 2.718 };
+    std::cout << t << "\n";
+}
diff --git a/day3/examples/print_tuple_foldex.cc b/day3/examples/print_tuple_foldex.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2483331ba8a14cf176596c2d19612807523d56ad
--- /dev/null
+++ b/day3/examples/print_tuple_foldex.cc
@@ -0,0 +1,31 @@
+#include <tuple>
+#include <iostream>
+#include <iomanip>
+
+template <class ... Args>
+auto operator<<(std::ostream & strm, const std::tuple<Args...> & t) -> std::ostream & 
+{
+    using namespace std;
+    auto print_one = [&strm](const auto & onearg) -> ostream & {
+        using bare_type = remove_cv_t<remove_reference_t<decltype(onearg)>>;
+        if constexpr (is_same_v<bare_type, string>)
+            strm << quoted(onearg);
+        else
+            strm << onearg;
+        return strm;
+    };
+    auto print_components = [&](const auto & ... args){
+       ((print_one(args) << ", "), ...);
+    };
+    strm << "[";
+    apply(print_components, t);
+    return strm <<"]";
+}
+
+auto main() -> int
+{
+    std::tuple t1{1, "one"};
+    std::tuple t2{2, "two", "II", 2.0};
+    std::cout << t1 << "\t" << t2 << "\n";
+}
+
diff --git a/day3/examples/saxpy2.cc b/day3/examples/saxpy2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a1cbf3bfa9c8e0c37a28633f078e0eb1a4e6da4e
--- /dev/null
+++ b/day3/examples/saxpy2.cc
@@ -0,0 +1,20 @@
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <ranges>
+#include <vector>
+
+auto main() -> int
+{
+    const std::vector inp1 { 1., 2., 3., 4., 5. };
+    const std::vector inp2 { 9., 8., 7., 6., 5. };
+    std::vector outp(inp1.size(), 0.);
+    auto saxpy = []<class T, class T_in, class T_out>
+        (T a, const T_in& x, const T_in& y, T_out& z) {
+        std::transform(x.begin(), x.end(), y.begin(), z.begin(),
+            [a](T X, T Y) { return a * X + Y; });
+    };
+    std::ostream_iterator<double> cout { std::cout, "\n" };
+    saxpy(10., inp1, inp2, outp);
+    copy(outp.begin(), outp.end(), cout);
+}
diff --git a/day3/examples/static_assert0.cc b/day3/examples/static_assert0.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fad5884d097b20e2ebe0a0841ac66edad8f6c944
--- /dev/null
+++ b/day3/examples/static_assert0.cc
@@ -0,0 +1,7 @@
+double advance(unsigned long L)
+{
+    static_assert(sizeof(L) >= 8, "long must be at least 8 bytes. ");
+    //Bit manipulation assuming "long" is at least 8 bytes
+    return static_cast<double>(L);
+}
+int main() {}
diff --git a/day3/examples/static_assert1.cc b/day3/examples/static_assert1.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7c63bb433cab16444ad687c3aa2487e9c36d21a3
--- /dev/null
+++ b/day3/examples/static_assert1.cc
@@ -0,0 +1,5 @@
+double advance(unsigned long i)
+{
+    static_assert(sizeof(i) >= 8, "long must be bigger than 8 bytes");
+    return 0.;
+}
diff --git a/day3/examples/static_assert2.cc b/day3/examples/static_assert2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7fa08bacffbb57b8d767740483b4eab0111aa55d
--- /dev/null
+++ b/day3/examples/static_assert2.cc
@@ -0,0 +1,23 @@
+#include <iostream>
+#include <type_traits>
+
+template < class T >
+struct SomeCalc
+{
+  static_assert(std::is_arithmetic<T>::value,"argument T must be an arithmetic type");
+  constexpr SomeCalc() {}
+  constexpr auto operator()(const T & t1, const T & t2) const ->decltype(t1+t2)
+  {
+    return t1+t2+1; // Let's say there is a bug in the implementation 
+  }
+};
+
+int main()
+{
+  constexpr SomeCalc<int> intadder;
+  constexpr int res = intadder(1,1);
+  static_assert(res==2,"Adder seems to return unexpected result");
+  SomeCalc<std::string> stradder;
+}
+
+
diff --git a/day3/examples/template_intro.cc b/day3/examples/template_intro.cc
new file mode 100644
index 0000000000000000000000000000000000000000..78faceb817316cdeb6818dbddf3ed48482c5b1c2
--- /dev/null
+++ b/day3/examples/template_intro.cc
@@ -0,0 +1,26 @@
+#include <iostream>
+
+template <class T>
+void copy(T* start, T* end, T* start2)
+{
+    for (; start != end; ++start, ++start2) {
+        *start2 = *start;
+    }
+}
+
+auto main() -> int
+{
+    double x[10], y[10];
+    for (auto& num : x)
+        num = 1;
+    copy(x, x + 10, y);
+    for (auto&& num : y)
+        std::cout << num << "\n";
+
+    std::string anames[5] = { "a", "b", "c", "d", "e" };
+    std::string bnames[5] = { " ", " ", " ", " ", " " };
+
+    copy(anames, anames + 5, bnames);
+    for (auto&& name : bnames)
+        std::cout << name << "\n";
+}
diff --git a/day3/examples/variadic_1.cc b/day3/examples/variadic_1.cc
new file mode 100644
index 0000000000000000000000000000000000000000..796578c0fb7a4dd64b7b489ff247aa709ee70a07
--- /dev/null
+++ b/day3/examples/variadic_1.cc
@@ -0,0 +1,39 @@
+#include <iostream>
+#include <string>
+#if __has_include(<boost/type_index.hpp>)
+#include <boost/type_index.hpp>
+constexpr auto use_boost_type_index { true };
+#else
+#include <typeinfo>
+constexpr auto use_boost_type_index { false };
+#endif
+
+
+// plain_type_of(var) returns the typename without reference
+// symbols, const qualifiers etc.
+//
+template <class T>
+auto plain_type_of(T&& var) -> std::string
+{
+    if constexpr (use_boost_type_index)
+        return boost::typeindex::type_id<T>().pretty_name();
+    else
+        return typeid(var).name();
+}
+
+template <class... Types>
+void f(Types&&... args)
+{
+    std::cout << "Printing out typenames without references etc. and values\n";
+    ((std::cout << plain_type_of(args) << ": " << args << "\n"), ...);
+}
+
+auto main() -> int
+{
+    const int i { 3 }, j {};
+    size_t k {}, l { 9 };
+    const char* cst { "C-style string..." };
+    std::string cppst { "C++ string..." };
+    f(i, j, true, k, l, cst, cppst);
+}
+
diff --git a/day3/examples/variadic_2.cc b/day3/examples/variadic_2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c388ce9ae2c371e255f2a0d2ea256db0a8f6ee65
--- /dev/null
+++ b/day3/examples/variadic_2.cc
@@ -0,0 +1,27 @@
+#include <iostream>
+
+template <typename... Types>
+void f(Types... args);
+template <typename Type1, typename... Types>
+void f(Type1 arg1, Types... rest)
+{
+    std::cout << " The first argument is " << arg1
+              << ". Remainder argument list has " << sizeof...(Types) << " elements.\n";
+    f(rest...);
+}
+template <>
+void f() {}
+template <typename... Types>
+void g(Types... args)
+{
+    std::cout << "Inside g: going to call function f with the sizes of my arguments\n";
+    f(sizeof(args)...);
+}
+
+int main()
+{
+    std::cout << R"hoho(Calling f(0,true," 123 ");)hoho" << '\n';
+    f(0, true, "123");
+    std::cout << R"hoho(Calling g(0,true," 123 ");)hoho" << '\n';
+    g(0, true, "123");
+}
diff --git a/day3/examples/variadic_3.cc b/day3/examples/variadic_3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..249c68b8c42648847c7453650a13b7705fcc7253
--- /dev/null
+++ b/day3/examples/variadic_3.cc
@@ -0,0 +1,36 @@
+#include <array>
+#include <iostream>
+#include <list>
+#include <numeric>
+
+template <class... Types>
+void increment_all(Types&... args) { (++args, ...); }
+template <class... Ts>
+void h(Ts... args)
+{
+    std::cout << "Printing parameters passed to h \n";
+    ((std::cout << args << "\t"), ...);
+    std::cout << "\n";
+    [=, &args...] { return increment_all(args...); }();
+
+    std::cout << "\nModified value due to call to increment_all() through lambda \n";
+    ((std::cout << args << "\t"), ...);
+    std::cout << "\n";
+
+    std::cout << "Creating std::array out of parameters...\n";
+    std::array t { args... };
+
+    std::cout << "\nsum = " << std::reduce(t.begin(), t.end()) << "\n";
+}
+auto main() -> int
+{
+    int i = 0;
+    std::list l { 0, 2, 4, 8, 16 };
+    auto it = l.begin();
+    std::cout << "i = " << i << "; iterator it points to list element of value " << (*it) << "\n";
+    std::cout << "increment_all(i, it)\n";
+    increment_all(i, it);
+    std::cout << "i = " << i << "; iterator it points to list element of value " << (*it) << "\n";
+    std::cout << "Calling h(1, 2, 3, 4)\n";
+    h(1, 2, 3, 4);
+}
diff --git a/notebooks/lambda_practice_0.ipynb b/notebooks/lambda_practice_0.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..2f2ff1e64f3494eddbf753828170d4fe0f83e25e
--- /dev/null
+++ b/notebooks/lambda_practice_0.ipynb
@@ -0,0 +1,248 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5b454048",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#include <iostream>\n",
+    "#include <algorithm>\n",
+    "#include <vector>\n",
+    "#include <array>\n",
+    "#include <cmath>\n",
+    "#include <complex>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9541e5f1",
+   "metadata": {},
+   "source": [
+    "# Practice using lambdas with algorithms"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "eb5b5448",
+   "metadata": {},
+   "source": [
+    "## std::for_each"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4d3f33ef",
+   "metadata": {},
+   "source": [
+    "In the following cell, we scale the elements of a vector by $1.5$ and print them. In a separate cell, use the algorithm `std::for_each` along with an appropriate lambda expression replace the values by the $sin(value)$, and\n",
+    "show the results."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "99bbcf10",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    std::vector X{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.8, 0.7};\n",
+    "    std::for_each(X.begin(), X.end(), [](auto& elem){ elem *= 1.5; });\n",
+    "    std::for_each(X.begin(), X.end(), [](auto&& elem){ std::cout << elem << \"\\n\"; });\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fd0e92e9",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c2172ca4",
+   "metadata": {},
+   "source": [
+    "## std::transform\n",
+    "\n",
+    "Using the slides as a guide, fill in the necessary code, so that the second sequence consists of the values $a x^2 + b x + c$, for $x$ taken from the first sequence, $a$ and $b$ being constants."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8fb70ac5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    std::vector X{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.8, 0.7};\n",
+    "    std::vector<double> Y;\n",
+    "    const auto a = 2.7182818284590;\n",
+    "    const auto b = 3.1415926535897;\n",
+    "    // std::transform(what to what using what data transformation ?);\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7f0597d6",
+   "metadata": {},
+   "source": [
+    "## std::copy_if\n",
+    "\n",
+    "Using the slides as a guild, write the necessary code to \"filter\" into the vector `Y` only those values out of the input vector `X`, for which the the cylindrical Bessel function of the first kind, $J_0(x) > 0.9$. Cylindrical Bessel function of the first kind $J_0(x)$ are available in the C++ standard library as `std::cyl_bessel_j(int, double)`.  "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "07defab8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    std::vector X{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.8, 0.7};\n",
+    "    std::vector<double> Y;\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fc56123b",
+   "metadata": {},
+   "source": [
+    "## std::partition\n",
+    "\n",
+    "The algorithm `std::partition` takes \n",
+    "\n",
+    "    - the bounds of one sequence (as start and end iterators)\n",
+    "    - a unary predicate callable entity (something that can be called with one parameter, and returns true or false)\n",
+    "\n",
+    "and reorders the elements in the range so that all the elements which test true come before all elements which test false. The return value of the function is an iterator marking the partition point:\n",
+    "\n",
+    "```c++\n",
+    "auto p = std::partition(start, stop, criterion);\n",
+    "```\n",
+    "\n",
+    "The range `start` to `p` will then contain all elements which \"pass\" and `p` to `stop` will contain all elements which don't pass. Partition the range in the previous exercise using the $J_0(x)$ function and the selection criteria we used. Print the two sub ranges, along with the values of the Bessel function to show that `partition` did what is expected of it."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "164bd972",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    std::vector X{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.8, 0.7};\n",
+    "    auto p = std::partition(X.begin(), X.end(), [](auto x){ return std::cyl_bessel_j(0, x) > 0.9; });\n",
+    "    std::cout << \"Passed...\\n\";\n",
+    "    std::for_each(X.begin(), p, [](auto&& x){ std::cout << x << \"\\t\" << std::cyl_bessel_j(0, x) << \"\\n\"; });\n",
+    "    std::cout << \"Did not pass.\\n\";\n",
+    "    std::for_each(p, X.end(), [](auto&& x){ std::cout << x << \"\\t\" << std::cyl_bessel_j(0, x) << \"\\n\"; });\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c9467bb9",
+   "metadata": {},
+   "source": [
+    "## std::sort\n",
+    "\n",
+    "Any container containing elements for which a \"less than\" comparison $x_i < x_j$ makes sense can be sorted. For instance, for integers, real numbers, strings etc. $a < b$ makes sense. But for complex numbers, for instance, such a comparison can not be uniquely defined. `std::sort(begin, end)` will sort any container in increasing order, so long as the elements can be compared to determine their relative ordering. Test:  "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "cfcc07df",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    std::vector X{1,5,3,8,9,2,7,2,6,3,1,0,8,4};\n",
+    "    std::sort(X.begin(), X.end());\n",
+    "    for (auto elem : X) std::cout << elem << \"\\n\";\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fc3ffce8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    std::vector<std::string> X{\"Conditionally\", \"copies\", \"elements\", \"from\", \"a\", \"source\", \"sequence\", \"to\", \n",
+    "                 \"a\", \"destination\", \"sequence\"};\n",
+    "    // Fun exercise for those who feel adventurous: Try using CTAD in defining this vector,\n",
+    "    // and explain the results. What would you have to do to correctly use CTAD in this case ?\n",
+    "    std::sort(X.begin(), X.end());\n",
+    "    for (auto elem : X) std::cout << elem << \"\\n\";\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9a391f89",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    // But this does not work. If you run this, you may have restart the kernel!\n",
+    "    std::vector<std::complex<double>> X{{1., 3.}, {0.99, 3.14}, {1.22, 0.12}};\n",
+    "    std::sort(X.begin(), X.end(), [](auto x, auto y){ return std::abs(x) < std::abs(y); });\n",
+    "    for (auto&& elem : X) std::cout << elem << \"\\n\";\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6f7badd2",
+   "metadata": {},
+   "source": [
+    "However, `std::sort` can accept a callable object as another parameter, after the range parameters, which specifies how the contents of the range should be compared. It should be a function which takes two objects of the value type of the container, $x$ and $y$ (for instance), and return true if $x$ should be placed before $y$ for the current sorting operation. For instance, we can say that complex numbers should be sorted in such a way that the numbers with larger absolute value follow those with smaller absolute value. This can be expressed as $\\lambda(x,y) = |x| < |y|$. Write the appropriate lambda expression as the 3rd argument to sort above and verify that you can sort by this criterion. Absolute values of complex number `c` can be calculated as `std::abs(c)`. Complex numbers are known to `std::cout`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "661c8dd9",
+   "metadata": {},
+   "source": [
+    "How would you now sort an array of complex numbers by their real parts ? (Principle of least surprises applies here: `std::real(c)`, `std::imag(c)` ...)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "881f5069",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++17",
+   "language": "C++",
+   "name": "cling-cpp17"
+  },
+  "language_info": {
+   "codemirror_mode": "c++",
+   "file_extension": ".c++",
+   "mimetype": "text/x-c++src",
+   "name": "c++"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/lambda_practice_1.ipynb b/notebooks/lambda_practice_1.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..716efb4e3eb25c304a0db2342e437ea02e8a3b87
--- /dev/null
+++ b/notebooks/lambda_practice_1.ipynb
@@ -0,0 +1,342 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "e7b04ecc",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": []
+     },
+     "execution_count": 1,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "#pragma cling add_include_path(\"/p/project/training2213/local/include\")\n",
+    "#include <iostream>\n",
+    "#include <vector>\n",
+    "#include <algorithm>\n",
+    "#include <boost/type_index.hpp>\n",
+    "#include \"Vbose.hh\"\n",
+    "template <class T>\n",
+    "void typeof(T&& t) {\n",
+    "    std::cout << \"Type name: \" << boost::typeindex::type_id_with_cvr<T>().pretty_name() << \"\\n\";\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d7b6595",
+   "metadata": {},
+   "source": [
+    "# Lambda functions: captures\n",
+    "\n",
+    "## When\n",
+    "\n",
+    "Variables which can be used inside lambda functions are those declared inside the lambda function, its formal arguments, global variables and variables captured by the capture brackets. Variables captured with `=` captures are copied into the lambda function. When does the copy take place ? Immediately when the lambda is declared or at the point when it is used ? How often does the copy happen, if we declare it once, but use it in a loop two million times ? Does `[=]` capture copy every variable defined in the context of the lambda function in to the lambda ? We will use the `Vbose` class to explore..."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "1e7328f5",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Constructor of object at 140514652397128, using string \"dinosaur\"\n",
+      "Constructor of object at 140514652397040, using string \"fish\"\n",
+      "Declaring lambda function {\n",
+      "Copy constructor of object at 140514652396968. Source for copy is at 140514652397128\n",
+      "Declaring lambda function }\n",
+      "Changing internal value of object at 140514652397128 from dinosaur to bird\n",
+      "Calling lambda function {\n",
+      "5 -> \n",
+      "In lambda function, captured value of locvar is : dinosaur\n",
+      "125\n",
+      "Calling lambda function }\n",
+      "Calling lambda function {\n",
+      "5 -> \n",
+      "In lambda function, captured value of locvar is : dinosaur\n",
+      "125\n",
+      "Calling lambda function }\n",
+      "Calling lambda function {\n",
+      "5 -> \n",
+      "In lambda function, captured value of locvar is : dinosaur\n",
+      "125\n",
+      "Calling lambda function }\n",
+      "Calling lambda function {\n",
+      "5 -> \n",
+      "In lambda function, captured value of locvar is : dinosaur\n",
+      "125\n",
+      "Calling lambda function }\n",
+      "Calling lambda function {\n",
+      "5 -> \n",
+      "In lambda function, captured value of locvar is : dinosaur\n",
+      "125\n",
+      "Calling lambda function }\n",
+      "Destructor of object at 140514652396968 with data \"dinosaur\"\n",
+      "Destructor of object at 140514652397040 with data \"fish\"\n",
+      "Destructor of object at 140514652397128 with data \"bird\"\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": []
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "{\n",
+    "    Vbose locvar{ \"dinosaur\" }, anothervar{\"fish\"};\n",
+    "    std::cout << \"Declaring lambda function {\\n\";\n",
+    "    auto lambda = [=](int i) {\n",
+    "        std::cout << \"\\nIn lambda function, captured value of locvar is : \"\n",
+    "                  << locvar.getval() << \"\\n\";\n",
+    "        return i * i * i;\n",
+    "    };\n",
+    "    std::cout << \"Declaring lambda function }\\n\";\n",
+    "\n",
+    "    locvar.value(\"bird\");\n",
+    "    for (int i = 0; i < 5; ++i) {\n",
+    "        std::cout << \"Calling lambda function {\\n\";\n",
+    "        std::cout << 5 << \" -> \" << lambda(5) << \"\\n\";\n",
+    "        std::cout << \"Calling lambda function }\\n\";        \n",
+    "    }\n",
+    "}\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "04c99e3d",
+   "metadata": {},
+   "source": [
+    "How often did the copy operation for the captured variables occur inside the loop ? How did the change of the variable `locvar` after the declaration of the lambda reflect itself inside the lambda function, when it was called in the loop ? How do these results change if you use reference capture rather than value capture ?"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "79d13085",
+   "metadata": {},
+   "source": [
+    "In the following, we examine the effects of the `mutable` keyword for lambdas. The callable objects created when the lambda expression is evaluated are by default `const`. Imagine that the compiler is automatically generating a class with an overloaded function call operator, `operator()`. The captured variables are the arguments given to the constructor. By default, the `operator()` is `const` qualified, so that the callable object may not change state, i.e., the internal copies of the captured variables it creates in its constructor can not change when the lambda is used. However, declaring the lambda as `mutable` creates a non-constant function call operator. In this case, if any of the captured values are changed inside the lambda function call, those changes survive from call to call.\n",
+    "\n",
+    "Mutable lambdas are also often used in connection with init-captures. We declare a new variable in the capture bracket, using an expression to initialize it. For instance `[i = 0UL]()mutable {}` makes a variable `i` available inside the lambda, but that variable is not something that was present in the surrounding scope, but was created along with the lambda, in its constructor. It is as if the variable was being declared with an `auto i = 0UL`. We can not drop the `auto` for variable declarations anywhere in C++, except in lambda capture brackets. This is because the capture brackets define all the parameters to be given to the constructor of the lambda: so it is a context where there can only be declarations. It was therefore formulated in this way."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "5884e24d",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Outside Lambda, S= Some string\n",
+      "Inside Lambda, S = 1\n",
+      "Outside Lambda, S= Some string\n",
+      "Inside Lambda, S = 2\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": []
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "{\n",
+    "    std::string S{\"Some string\"};\n",
+    "    auto L = [S=1UL]()mutable { std::cout << \"Inside Lambda, S = \" << S << \"\\n\"; ++S; };\n",
+    "    std::cout << \"Outside Lambda, S= \" << S << \"\\n\";\n",
+    "    L();\n",
+    "    std::cout << \"Outside Lambda, S= \" << S << \"\\n\";\n",
+    "    L();\n",
+    "    // You can understand the output by noting that despite the name S appearing in the capture\n",
+    "    // bracket, the S was \"init captured\" from an unsigned long. It has no connection whatsoever\n",
+    "    // with the variable S outside.\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6135039c",
+   "metadata": {},
+   "source": [
+    "A popular application for mutable lambdas is generator functions. The algorithm `std::generate` takes the bounds of a sequence and a callable object of no input parameters (expected to be called just as `func()` with no inputs). A similar algorithm, `std::generate_n` accepts the start of the sequence, the number of elements it contains and a callable object. The generate and assign values for the sequence elements by calling the callable object once for each of them. Here is an example. We initialize a vector to the squares of positive integers. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "c9daa776",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " v = \n",
+      "1\n",
+      "4\n",
+      "9\n",
+      "16\n",
+      "25\n",
+      "36\n",
+      "49\n",
+      "64\n",
+      "81\n",
+      "100\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": []
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "{\n",
+    "    using namespace std;\n",
+    "    vector<unsigned long> v, w;\n",
+    "    generate_n(back_inserter(v), 10, [i = 0UL]() mutable {\n",
+    "        ++i;\n",
+    "        return i * i;\n",
+    "    });\n",
+    "    // v = [1, 4, 9, 16 ... ]\n",
+    "    std::cout << \" v = \\n\";\n",
+    "    for (auto el : v)\n",
+    "        std::cout << el << \"\\n\";\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f882cb25",
+   "metadata": {},
+   "source": [
+    "And in the following we do the same, but initialize a vector with the first 50 Fibonacci numbers..."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "7cec5bf6",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " w = \n",
+      "1\n",
+      "1\n",
+      "2\n",
+      "3\n",
+      "5\n",
+      "8\n",
+      "13\n",
+      "21\n",
+      "34\n",
+      "55\n",
+      "89\n",
+      "144\n",
+      "233\n",
+      "377\n",
+      "610\n",
+      "987\n",
+      "1597\n",
+      "2584\n",
+      "4181\n",
+      "6765\n",
+      "10946\n",
+      "17711\n",
+      "28657\n",
+      "46368\n",
+      "75025\n",
+      "121393\n",
+      "196418\n",
+      "317811\n",
+      "514229\n",
+      "832040\n",
+      "1346269\n",
+      "2178309\n",
+      "3524578\n",
+      "5702887\n",
+      "9227465\n",
+      "14930352\n",
+      "24157817\n",
+      "39088169\n",
+      "63245986\n",
+      "102334155\n",
+      "165580141\n",
+      "267914296\n",
+      "433494437\n",
+      "701408733\n",
+      "1134903170\n",
+      "1836311903\n",
+      "2971215073\n",
+      "4807526976\n",
+      "7778742049\n",
+      "12586269025\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": []
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "{\n",
+    "    using namespace std;\n",
+    "    vector<unsigned long> v, w;\n",
+    "    generate_n(back_inserter(w), 50, [ i = 0UL, j = 1UL ]() mutable {\n",
+    "        i = std::exchange(j, j + i);\n",
+    "        return i;\n",
+    "    });\n",
+    "    // w = [1, 1, 2, 3, 5, 8, 11 ...]\n",
+    "\n",
+    "    std::cout << \" w = \\n\";\n",
+    "    for (auto el : w)\n",
+    "        std::cout << el << \"\\n\";\n",
+    "}"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++17",
+   "language": "C++",
+   "name": "cling-cpp17"
+  },
+  "language_info": {
+   "codemirror_mode": "c++",
+   "file_extension": ".c++",
+   "mimetype": "text/x-c++src",
+   "name": "c++"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}