{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Functions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### general"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "void change(int& x) {\n",
    "    x = x + 1;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int a = 0;\n",
    "change(a);\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### not in general"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct CountDown {\n",
    "    CountDown(int num): number{num} {}\n",
    "    void next();\n",
    "    int number;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "void CountDown::next() {\n",
    "    this->number = this->number - 1;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "CountDown counter = CountDown(5);\n",
    "counter.next();\n",
    "counter.number"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "counter.next();\n",
    "counter.number"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Namespaces"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstdio>\n",
    "\n",
    "namespace A_Space::Sub_Space {\n",
    "    enum class Color {\n",
    "        red=1,\n",
    "        green=2,\n",
    "        blue=3\n",
    "    };\n",
    "    struct A_Class {\n",
    "        int number = 1998;\n",
    "    };\n",
    "}\n",
    "\n",
    "namespace B_Space {\n",
    "    struct A_Class {\n",
    "        int number = 1998;\n",
    "    };\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "we just used a color from a namespace."
     ]
    }
   ],
   "source": [
    "auto a_color = A_Space::Sub_Space::Color::red;\n",
    "\n",
    "if (a_color == A_Space::Sub_Space::Color::red) {\n",
    "    printf(\"we just used a color from a namespace.\");\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "we just did an comparation with two variables that comes from different namespaces."
     ]
    }
   ],
   "source": [
    "auto a = A_Space::Sub_Space::A_Class().number;\n",
    "auto b = B_Space::A_Class().number;\n",
    "\n",
    "if (a == b) {\n",
    "    printf(\"we just did an comparation with two variables that comes from different namespaces.\");\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### using"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "input_line_23:3:20: warning: self-comparison always evaluates to true [-Wtautological-compare]\n",
      "    if (Color::red == Color::red) {\n",
      "                   ^\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "\n",
    "void a_function() {\n",
    "    using A_Space::Sub_Space::Color;\n",
    "    if (Color::red == Color::red) {\n",
    "        std::cout << \"hi\";\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hi"
     ]
    }
   ],
   "source": [
    "a_function();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "\n",
    "namespace C_Space {\n",
    "    using namespace std;\n",
    "    \n",
    "    struct C_Class {\n",
    "        int number = 1998;\n",
    "        void print() {\n",
    "            cout << \"hi\";\n",
    "        }\n",
    "    };\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "void another_function() {\n",
    "    using theClass = C_Space::C_Class;\n",
    "    theClass().print();\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hi"
     ]
    }
   ],
   "source": [
    "another_function()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Structured Bindings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1, 2"
     ]
    }
   ],
   "source": [
    "int a[2] = {1,2};\n",
    " \n",
    "auto [x,y] = a; // creates e[2], copies a into e, then x refers to e[0], y refers to e[1]\n",
    "auto& [xr, yr] = a; // xr refers to a[0], yr refers to a[1]\n",
    "\n",
    "printf(\"%d, %d\", x,y);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "999"
     ]
    }
   ],
   "source": [
    "struct Dark {\n",
    "    int brightness;\n",
    "    const char* description;\n",
    "};\n",
    "const static char text[]{\"I'm dark inside.\"};\n",
    "const auto [light, string] = Dark{999, text};\n",
    "printf(\"%d\", light);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Selection Statements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### if statements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I love you."
     ]
    }
   ],
   "source": [
    "#include <string>\n",
    "#include <iostream>\n",
    "using namespace std;\n",
    "\n",
    "string you = \"\";\n",
    "string love_me = \"\";\n",
    "\n",
    "if (you == love_me){\n",
    "    std::cout << \"I love you.\";\n",
    "} else {\n",
    "    std::cout << \"I was wrong.\";\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I was wrong."
     ]
    }
   ],
   "source": [
    "if (string future_you = \"changed\"; future_you == love_me) {\n",
    "    std::cout << \"I love you.\";\n",
    "} else {\n",
    "    std::cout << \"I was wrong.\";\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### constexpr if statements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`constexpr` indicates that the `if statement` is resolved at compile time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstdio>\n",
    "#include <stdexcept>\n",
    "#include <type_traits>\n",
    "\n",
    "template <typename T>\n",
    "auto value_of(T x) {\n",
    "    if constexpr (std::is_pointer<T>::value) {\n",
    "        if (!x) throw std::runtime_error{ \"Null pointer dereference.\" };\n",
    "        return *x;\n",
    "    } else {\n",
    "        return x;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "yingshaoxo was born in 1998.\n",
      "yingshaoxo was born in 1998.\n"
     ]
    }
   ],
   "source": [
    "unsigned long year{ 1998 }; //my birth year\n",
    "auto year_ptr = &year; //pointer\n",
    "auto &year_ref = year; //reference\n",
    "printf(\"yingshaoxo was born in %lu.\\n\", value_of(year_ptr));\n",
    "printf(\"yingshaoxo was born in %lu.\\n\", value_of(year_ref));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "@0x7fff53959eb0"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "year_ptr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1998"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "year_ref"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Exception: Null pointer dereference.\n"
     ]
    }
   ],
   "source": [
    "try {\n",
    "    year_ptr = nullptr;\n",
    "    value_of(year_ptr);\n",
    "} catch (const std::exception& e) {\n",
    "    printf(\"Exception: %s\\n\", e.what());\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### constexpr if statements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fine"
     ]
    }
   ],
   "source": [
    "#include <string>\n",
    "\n",
    "enum class People { \n",
    "    Me, \n",
    "    Him,\n",
    "    Nobody,\n",
    "}; \n",
    "\n",
    "People you_love = People::Nobody;\n",
    "\n",
    "switch (you_love) {\n",
    "    case People::Me: {\n",
    "        printf(\"nice\");\n",
    "        break;\n",
    "    }\n",
    "    case People::Him: {\n",
    "        printf(\"I'm dark inside.\");\n",
    "        break;\n",
    "    }\n",
    "    case People::Nobody: {\n",
    "        printf(\"fine\");\n",
    "        break;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "enum class People2 { \n",
    "    Me, \n",
    "    Him=5,\n",
    "    Nobody,\n",
    "}; \n",
    "\n",
    "//int num = (int)(People2::Nobody);\n",
    "int num = static_cast<int>(People2::Nobody);\n",
    "num"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So what is enumeration anyway?\n",
    "\n",
    "It's a representation of different stuff in a fixed range, like fixed colors: red, blue, green, and so on\n",
    "\n",
    "You can also use a number to indicate the difference between objects, like what we did above. It shows 6.\n",
    "\n",
    "> Generally speaking, I don't think this is useful because I never saw it in other modern programming languages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Iteration Statements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### while loops"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0123456789"
     ]
    }
   ],
   "source": [
    "int i = 0;\n",
    "while (i < 10) {\n",
    "    printf(\"%d\", i);\n",
    "    ++i;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "uint8_t:\n",
      "===\n",
      "2 4 8 16 32 64 128 \n",
      "0 "
     ]
    }
   ],
   "source": [
    "bool double_return_overflow(uint8_t& x) {\n",
    "    const auto original = x;\n",
    "    x *= 2;\n",
    "    //x += 1;\n",
    "    return original > x;\n",
    "}\n",
    "\n",
    "uint8_t x{1};\n",
    "printf(\"uint8_t:\\n===\\n\");\n",
    "while (!double_return_overflow(x)) {\n",
    "    printf(\"%u \", x);\n",
    "}\n",
    "printf(\"\\n%u \", x);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### do while"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "unsigned int i = 0;\n",
    "do {\n",
    "    printf(\"%u \", i);\n",
    "    ++i;\n",
    "} while (i < 10);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you can use `while`, do not use `do while`.\n",
    "\n",
    "It makes people confused."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### for loops"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The world belongs to us, but eventually belongs to you."
     ]
    }
   ],
   "source": [
    "string text = \"The world belongs to us, but eventually belongs to you.\";\n",
    "\n",
    "for(int i=0; i<text.length(); ++i) {\n",
    "    printf(\"%c\", text[i]);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ranged-Based for loops"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "string text = \"The world belongs to us, but eventually belongs to you.\";"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The world belongs to us, but eventually belongs to you."
     ]
    }
   ],
   "source": [
    "for (char& c: text) {\n",
    "    printf(\"%c\", c);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The world belongs to us, but eventually belongs to you."
     ]
    }
   ],
   "source": [
    "for (auto c: text) {\n",
    "    printf(\"%c\", c);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The world belongs to us, but eventually belongs to you."
     ]
    }
   ],
   "source": [
    "for (auto b=text.begin(); b!=text.end(); ++b) {\n",
    "    printf(\"%c\", *b);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `text` here is actually an iterator, or to be more accurate, has implemented an iterator inside it.\n",
    "\n",
    "If you want to use the `range operation`, you must make sure that your `range class` has two functions: `begin()` and `end()`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Range Expressions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can define our own \"ranges\".\n",
    "\n",
    "Every `range` exposes a `begin` and an `end` method. These functions represent the common interface that a range-based for loop uses to interact with a range. \n",
    "\n",
    "Both methods return iterators. An iterator is an object that supports `operator*`, `operator!=`, and `operator++`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct MyIterator {\n",
    "    private:\n",
    "        int num{1};\n",
    "    public:\n",
    "        int operator*() {\n",
    "            return this->num;\n",
    "        }\n",
    "        \n",
    "        bool operator!=(int x) {\n",
    "            return x >= this->num; // if true, we go on the iteration\n",
    "        }\n",
    "    \n",
    "        auto& operator++() { // we want to get reference variable then creating a new instance every time when we go to the next loop\n",
    "            ++this->num;\n",
    "            return *this; \n",
    "        }\n",
    "};\n",
    "\n",
    "struct MyRange {\n",
    "    private:\n",
    "        int max;\n",
    "    public:\n",
    "        MyRange(int max) {\n",
    "            this->max = max;\n",
    "        }\n",
    "    \n",
    "        MyIterator begin() {\n",
    "            return MyIterator{};\n",
    "        }\n",
    "        \n",
    "        int end() {\n",
    "            return this->max;\n",
    "        }\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4 5 "
     ]
    }
   ],
   "source": [
    "for (auto i: MyRange(5)) {\n",
    "    printf(\"%d \", i);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A Fibonacci Range"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://www.mathsisfun.com/numbers/fibonacci-sequence.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 "
     ]
    }
   ],
   "source": [
    "struct FibonacciIterator {\n",
    "    private:\n",
    "        int last{1}, current{1};\n",
    "    public:\n",
    "        int operator*() const { // *pointer to get an interger\n",
    "            return current;\n",
    "        }\n",
    "    \n",
    "        bool operator!=(int x) const { // != must be used by the range mechanism\n",
    "            // if 5000>=4181, return True, continue to work\n",
    "            // if 5000>=6765, return False, stop the iteration\n",
    "            return x >= current;\n",
    "        }\n",
    "    \n",
    "        FibonacciIterator& operator++() {\n",
    "            const auto tmp = current;\n",
    "            current += last;\n",
    "            last = tmp;\n",
    "            return *this;\n",
    "        }\n",
    "};\n",
    "\n",
    "struct FibonacciRange {\n",
    "    private:\n",
    "        const int max;\n",
    "    public:\n",
    "        explicit FibonacciRange(int max): max{max} {}\n",
    "        FibonacciIterator begin() const {\n",
    "            return FibonacciIterator{};\n",
    "        }\n",
    "        int end() const {\n",
    "            return max;\n",
    "        }\n",
    "};\n",
    "\n",
    "for (const auto i: FibonacciRange{5000}) {\n",
    "    printf(\"%d \", i);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Make fun with Range Expressions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct MyIterator2 {\n",
    "    private:\n",
    "        int num{1};\n",
    "    public:\n",
    "        int operator*() {\n",
    "            return this->num;\n",
    "        }\n",
    "        \n",
    "        bool operator!=(int x) {\n",
    "            return x >= -this->num; // if true, we go on the iteration\n",
    "        }\n",
    "    \n",
    "        auto& operator++() { // we want to get reference variable then creating a new instance every time when we go to the next loop\n",
    "            this->num *= -2;\n",
    "            return *this; \n",
    "        }\n",
    "};\n",
    "\n",
    "struct MyRange2 {\n",
    "    private:\n",
    "        int max;\n",
    "    public:\n",
    "        MyRange2(int max) {\n",
    "            this->max = max;\n",
    "        }\n",
    "    \n",
    "        MyIterator2 begin() {\n",
    "            return MyIterator2{};\n",
    "        }\n",
    "        \n",
    "        int end() {\n",
    "            return this->max;\n",
    "        }\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 -2 4 -8 16 -32 64 -128 256 -512 1024 "
     ]
    }
   ],
   "source": [
    "for (auto i: MyRange2(1000)) {\n",
    "    printf(\"%d \", i);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Jump Statements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`continue`, `break` are jump statements.\n",
    "\n",
    "But we already know it from Python background, do we？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
