{"id":5289,"date":"2017-07-29T06:34:15","date_gmt":"2017-07-29T06:34:15","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-functions\/"},"modified":"2023-06-26T12:09:33","modified_gmt":"2023-06-26T12:09:33","slug":"c-core-guidelines-functions","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-functions\/","title":{"rendered":"C++ Core Guidelines: Function Definitions"},"content":{"rendered":"<p>Functions are the &#8220;fundamental building block of programs.&#8221;&nbsp; and &#8220;the most critical part in most interfaces.&#8221;&nbsp; These statements introduce the rules to function of the C++ core guidelines. Of course, both statements are right. So, let&#8217;s dive deeper into the more than 30 rules for defining functions, passing arguments to functions, and returning values from functions.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p>I will not write about each rule in depth because there are too many rules. I will try to make a story out of the rules. Therefore, you and I can keep them in mind. Let&#8217;s start with the rules for defining functions. Here is an overview.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" alignright size-full wp-image-5288\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/cogs.jpg\" alt=\"cogs\" width=\"300\" height=\"225\" style=\"float: right;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/cogs.jpg 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/cogs-300x225.jpg 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<ul>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-package\">F.1: \u201cPackage\u201d meaningful operations as carefully named functions<\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-logical\">F.2: A function should perform a single logical operation<\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-single\">F.3: Keep functions short and simple<\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-constexpr\">F.4: If a function may have to be evaluated at compile time, declare it <code class=\"highlighter-rouge no-highlight\">constexpr<\/code><\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-inline\">F.5: If a function is very small and time-critical, declare it inline<\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-noexcept\">F.6: If your function may not throw, declare it <code class=\"highlighter-rouge no-highlight\">noexcept<\/code><\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-smart\">F.7: For general use, take <code class=\"highlighter-rouge no-highlight\">T*<\/code> or <code class=\"highlighter-rouge no-highlight\">T&amp;<\/code> arguments rather than smart pointers<\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-pure\">F.8: Prefer pure functions<\/a><\/li>\n<li><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-unused\">F.9: Unused parameters should be unnamed<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Function_definitions\"><\/span>Function definitions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"F1_%E2%80%9CPackage%E2%80%9D_meaningful_operations_as_carefully_named_functions\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-package\">F.1: \u201cPackage\u201d meaningful operations as carefully named functions<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<h3><span class=\"ez-toc-section\" id=\"F2_A_function_should_perform_a_single_logical_operation\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-logical\">F.2: A function should perform a single logical operation<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<h3><span class=\"ez-toc-section\" id=\"F3_Keep_functions_short_and_simple\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-single\">F.3: Keep functions short and simple<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The first three rules are pretty obvious and share a common idea. I will start with rule F2. If you write a function that <strong>performs a single logical operation (F2)<\/strong>, the function will become short and straightforward with a high likelihood<strong> (F3).&nbsp; <\/strong>The rules talk about functions that should fit on a screen. Now, you have these short and simple functions that do exactly one logical operation, and you should&nbsp;<strong>carefully give them names (F1). <\/strong>These carefully named functions are the basic building blocks to combine and build higher abstractions. Now, you have well-named functions and can easily reason about your program.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"F4_If_a_function_may_have_to_be_evaluated_at_compile-time_declare_it_constexpr\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-constexpr\">F.4: If a function may have to be evaluated at compile-time, declare it <code class=\"highlighter-rouge no-highlight\">constexpr<\/code><\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>A<span style=\"font-family: courier new,courier;\"> constexpr<\/span> function is a function that can run at compile time or run time. If you invoke a <span style=\"font-family: courier new,courier;\">constexpr<\/span> function with constant expressions and ask for the result at compile-time, you will get it at compile-time. If you invoke the <span style=\"font-family: courier new,courier;\">constexpr<\/span> function with arguments that can not be evaluated at compile-time, you can use it as an ordinary runtime function.&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">constexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">min<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> x, <span style=\"color: #007788; font-weight: bold;\">int<\/span> y) { <span style=\"color: #006699; font-weight: bold;\">return<\/span> x <span style=\"color: #555555;\">&lt;<\/span> y <span style=\"color: #555555;\">?<\/span> x <span style=\"color: #555555;\">:<\/span> y; }\r\n\r\nconstexpr <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res<span style=\"color: #555555;\">=<\/span> min(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>);\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> first <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">3<\/span>;\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> res2 <span style=\"color: #555555;\">=<\/span> min(first, <span style=\"color: #ff6600;\">4<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The function <span style=\"font-family: courier new,courier;\">min<\/span> has the potential to run at compile time. If I invoke <span style=\"font-family: courier new,courier;\">min<\/span> with constant expressions and ask for the result at compile-time, I will get it at compile-time: <span style=\"font-family: courier new,courier;\">constexpr <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res<span style=\"color: #555555;\">=<\/span> min(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>). <\/span>I have to use <span style=\"font-family: courier new,courier;\">min <\/span>as an ordinary function because&nbsp;<span style=\"font-family: courier new,courier;\">first&nbsp;<\/span>is not a constant expression:<span style=\"font-family: courier new,courier;\"> <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res2 <span style=\"color: #555555;\">=<\/span> min(first, <span style=\"color: #ff6600;\">4<\/span>).<\/span><\/p>\n<p>There is a lot more to <span style=\"font-family: courier new,courier;\">constexpr<\/span> functions. Their syntax was somewhat limited with C++11, and they became pretty comfortable with C++14. They are a kind of pure function in C++. See my posts about <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/constexpr\">constexpr<\/a>.<\/p>\n<\/p>\n<h3><span class=\"ez-toc-section\" id=\"F5_If_a_function_is_very_small_and_time-critical_declare_it_inline\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-inline\">F.5: If a function is very small and time-critical, declare it inline<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>I was astonished to read this rule because the optimizer will <span style=\"font-family: courier new,courier;\">inline<\/span> functions that are not declared <span style=\"font-family: courier new,courier;\">inline<\/span>, and the other way around: they will not <span style=\"font-family: courier new,courier;\">inline<\/span> functions, although you declare them as <span style=\"font-family: courier new,courier;\">inline. <\/span>In the end, inline is only a hint for the optimizer.&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">constexpr<\/span> implies <span style=\"font-family: courier new,courier;\">inline.<\/span> The same holds, by default, <code>true<\/code> for member functions defined in the class or function templates.<\/p>\n<p>With modern compilers, the main reason for using <span style=\"font-family: courier new,courier;\">inline<\/span> is to break the One Definition Rule (ODR). You can define an <span style=\"font-family: courier new,courier;\">inline<\/span> function in more than one translation unit. Here is my post about <a href=\"https:\/\/www.modernescpp.com\/index.php\/inline\">inline.<\/a><\/p>\n<h3><span class=\"ez-toc-section\" id=\"F6_If_your_function_may_not_throw_declare_it_noexcept\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-noexcept\">F.6: If your function may not throw, declare it <code class=\"highlighter-rouge no-highlight\">noexcept<\/code><\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>By declaring a function as <span style=\"font-family: courier new,courier;\">noexcept,<\/span> you reduce the number of alternative control paths; therefore, <span style=\"font-family: courier new,courier;\">noexecpt<\/span> is a valuable hint to the optimizer.<\/p>\n<p>Even if your function can throw, <span style=\"font-family: courier new,courier;\">noexcept<\/span> often makes a lot of sense. <span style=\"font-family: courier new,courier;\">noexcept<\/span> means in such case: I don&#8217;t care. The reason may be that you cannot react to an exception. Therefore, the only way to deal with exceptions is that <span style=\"font-family: courier new,courier;\">terminate()<\/span> will be invoked. <span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p>Here is an example of a<span style=\"font-family: courier new,courier;\"><\/span>function declared as <span style=\"font-family: courier new,courier;\">noexcept<\/span> that may throw because the program may run out of memory.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">vector<span style=\"color: #555555;\">&lt;<\/span>string<span style=\"color: #555555;\">&gt;<\/span> collect(istream<span style=\"color: #555555;\">&amp;<\/span> is) noexcept\r\n{\r\n    vector<span style=\"color: #555555;\">&lt;<\/span>string<span style=\"color: #555555;\">&gt;<\/span> res;\r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (string s; is <span style=\"color: #555555;\">&gt;&gt;<\/span> s;)\r\n        res.push_back(s);\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> res;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"F7_For_general_use_take_T_or_T_arguments_rather_than_smart_pointers\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-smart\">F.7: For general use, take <code class=\"highlighter-rouge no-highlight\">T*<\/code> or <code class=\"highlighter-rouge no-highlight\">T&amp;<\/code> arguments rather than smart pointers<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>You restrict the usage of your functions by using Smart Pointers. The example makes the point clear.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ accepts any int*<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">f<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">*<\/span>);\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ can only accept ints for which you want to transfer ownership<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">u<\/span>(unique_ptr<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span>);\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ can only accept ints for which you are willing to share ownership<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">s<\/span>(shared_ptr<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span>);<span style=\"color: #007788; font-weight: bold;\"><\/span><span style=\"color: #cc00ff;\"><\/span><span style=\"color: #006699; font-weight: bold;\"><\/span><span style=\"color: #555555;\"><\/span><span style=\"color: #007788; font-weight: bold;\"><\/span><span style=\"color: #555555;\"><\/span>\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ accepts any int<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">h<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The functions <span style=\"font-family: courier new,courier;\">u<\/span> and <span style=\"font-family: courier new,courier;\">s<\/span> have unique ownership semantics. <span style=\"font-family: courier new,courier;\">u<\/span> want to transfer ownership, <span style=\"font-family: courier new,courier;\">s<\/span> wants to share ownership. The function <code>s<\/code> includes a minor performance penalty. The reference counter of the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> has to be increased and decreased. This atomic operation takes a little bit of time.&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"F8_Prefer_pure_functions\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-pure\">F.8: Prefer pure functions<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>A pure function is a function that always returns the same value when given the same arguments. This property is also often called <a href=\"https:\/\/en.wikipedia.org\/wiki\/Referential_transparency\">referential transparency<\/a>.<\/p>\n<p>Pure functions have a few interesting properties:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5154\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/PureImpureFunctionsEng.png\" alt=\"PureImpureFunctionsEng\" width=\"500\" height=\"132\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/PureImpureFunctionsEng.png 867w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/PureImpureFunctionsEng-300x79.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/PureImpureFunctionsEng-768x203.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>These properties have far-reaching consequences because you can think about your function in isolation:<\/p>\n<ul>\n<li>The correctness of the code is easier to verify<\/li>\n<li>The refactoring and testing of the code are simpler<\/li>\n<li>You can memorize function results<\/li>\n<li>You can reorder pure functions or perform them on other threads.<\/li>\n<\/ul>\n<p>Pure functions are often called mathematical functions.<\/p>\n<p>By default, we have no pure functions in C++, such as the purely functional language Haskell, but <span style=\"font-family: courier new,courier;\">constexpr<\/span> functions are nearly pure. So pureness is based on discipline in C++.<\/p>\n<p>Only for completeness. Template metaprogramming is a purely functional language embedded in the imperative language C++. If you are curious, read here about <a href=\"https:\/\/www.modernescpp.com\/index.php\/functional-in-c-98\">template metaprogramming.<\/a><\/p>\n<h3><span class=\"ez-toc-section\" id=\"F9_Unused_parameters_should_be_unnamed\"><\/span><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-unused\">F.9: Unused parameters should be unnamed<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If you don&#8217;t provide names for the unused parameters, your program will be easier to read and will not get warnings about unused parameters.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Whats_next\"><\/span>What&#8217;s next<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>These were the rules about function definitions. I will write about the parameter passing to functions in the next post.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Functions are the &#8220;fundamental building block of programs.&#8221;&nbsp; and &#8220;the most critical part in most interfaces.&#8221;&nbsp; These statements introduce the rules to function of the C++ core guidelines. Of course, both statements are right. So, let&#8217;s dive deeper into the more than 30 rules for defining functions, passing arguments to functions, and returning values from [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":5288,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[503],"class_list":["post-5289","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-functions"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5289","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5289"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5289\/revisions"}],"predecessor-version":[{"id":6867,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5289\/revisions\/6867"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5288"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5289"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5289"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5289"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}