C++ Core Guidelines: Function Definitions

Functions are the "fundamental building block of programs."  and "the most critical part in most interfaces."  These statements introduce the rules to function of the C++ core guidelines. Of course, both statements are absolutely right. So, let's dive deeper into the more than 30 rules for defining functions, passing arguments to functions, and returning values from functions.

 

I will not write about each rule in depth because there are way too many rules. I will try to make a story out of the rules, therefore, you and I can keep them in mind. Let's start with the rules for defining functions. Here is an overview.

cogs

 

 

Function definitions

F.1: “Package” meaningful operations as carefully named functions

F.2: A function should perform a single logical operation

F.3: Keep functions short and simple

The first three rules are quite obvious and share a common idea. I will start with rule F2. If you write a function, that performs a single logical operation (F2), the function will with a high likelihood become short and simple (F3).  The rules talk about functions that should fit on a screen. Now, you have these short and simple functions that exactly do one logical operation and you should carefully give them names (F1). These carefully named functions are the basic building blocks that you can combine and build higher abstractions. Now, you have well-named functions and you can reason about your program quite easily.

F.4: If a function may have to be evaluated at compile-time, declare it constexpr

A constexpr function is a function that can run at compile time or run time. If you invoke a constexpr function with constant expressions and you ask for the result at compile-time, you will get it at compile time. If you invoke the constexpr function with arguments that can not be evaluated at compile-time, you can use it as an ordinary runtime function. 

 

constexpr int min(int x, int y) { return x < y ? x : y; }

constexpr auto res= min(3, 4);

int first = 3;
auto res2 = min(first, 4);

 

The function min has the potential to run at compile time. If I invoke min with constant expressions and ask for the result at compile-time, I will get it at compile time: constexpr auto res= min(3, 4). I have to use min as an ordinary function because first is not a constant expression: auto res2 = min(first, 4).

There is a lot more to constexpr functions. Their syntax was rather limited with C++11 and become quite comfortable with C++14. They are a kind of pure functions in C++. See my posts about constexpr.

 

Rainer D 6 P2 540x540Modernes C++ Mentoring

Stay informed about my mentoring programs.

 

 

Subscribe via E-Mail.

F.5: If a function is very small and time-critical, declare it inline

I was really astonished to read this rule because the optimizer will inline functions, that are not declared inline, and the other way around: they will not inline functions, although you declare them as inline. In the end, inline is only a hint for the optimizer. 

constexpr implies inline. The same holds by default true for member functions defined in the class, or function templates.

With modern compilers, the main reason for using inline is to break the One Definition Rule (ODR). You can define an inline function in more than one translation unit. Here is my post about inline.

F.6: If your function may not throw, declare it noexcept

By declaring a function as noexcept, you reduce the number of alternative control paths; therefore, noexecpt is a valuable hint to the optimizer.

Even if your function can throw, noexcept makes often a lot of sense. noexcept just means in such case: I don't care. The reason may be that you have no way to react to an exception. Therefore, the only way to deal with exceptions is that terminate() will be invoked.

Here is an example of afunction declared as noexcept that may throw, because the program may run out of memory.

vector<string> collect(istream& is) noexcept
{
    vector<string> res;
    for (string s; is >> s;)
        res.push_back(s);
    return res;
}

 

F.7: For general use, take T* or T& arguments rather than smart pointers

You restrict the usage of your functions by using Smart Pointers. The example makes the point clear.

// accepts any int*
void f(int*);

// can only accept ints for which you want to transfer ownership
void u(unique_ptr<int>);

// can only accept ints for which you are willing to share ownership
void s(shared_ptr<int>);

// accepts any int
void h(int&);

 

The functions u and s have special ownership semantic. u want to transfer ownership, s wants to share ownership. The function s includes a small performance penalty. The reference counter of the std::shared_ptr has to be increased and decreased. This atomic operation takes a little bit of time. 

F.8: Prefer pure functions

A pure function is a function that always returns the same value when given the same arguments. This property is also often called referential transparency.

Pure functions have a few interesting properties:

PureImpureFunctionsEng

These properties have far-reaching consequences because you can think about your function in isolation:

  • The correctness of the code is easier to verify
  • The refactoring and testing of the code is simpler
  • You can memorize function results
  • You can reorder pure functions or perform them on other threads.

Pure functions are often called mathematical functions.

By default, we have no pure functions in C++ such as the purely functional language Haskell, but constexpr functions are nearly pure. So pureness is based on discipline in C++.

Only for completeness. Template metaprogramming is a purely functional language embedded in the imperative language C++. If you are curious, read here about template metaprogramming.

F.9: Unused parameters should be unnamed

If you don't provide names for the unused parameters, your program will be easier to read and you will not get warnings about unused parameters.

What's next

These were the rules about function definitions. In the next post, I will write about the parameter passing to functions.

 

 

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, and Ann Shatoff.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, and Slavko Radman.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

My special thanks to PVS-Studio PVC Logo

 

My special thanks to Tipi.build tipi.build logo

Seminars

I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ - The Core Language
  • C++ - The Standard Library
  • C++ - Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++

New

  • Clean Code with Modern C++
  • C++20

Contact Me

Modernes C++,

RainerGrimmDunkelBlauSmall

Tags: Functions

Comments   

+1 #1 Jeremiah 2017-10-18 00:48
Very nice blog post. I certainly appreciate this website.
Keep writing!
Quote
+1 #2 Johnette 2017-11-11 20:50
Your method of describing the whole thing in this paragraph is actually fastidious, every
one be capable of without difficulty understand it, Thhanks a lot.
Quote

Mentoring

Stay Informed about my Mentoring

 

English Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Interactive Course: The All-in-One Guide to C++20

Subscribe to the newsletter (+ pdf bundle)

All tags

Blog archive

Source Code

Visitors

Today 2737

Yesterday 5317

Week 2737

Month 146908

All 11628062

Currently are 278 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments