From 0f61101ea88eed27b654d59120a5cad69fe52bc4 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Thu, 3 Aug 2023 22:38:45 +0200 Subject: [PATCH 1/6] Add initial doc proposal for functions --- concepts/functions/.meta/config.json | 8 ++ concepts/functions/about.md | 3 + concepts/functions/introduction.md | 115 +++++++++++++++++++++++++++ concepts/functions/links.json | 18 +++++ 4 files changed, 144 insertions(+) create mode 100644 concepts/functions/.meta/config.json create mode 100644 concepts/functions/about.md create mode 100644 concepts/functions/introduction.md create mode 100644 concepts/functions/links.json diff --git a/concepts/functions/.meta/config.json b/concepts/functions/.meta/config.json new file mode 100644 index 000000000..ee67dacff --- /dev/null +++ b/concepts/functions/.meta/config.json @@ -0,0 +1,8 @@ +{ + "blurb": "In C++, functions support overloading, constant arguments and default values.", + "authors": [ + "vaeng" + ], + "contributors": [ + ] +} diff --git a/concepts/functions/about.md b/concepts/functions/about.md new file mode 100644 index 000000000..f39ee3c37 --- /dev/null +++ b/concepts/functions/about.md @@ -0,0 +1,3 @@ +# About + +[comment]: (Please fill with introduction.md content. For real.) \ No newline at end of file diff --git a/concepts/functions/introduction.md b/concepts/functions/introduction.md new file mode 100644 index 000000000..8565bd435 --- /dev/null +++ b/concepts/functions/introduction.md @@ -0,0 +1,115 @@ +# Introduction + +## Terminology + +You have already used and written C++ functions in a couple of concepts. +It is time to get technical. +The code snipped below shows the most common terms for easy reference. +As C++ ignores whitespace, the formatting has been changed to have each element on a single line. + +```cpp +// Function declaration: +bool admin_detected(string user, string password) // Function header +; // Don't forget the ';' for the declaration + +// Function definition: +bool // Return type +admin_detected // Function name +(string user, string password) // Parameter list +{ return user == "admin" && password == "1234"; } // Function body +``` +~~~~exercism/advanced +The declaration works like a note to the compiler, that there is a function of that name, return type and paramter list. +The code will not compile, if the definition is missing. +Declarations are optional, they are needed if you use the function before its definiton. +Declarations can solve problems like cyclic references. +~~~~ + +## The const qualifier + +Sometimes you want to make sure that values cannot be changed after they have been initialized. +C++ uses the `const` keyword as a qualifier for constants. + +```cpp +const int number_of_dragon_balls{7}; +number_of_dragon_balls--; // compilation error +``` + +~~~~exercism/note +You will often see constants written in _UPPER_SNAKE_CASE_. +It is recommened to reserve this casing for macros, if there is no other convention. +~~~~ + +If you try to change a constant variable after it has been set, your code will not compile. +This helps to avoid unintended changes but also opens up optimization possibilities for the compiler. +As a human, it is also easier to reason about the code, if you know that certain parts will not be affected. + +You can also have `const` as a qualifier for function parameters. + +```cpp +string guess_number(const int& secret, const int& guess) { + if (secret < guess) return "lower."; + if (secret > guess) return "higher."; + return "exact!"; +} +``` + +When you pass a `const` reference to the function, you can be sure that it will be left unchanged. +You will often see `const` references for objects that might be costly to copy, like very long strings. +A third use-case for the `const` qualifier are member functions, that do not change the instance of a class. + +```cpp +class Stubborn { + public: + Stubborn(string reply) { + response = reply; + } + string answer() const { + return response; + } + private: + string response{}; +}; +``` + +## Function Overloading + +If you take the function header without the return type, you get a function's __type signature__. +The type signature is defined by the function's name, the number of parameters, their types, and their qualifiers. +If you change anything about the signature, the compiler will search for a fitting function. +When two functions have the same name but differences in the rest of their type signature, the practice is called function overloading. + +The `play_sound` example has six different overloads to accommodate many different scenarios: + +```cpp +// different argument types: +void play_sound(char note); // C, D, E, ..., B +void play_sound(string solfege); // do, re, mi, ..., ti +void play_sound(int jianpu); // 1, 2, 3, ..., 7 + +// different number of arguments: +void play_sound(string solfege, double duration); + +// different qualifiers: +void play_sound(vector& solfege); +void play_sound(const vector& solfege); +``` + +The return type is explicitly not part of the type signature and you will get compilation errors if you have two functions that only differ in their return type. +The compiler will complain because it is not clear, which of the two should be used. + +## Default arguments + +Some functions can get very lengthy and many of its calls might use the same values for most of the parameters. +The repetition in those calls can be avoided with default arguments. + +```cpp +void record_new_horse_birth(string name, double weight, string color="brown-ish", string dam="Alruccaba", string sire="Poseidon"); + +record_new_horse_birth("Urban Sea", 130); // color will be brown, dam Alruccabam, sire Poseidon +record_new_horse_birth("Highclere", 175, "off-white", "Fall Aspen"); // sire will be Poseidon +``` + +As the function declaration is often read before the definition, it is the better place to set the default arguments. +If one parameter has a default declaration, all the parameters to its right need a default declaration as well. +Sometimes complicated function overloads can be refactored to fewer functions with default arguments to improve maintainability. diff --git a/concepts/functions/links.json b/concepts/functions/links.json new file mode 100644 index 000000000..507dc758d --- /dev/null +++ b/concepts/functions/links.json @@ -0,0 +1,18 @@ +[ + { + "url": "https://en.cppreference.com/w/cpp/language/cv", + "description": "C++ reference on const qualifiers" + }, + { + "url": "https://en.cppreference.com/book/intro/function_overloading", + "description": "C++ reference on function overloading" + } + { + "url": "https://en.cppreference.com/w/cpp/language/overload_resolution", + "description": "C++ reference on overload resolution" + }, + { + "url": "https://en.cppreference.com/w/cpp/language/default_arguments", + "description": "C++ reference on default arguments" + } +] \ No newline at end of file From 94bff5eee01c599f946f00cd7de6bb12a82fe9d5 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Thu, 3 Aug 2023 22:47:54 +0200 Subject: [PATCH 2/6] make configlet happy --- config.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config.json b/config.json index b82c24a9e..dc0a46d55 100644 --- a/config.json +++ b/config.json @@ -1090,6 +1090,11 @@ "uuid": "2e4f454e-4a54-4999-9627-86840c88fc46", "slug": "enums", "name": "Enumerations" + }, + { + "uuid": "18b2f529-3be6-4a70-be7d-81aa07393585", + "slug": "functions", + "name": "Functions" } ], "key_features": [ From 378fd433d2f364bbd19a0392bb733daf31e45389 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Thu, 3 Aug 2023 22:48:07 +0200 Subject: [PATCH 3/6] make it happier --- concepts/functions/links.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/functions/links.json b/concepts/functions/links.json index 507dc758d..c08cc662b 100644 --- a/concepts/functions/links.json +++ b/concepts/functions/links.json @@ -6,7 +6,7 @@ { "url": "https://en.cppreference.com/book/intro/function_overloading", "description": "C++ reference on function overloading" - } + }, { "url": "https://en.cppreference.com/w/cpp/language/overload_resolution", "description": "C++ reference on overload resolution" From aa4e25065dd8a786a26a13f4d11082e61b4d6bc9 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:51:59 +0200 Subject: [PATCH 4/6] =?UTF-8?q?Implement=20comments=20from=20Siebenschl?= =?UTF-8?q?=C3=A4fer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- concepts/functions/.meta/config.json | 2 +- concepts/functions/introduction.md | 30 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/concepts/functions/.meta/config.json b/concepts/functions/.meta/config.json index ee67dacff..8e9c22977 100644 --- a/concepts/functions/.meta/config.json +++ b/concepts/functions/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "In C++, functions support overloading, constant arguments and default values.", + "blurb": "In C++, functions support overloading, constant arguments, and default values.", "authors": [ "vaeng" ], diff --git a/concepts/functions/introduction.md b/concepts/functions/introduction.md index 8565bd435..a70b60c83 100644 --- a/concepts/functions/introduction.md +++ b/concepts/functions/introduction.md @@ -4,8 +4,8 @@ You have already used and written C++ functions in a couple of concepts. It is time to get technical. -The code snipped below shows the most common terms for easy reference. -As C++ ignores whitespace, the formatting has been changed to have each element on a single line. +The code snippet below shows the most common terms for easy reference. +As C++ ignores whitespace, the formatting has been changed to put each element on a single line. ```cpp // Function declaration: @@ -19,10 +19,10 @@ admin_detected // Function name { return user == "admin" && password == "1234"; } // Function body ``` ~~~~exercism/advanced -The declaration works like a note to the compiler, that there is a function of that name, return type and paramter list. -The code will not compile, if the definition is missing. +The declaration works like a note to the compiler, that there is a function of that name, return type and parameter list. +The code will not work, if the definition is missing. Declarations are optional, they are needed if you use the function before its definiton. -Declarations can solve problems like cyclic references. +Declarations can solve problems like cyclic references and they can be used to separate the interface from the implementation. ~~~~ ## The const qualifier @@ -55,8 +55,8 @@ string guess_number(const int& secret, const int& guess) { ``` When you pass a `const` reference to the function, you can be sure that it will be left unchanged. -You will often see `const` references for objects that might be costly to copy, like very long strings. -A third use-case for the `const` qualifier are member functions, that do not change the instance of a class. +You will often see `const` references for objects that might be costly to copy, like longer strings. +A third use-case for the `const` qualifier are member functions that do not change the instance of a class. ```cpp class Stubborn { @@ -72,14 +72,14 @@ class Stubborn { }; ``` -## Function Overloading +## Function overloading If you take the function header without the return type, you get a function's __type signature__. -The type signature is defined by the function's name, the number of parameters, their types, and their qualifiers. -If you change anything about the signature, the compiler will search for a fitting function. +The type signature is defined by the function's name, the number of parameters, their types, and their qualifiers (but not their names). +A change in the signature results in a new function. When two functions have the same name but differences in the rest of their type signature, the practice is called function overloading. -The `play_sound` example has six different overloads to accommodate many different scenarios: +The `play_sound` example has six different overloads to accommodate different scenarios: ```cpp // different argument types: @@ -96,7 +96,7 @@ void play_sound(const vector& solfege); ``` The return type is explicitly not part of the type signature and you will get compilation errors if you have two functions that only differ in their return type. -The compiler will complain because it is not clear, which of the two should be used. +The compiler will complain because it is not clear which of the two should be used. ## Default arguments @@ -104,10 +104,10 @@ Some functions can get very lengthy and many of its calls might use the same val The repetition in those calls can be avoided with default arguments. ```cpp -void record_new_horse_birth(string name, double weight, string color="brown-ish", string dam="Alruccaba", string sire="Poseidon"); +void record_new_horse_birth(string name, int weight, string color="brown-ish", string dam="Alruccaba", string sire="Poseidon"); -record_new_horse_birth("Urban Sea", 130); // color will be brown, dam Alruccabam, sire Poseidon -record_new_horse_birth("Highclere", 175, "off-white", "Fall Aspen"); // sire will be Poseidon +record_new_horse_birth("Urban Sea", 130); // color will be brown, dam "Alruccabam", sire "Poseidon" +record_new_horse_birth("Highclere", 175, "off-white", "Fall Aspen"); // sire will be "Poseidon" ``` As the function declaration is often read before the definition, it is the better place to set the default arguments. From 383d3da25495dba6f33aa30a213d2b60eb164a1c Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Sun, 6 Aug 2023 14:28:54 +0200 Subject: [PATCH 5/6] Make the overloading part less technical --- concepts/functions/introduction.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/concepts/functions/introduction.md b/concepts/functions/introduction.md index a70b60c83..676ccd583 100644 --- a/concepts/functions/introduction.md +++ b/concepts/functions/introduction.md @@ -74,10 +74,11 @@ class Stubborn { ## Function overloading -If you take the function header without the return type, you get a function's __type signature__. -The type signature is defined by the function's name, the number of parameters, their types, and their qualifiers (but not their names). -A change in the signature results in a new function. -When two functions have the same name but differences in the rest of their type signature, the practice is called function overloading. +Multiple functions can have the same name if the parameter list is different. +That is called function overloading and it is usually done if these functions perform very similar tasks. + +The function header without the return type is the function's __type signature__. +A change in the type signature results in a new function. The `play_sound` example has six different overloads to accommodate different scenarios: @@ -95,8 +96,11 @@ void play_sound(vector& solfege); void play_sound(const vector& solfege); ``` +~~~~exercism/advanced +The type signature is defined by the function's name, the number of parameters, their types, and their qualifiers (but not their names). The return type is explicitly not part of the type signature and you will get compilation errors if you have two functions that only differ in their return type. The compiler will complain because it is not clear which of the two should be used. +~~~~ ## Default arguments From 31d00c2aab77f8b1fd695392d51f4e93206b53c9 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Sun, 6 Aug 2023 20:40:12 +0200 Subject: [PATCH 6/6] Last fixes --- concepts/functions/about.md | 123 ++++++++++++++++++++++++++++- concepts/functions/introduction.md | 9 ++- 2 files changed, 129 insertions(+), 3 deletions(-) diff --git a/concepts/functions/about.md b/concepts/functions/about.md index f39ee3c37..e2f12ed33 100644 --- a/concepts/functions/about.md +++ b/concepts/functions/about.md @@ -1,3 +1,124 @@ # About -[comment]: (Please fill with introduction.md content. For real.) \ No newline at end of file +## Terminology + +You have already used and written C++ functions in a couple of concepts. +It is time to get technical. +The code snippet below shows the most common terms for easy reference. +As C++ ignores whitespace, the formatting has been changed to put each element on a single line. + +```cpp +// Function declaration: +bool // Return type +admin_detected(string user, string password) // Type signature +; // Don't forget the ';' for the declaration + +// Function definition: +bool // Return type +admin_detected // Function name +(string user, string password) // Parameter list +{ return user == "admin" && password == "1234"; } // Function body +``` +~~~~exercism/advanced +The declaration works like a note to the compiler, that there is a function of that name, return type and parameter list. +The code will not work, if the definition is missing. +Declarations are optional, they are needed if you use the function before its definiton. +Declarations can solve problems like cyclic references and they can be used to separate the interface from the implementation. +~~~~ + +## The const qualifier + +Sometimes you want to make sure that values cannot be changed after they have been initialized. +C++ uses the `const` keyword as a qualifier for constants. + +```cpp +const int number_of_dragon_balls{7}; +number_of_dragon_balls--; // compilation error +``` + +~~~~exercism/note +You will often see constants written in _UPPER_SNAKE_CASE_. +It is recommened to reserve this casing for macros, if there is no other convention. +~~~~ + +If you try to change a constant variable after it has been set, your code will not compile. +This helps to avoid unintended changes but also opens up optimization possibilities for the compiler. +As a human, it is also easier to reason about the code, if you know that certain parts will not be affected. + +You can also have `const` as a qualifier for function parameters. + +```cpp +string guess_number(const int& secret, const int& guess) { + if (secret < guess) return "lower."; + if (secret > guess) return "higher."; + return "exact!"; +} +``` + +When you pass a `const` reference to the function, you can be sure that it will be left unchanged. +You will often see `const` references for objects that might be costly to copy, like longer strings. +A third use-case for the `const` qualifier are member functions that do not change the instance of a class. + +```cpp +class Stubborn { + public: + Stubborn(string reply) { + response = reply; + } + string answer(const string& question) const { + if (question.lenghth() == 0) { return "";} + return response; + } + private: + string response{}; +}; +``` + +The `Stubborn` member function `answer` uses a `const string&` reference as a parameter. +This avoids a copy operation from the original object that was passed to the function. + +## Function overloading + +Multiple functions can have the same name if the parameter list is different. +That is called function overloading and it is usually done if these functions perform very similar tasks. + +The function header without the return type is the function's __type signature__. +A change in the type signature results in a new function. + +The `play_sound` example has six different overloads to accommodate different scenarios: + +```cpp +// different argument types: +void play_sound(char note); // C, D, E, ..., B +void play_sound(string solfege); // do, re, mi, ..., ti +void play_sound(int jianpu); // 1, 2, 3, ..., 7 + +// different number of arguments: +void play_sound(string solfege, double duration); + +// different qualifiers: +void play_sound(vector& solfege); +void play_sound(const vector& solfege); +``` + +~~~~exercism/advanced +The type signature is defined by the function's name, the number of parameters, their types, and their qualifiers (but not their names). +The return type is explicitly not part of the type signature and you will get compilation errors if you have two functions that only differ in their return type. +The compiler will complain because it is not clear which of the two should be used. +~~~~ + +## Default arguments + +Some functions can get very lengthy and many of its calls might use the same values for most of the parameters. +The repetition in those calls can be avoided with default arguments. + +```cpp +void record_new_horse_birth(string name, int weight, string color="brown-ish", string dam="Alruccaba", string sire="Poseidon"); + +record_new_horse_birth("Urban Sea", 130); // color will be brown, dam "Alruccabam", sire "Poseidon" +record_new_horse_birth("Highclere", 175, "off-white", "Fall Aspen"); // sire will be "Poseidon" +``` + +As the function declaration is often read before the definition, it is the better place to set the default arguments. +If one parameter has a default declaration, all the parameters to its right need a default declaration as well. +Sometimes complicated function overloads can be refactored to fewer functions with default arguments to improve maintainability. diff --git a/concepts/functions/introduction.md b/concepts/functions/introduction.md index 676ccd583..b832a0a5a 100644 --- a/concepts/functions/introduction.md +++ b/concepts/functions/introduction.md @@ -9,7 +9,8 @@ As C++ ignores whitespace, the formatting has been changed to put each element o ```cpp // Function declaration: -bool admin_detected(string user, string password) // Function header +bool // Return type +admin_detected(string user, string password) // Type signature ; // Don't forget the ';' for the declaration // Function definition: @@ -64,7 +65,8 @@ class Stubborn { Stubborn(string reply) { response = reply; } - string answer() const { + string answer(const string& question) const { + if (question.lenghth() == 0) { return "";} return response; } private: @@ -72,6 +74,9 @@ class Stubborn { }; ``` +The `Stubborn` member function `answer` uses a `const string&` reference as a parameter. +This avoids a copy operation from the original object that was passed to the function. + ## Function overloading Multiple functions can have the same name if the parameter list is different.