From 6428e4e1ab8cdc7c6b57a5403ec3f6cbf2db2e17 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent <vincent.rouvreau@inria.fr> Date: Mon, 10 May 2021 15:16:19 +0200 Subject: [PATCH] Rework spaceship operator, and some phrasings --- 3-Operators/2-Comparison.ipynb | 43 ++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/3-Operators/2-Comparison.ipynb b/3-Operators/2-Comparison.ipynb index 2aa90a2..8571de7 100644 --- a/3-Operators/2-Comparison.ipynb +++ b/3-Operators/2-Comparison.ipynb @@ -86,7 +86,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Defining `<` operator does not automatically defines the others, but all may be defined once `operator<` and `operator!=` are defined:\n", + "Defining `operator<` does not automatically defines the others, but a **good practice** is to define the other comparison operators once `operator<` and `operator!=` are defined, and in function of these two as follows:\n", "\n", "* `operator>(lhs, rhs)` is `operator<(rhs, lhs)`\n", "* `operator>=(lhs, rhs)` is `!operator<(lhs, rhs)`\n", @@ -100,7 +100,7 @@ "\n", "* None is defined by default.\n", "* They are independant from each other: defining one **doesn't** define the other one...\n", - "* ... but **never** define `operator!=` as something other than `!operator==`!\n", + "* ... but **never** define `operator!=` as something other than `!(operator==)`\n", "* As we've seen above, they are not involved at all in implicit definitions of `<=` or `>=` if only `<` or `>` is explicitly defined. Same remark as the line above though!\n", "* Make sure you're thought well the result of your comparison:\n" ] @@ -284,7 +284,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "C++ 20 introduces the so-called spaceship operator, which enables defining more concisely all those operators:" + "C++ 20 introduces the so-called spaceship operator, which enables defining more concisely all those operators (the following code doesn't work in Xeus-cling; you may use [@Coliru](https://coliru.stacked-crooked.com/a/1cec8ddda8a1eece)):" ] }, { @@ -400,7 +400,7 @@ "source": [ "This is rather cumbersome to type, but it is even dangerous: if at some point we extend the class and add `Nsaw_` for instance, we need not to forget to update the operator as well!\n", "\n", - "C++ 20 will enable default behaviour for the comparison operators, so in this case you would be able to write instead ([@Coliru](https://coliru.stacked-crooked.com/a/11c22df77c7065fe)):" + "C++ 20 will enable default behaviour for the comparison operators, so in this case you would be able to write instead ([@Coliru](https://coliru.stacked-crooked.com/a/fa889df647c73a7f)):" ] }, { @@ -413,8 +413,9 @@ "\n", "struct Toolbox\n", "{\n", - " bool operator==(const Toolbox&) const = default; \n", - " // < apparently only works with the internal declaration for operator==\n", + " bool operator==(const Toolbox&) const = default;\n", + "\n", + " auto operator<=>(const Toolbox&) const = default;\n", " \n", " unsigned int Nscrewdriver_;\n", " \n", @@ -437,6 +438,7 @@ " toolbox2.Nnails_ = 200;\n", " \n", " std::cout << std::boolalpha << (toolbox1 == toolbox2) << std::endl;\n", + " std::cout << std::boolalpha << (toolbox1 < toolbox2) << std::endl;\n", " \n", " return EXIT_SUCCESS; \n", "}" @@ -446,7 +448,34 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "[Examples](https://www.modernescpp.com/index.php/c-20-more-details-to-the-spaceship-operator) on [the](https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/) Web often show the defaulting of a comparison used directly upon the spaceship operator, which is something I will have to investigate when I upgrade to C++ 20 as it seems at first sight rather dangerous to me (see the `Rational` example, where even the default `operator==` is unlikely to be what we want)." + "As you can experiment, the `operator<` will compare data attributes in order of their declaration as if it was implemented this way:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bool operator<(const Rational& lhs, const Rational& rhs)\n", + "{\n", + " if !(toolbox1.Nscrewdriver_ == toolbox2.Nscrewdriver_)\n", + " return toolbox1.Nscrewdriver_ < toolbox2.Nscrewdriver_;\n", + " if !(toolbox1.Nhammer_ == toolbox2.Nhammer_)\n", + " return toolbox1.Nhammer_ < toolbox2.Nhammer_;\n", + " if !(toolbox1.Nnails_ == toolbox2.Nnails_)\n", + " return toolbox1.Nnails_ < toolbox2.Nnails_;\n", + " return false;\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[This example](https://www.modernescpp.com/index.php/c-20-more-details-to-the-spaceship-operator), or [that example](https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/) show other defaulting of a comparison used directly upon the spaceship operator.\n", + "\n", + "**Be aware** the default implementation may not be what you expected (see the `Rational` example, where even the default `operator==` is unlikely to be what we want)." ] }, { -- GitLab