diff --git a/notebooks/08_Functors+Lambdas.ipynb b/notebooks/08_Functors+Lambdas.ipynb index 8df7e34bb315562c3ab8d265894fc37c3f956850..90682ed36058bfe3ae5ede117cf9de88b6b2dbc3 100644 --- a/notebooks/08_Functors+Lambdas.ipynb +++ b/notebooks/08_Functors+Lambdas.ipynb @@ -76,7 +76,7 @@ "#### Functors\n", "In C++ we can as one alternative use a **function object**, a.k.a. **functor**. This is an object of a class that overloads the function call operator ```operator()```.\n", "\n", - "**Example #1:**" + "##### **Example 1:**" ] }, { @@ -135,7 +135,7 @@ "***\n", "Now that was a simple functor and did only demonstrate **how** it works and not **why** that approach can be advantageous.\n", "\n", - "**Example 2:** \n", + "##### **Example 2:** \n", "In our second example we will use a stateful functor that allows to perform different binary operations. The type of operation will be passed via its constructor." ] }, @@ -216,7 +216,7 @@ "id": "6adaab27", "metadata": {}, "source": [ - "**Example 3:** \n", + "##### **Example 3:** \n", "So how would our set example for myPair look like with a functor?" ] }, @@ -308,6 +308,208 @@ "!./a.out" ] }, + { + "cell_type": "markdown", + "id": "c51deb94-f9c2-4a88-914b-ddf70f29601e", + "metadata": {}, + "source": [ + "#### std::function\n", + "\n", + "Quoting from cppreference:\n", + "> Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.\n", + ">\n", + "> The stored callable object is called the target of std::function. If a std::function contains no target, it is called empty. Invoking the target of an empty std::function results in std::bad_function_call exception being thrown. \n", + "\n", + "The functionality of ```std::function``` is quite useful especially in combination with lambda functions (see below)." + ] + }, + { + "cell_type": "markdown", + "id": "6c584ecb-10c3-4ff2-ab53-2a66c0963009", + "metadata": {}, + "source": [ + "##### **Example 4:**\n", + "Assign a simple free-function" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "21120bbb-03a7-4048-97f4-0426c40c5bac", + "metadata": {}, + "outputs": [], + "source": [ + "#include <iostream>\n", + "void sayIt() { std::cout << \"He said captain, I said wot\" << std::endl; }" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "bab0ab95-e5fd-4368-b3c2-77bcb869cfe0", + "metadata": {}, + "outputs": [], + "source": [ + "// generate an object of type std::function;\n", + "\n", + "// need this header file\n", + "#include <functional>\n", + "\n", + "// need to supply the prototype of the function/invocation that we want to target\n", + "std::function< void( ) > sensible;" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "b4e3f68a-6c70-49e7-a04c-924804c4cb35", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "empty -> nothing to do!\n" + ] + } + ], + "source": [ + "// std::function overloads 'operator bool' so we can check if anything is targetted, yet\n", + "if( !sensible ) {\n", + " std::cout << \"empty -> nothing to do!\" << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "c5b3e4d0-64b4-47c6-848f-f787bf9c0b17", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "He said captain, I said wot\n" + ] + } + ], + "source": [ + "// now assign a target to our std::object\n", + "sensible = sayIt;\n", + "\n", + "// and perform the invocation\n", + "sensible();" + ] + }, + { + "cell_type": "markdown", + "id": "1ad030ff-9527-4436-be80-72baf9ac7b29", + "metadata": {}, + "source": [ + "##### **Example 5:**\n", + "Now lets use a functor with a slightly more complicated interface" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ff8d558b-da83-46d9-9842-8e0d9d5ba56d", + "metadata": {}, + "outputs": [], + "source": [ + "// that's our functor\n", + "struct Mult {\n", + " int operator() ( int a, int b ) { return a*b; } \n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b5790b96-bf62-4d6e-ad9c-e56839882728", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "// if we want, we can alias our std::function type\n", + "using binaryOp = std::function< int(int,int) >;\n", + "\n", + "// now instantiate an object that targets the functor\n", + "binaryOp multiply = Mult();\n", + "\n", + "// note that we needed the () to differentiate between the invocation and the functor itself!\n", + "\n", + "multiply(2,3)" + ] + }, + { + "cell_type": "markdown", + "id": "589b7083-7a36-4ff8-bdd0-c46f9994228c", + "metadata": {}, + "source": [ + "##### **Example 6:**\n", + "A member function of a class can also serve as target" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "646b302f-cdf5-40ed-98f8-01d98a9b277a", + "metadata": {}, + "outputs": [], + "source": [ + "struct ItemsInStore{\n", + " int num;\n", + " ItemsInStore() = delete;\n", + " ItemsInStore( int num ) : num(num) {};\n", + " void decrementAndShowRest() {\n", + " std::cout << \"Only \" << --num << \" items left!\" << std::endl;\n", + " }\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "b56b370a-654f-4665-a86d-1b4a1497a813", + "metadata": {}, + "outputs": [], + "source": [ + "std::function< void( ItemsInStore& ) > takeOne = &ItemsInStore::decrementAndShowRest;" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "b267e62f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Only 4 items left!\n", + "Only 3 items left!\n" + ] + } + ], + "source": [ + "ItemsInStore candyBox( 5 );\n", + "takeOne( candyBox );\n", + "takeOne( candyBox );" + ] + }, { "cell_type": "markdown", "id": "9d2c9715",