diff --git a/4-Templates/1-Intro.ipynb b/4-Templates/1-Intro.ipynb index 1cf2dbe35c5bd6157826884a9a822fa4a8e353f2..ce4ef733b57535cb717f4ccc9824a0e4c63f7afe 100644 --- a/4-Templates/1-Intro.ipynb +++ b/4-Templates/1-Intro.ipynb @@ -32,7 +32,7 @@ "metadata": {}, "outputs": [], "source": [ - "int min(int lhs, int rhs)\n", + "int Min(int lhs, int rhs)\n", "{\n", " return lhs < rhs ? lhs : rhs;\n", "}" @@ -44,7 +44,7 @@ "metadata": {}, "outputs": [], "source": [ - "double min(double lhs, double rhs)\n", + "double Min(double lhs, double rhs)\n", "{\n", " return lhs < rhs ? lhs : rhs;\n", "}" @@ -56,7 +56,7 @@ "metadata": {}, "outputs": [], "source": [ - "float min(float lhs, float rhs)\n", + "float Min(float lhs, float rhs)\n", "{\n", " return lhs < rhs ? lhs : rhs;\n", "}" @@ -71,9 +71,9 @@ "#include <iostream>\n", "\n", "{\n", - " std::cout << min(5, -8) << std::endl;\n", - " std::cout << min(5., -8.) << std::endl; \n", - " std::cout << min(5.f, -8.f) << std::endl; \n", + " std::cout << Min(5, -8) << std::endl;\n", + " std::cout << Min(5., -8.) << std::endl; \n", + " std::cout << Min(5.f, -8.f) << std::endl; \n", "}" ] }, @@ -95,7 +95,7 @@ "outputs": [], "source": [ "template<class T>\n", - "T min2(T lhs, T rhs)\n", + "T MinWithTemplate(T lhs, T rhs)\n", "{\n", " return lhs < rhs ? lhs : rhs;\n", "}" @@ -110,10 +110,10 @@ "#include <iostream>\n", "\n", "{\n", - " std::cout << min2<int>(5, -8) << std::endl;\n", - " std::cout << min2(5, -8) << std::endl; \n", - " std::cout << min2(5., -8.) << std::endl; \n", - " std::cout << min2(5.f, -8.f) << std::endl; \n", + " std::cout << MinWithTemplate<int>(5, -8) << std::endl;\n", + " std::cout << MinWithTemplate(5, -8) << std::endl; \n", + " std::cout << MinWithTemplate(5., -8.) << std::endl; \n", + " std::cout << MinWithTemplate(5.f, -8.f) << std::endl; \n", "}" ] }, @@ -306,7 +306,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The template must be reminded in the definition as well; please notice before the `::` the brackets with the parameters *without their type*.\n", + "The template must be reminded in the definition as well; please notice before the `::` the brackets with the template parameters.\n", "\n", "### Template method of a template class\n", "\n", @@ -417,7 +417,7 @@ " \n", " HoldAValue3(T value);\n", " \n", - " friend void print(const HoldAValue3<T>& obj);\n", + " friend void Print(const HoldAValue3<T>& obj);\n", " \n", " private:\n", " \n", @@ -446,7 +446,7 @@ "#include <iostream>\n", "\n", "template<class T>\n", - "void print(const HoldAValue3<T>& obj)\n", + "void Print(const HoldAValue3<T>& obj)\n", "{\n", " // Friendship required to access private data.\n", " // I wouldn't recommend friendship where an accessor would do the same task easily!\n", @@ -462,7 +462,7 @@ "source": [ "{\n", " HoldAValue3<int> hold(5);\n", - " print(hold); // LINK ERROR, and that is not something amiss in Xeus-cling!\n", + " Print(hold); // LINK ERROR, and that is not something amiss in Xeus-cling!\n", "}" ] }, @@ -489,7 +489,7 @@ " // 'Repeating' the list of template arguments and not using the ones from the class will fix the issue...\n", " // T wouldn't have work here; the label MUST differ.\n", " template<class U>\n", - " friend void print(const HoldAValue4<U>& obj);\n", + " friend void Print(const HoldAValue4<U>& obj);\n", " \n", " private:\n", " \n", @@ -519,7 +519,7 @@ "\n", "// Notice it is only a label: in the definition I'm free to use the same label as for the class definitions!\n", "template<class T>\n", - "void print(const HoldAValue4<T>& obj)\n", + "void Print(const HoldAValue4<T>& obj)\n", "{\n", " std::cout << \"Underlying value is \" << obj.value_ << std::endl;\n", "}" @@ -533,7 +533,7 @@ "source": [ "{\n", " HoldAValue4<int> hold(5);\n", - " print(hold); // Ok!\n", + " Print(hold); // Ok!\n", "}" ] }, @@ -541,7 +541,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This way of declaring friendship works but is not entirely fullproof: `print<int>` is hence a friend of `HoldAValue4<double>`, which was not what was sought. Most of the time it's ok but there are 2 other ways to declare friendship; have a look at [this link](https://web.mst.edu/~nmjxv3/articles/templates.html) if you want to learn more about it." + "This way of declaring friendship works but is not entirely fullproof: `Print<int>` is hence a friend of `HoldAValue4<double>`, which was not what was sought. Most of the time it's ok but there are 2 other ways to declare friendship; have a look at [this link](https://web.mst.edu/~nmjxv3/articles/templates.html) if you want to learn more about it." ] }, { @@ -725,4 +725,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/4-Templates/2-Specialization.ipynb b/4-Templates/2-Specialization.ipynb index 4cb0175617d32f7ab6155bc9271a1c09521da3fc..d517281fed152e51fe104af2da4234d10606e86d 100644 --- a/4-Templates/2-Specialization.ipynb +++ b/4-Templates/2-Specialization.ipynb @@ -308,9 +308,12 @@ "metadata": {}, "outputs": [], "source": [ + "#include <iostream>\n", + "\n", "template<class TypeT, std::size_t Nelts>\n", "MyArray<TypeT, Nelts>::MyArray(TypeT initial_value)\n", "{\n", + " std::cout << \"Generic constructor\" << std::endl;\n", " for (auto i = 0ul; i < Nelts; ++i)\n", " content_[i] = initial_value;\n", "}" @@ -359,7 +362,8 @@ "outputs": [], "source": [ "{\n", - " MyArray<int, 10ul> array1(2); \n", + " MyArray<int, 8ul> generic_array(2); \n", + " MyArray<int, 10ul> specific_array(2); \n", "}" ] }, @@ -408,7 +412,7 @@ "#include <string>\n", "\n", "template<class T>\n", - "void PrintSquare<T, std::string>(T t, std::string u)\n", + "void PrintSquare<T, std::string>(T t, std::string u) // COMPILATION ERROR!\n", "{\n", " std::cout << \"Partial function specialization: doesn't compile!\" << std::endl; \n", " std::cout << \"(t^2, u^2) = (\" << t * t << \", \" << (u + u) << \")\" << std::endl;\n", @@ -419,7 +423,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You might have the impress it works if you try defining the function without specifying the brackets:" + "You might have the impress it works if you try defining the function without specifying the brackets\n", + "\n", + "_(please use [@Coliru](https://coliru.stacked-crooked.com/a/b1504e7033fd9346) - the code below no longer works in Xeus-cling as of September 2022)_" ] }, { @@ -428,48 +434,40 @@ "metadata": {}, "outputs": [], "source": [ + "// DOESN'T WORK ON XEUS-CLING!\n", + "\n", "#include <iostream>\n", "#include <string>\n", "\n", + "template<class T, class U>\n", + "void PrintSquare(T t, U u)\n", + "{\n", + " std::cout << \"Generic instantiation\" << std::endl;\n", + " std::cout << \"(t^2, u^2) = (\" << t * t << \", \" << u * u << \")\" << std::endl;\n", + "}\n", + "\n", + "\n", "template<class T>\n", "void PrintSquare(T t, std::string u)\n", "{\n", - " std::cout << \"Seamingly ok function template specialization \" << std::endl;\n", + " std::cout << \"Seemingly ok function template specialization \" << std::endl;\n", " std::cout << \"(t^2, u^2) = (\" << t * t << \", \" << (u + u) << \")\" << std::endl;\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "// May fail to Xeus-cling; but expected behaviour is to 'work' but not as intended...\n", - "// Restarting your kernel may make it work (of course then execute first the cell above)\n", + "}\n", + "\n", + "\n", + "int main(int argc, char** argv)\n", "{\n", " std::string hello(\"Hello\");\n", " PrintSquare(5., hello);\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "but you actually did simply an overload of `Print()`; calling the explicit specialization fails:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "{\n", - " PrintSquare<double, std::string>(5., std::string(\"Hello\"));\n", + " \n", + " // But if you uncomment this line, the compilation will fail...\n", + " // PrintSquare<double, std::string>(5., std::string(\"Hello\"));\n", + " \n", + " // ... whereas it is a perfectly legit rule of instantiation, as you may check with:\n", + " // PrintSquare<double, int>(5., 3);\n", + " \n", + " \n", + " return EXIT_SUCCESS; \n", "}" ] }, diff --git a/4-Templates/3-Syntax.ipynb b/4-Templates/3-Syntax.ipynb index c6bf782cd2699eaf0c63782a7eda5fba80e223e5..96610e517462e6410e989b86416f662e0d09c0ee 100644 --- a/4-Templates/3-Syntax.ipynb +++ b/4-Templates/3-Syntax.ipynb @@ -240,7 +240,7 @@ "#include <list>\n", "\n", "template<typename T>\n", - "concept HasValueType = requires(T a) \n", + "concept HasValueType = requires(T) \n", "{\n", " typename T::value_type;\n", "};\n", diff --git a/4-Templates/5-MoreAdvanced.ipynb b/4-Templates/5-MoreAdvanced.ipynb index 9a69eae9a752d9ea0564d6fb08127628c317cbec..8c8ff28b6ba29eafe084947dd4fc2871262b8058 100644 --- a/4-Templates/5-MoreAdvanced.ipynb +++ b/4-Templates/5-MoreAdvanced.ipynb @@ -114,7 +114,7 @@ "- Requires `T` is copyable.\n", "- Copy `T`, which is potentially a time-consuming operator. \n", "\n", - "We could replace by `const T& GetValue() const`, but it's a bit on the nose (and less efficient) for plain old data type. The best of both world may be achieved by a trait:\n" + "We could replace by `const T& GetValue() const` to solve both those issues, but it's a bit on the nose (and less efficient) for plain old data type. The best of both world may be achieved by a trait:\n" ] }, { @@ -125,6 +125,8 @@ "source": [ "#include <iostream>\n", "#include <string>\n", + "#include <type_traits> // for std::conditional, std::is_trivial\n", + "\n", "\n", "template<class T>\n", "class ImprovedHoldAValue\n",