Commit 67689ca1 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

Fixes following review by @steff.

parent afbf8fac
Pipeline #246993 passed with stage
in 11 minutes and 35 seconds
%% Cell type:markdown id: tags:
# [Getting started in C++](/) - [Procedural programming](./0-main.ipynb) - [Static and constexpr](./7-StaticAndConstexpr.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#Static-keyword" data-toc-modified-id="Static-keyword-1">Static keyword</a></span></li><li><span><a href="#Constexpr" data-toc-modified-id="Constexpr-2">Constexpr</a></span></li></ul></div>
%% Cell type:markdown id: tags:
## Static keyword
%% Cell type:markdown id: tags:
`static` may be seen as _at compile time_, whereas `dynamic` may be seen as _at runtime_.
A reply to this [StackOverflow question](https://stackoverflow.com/questions/572547/what-does-static-mean-in-c) gives a rather good summary of what `static` means in C (we shall see [later](./2-ObjectProgramming/5-static.ipynb) a C++-only keyword that unfortunately share the same moniker):
A reply to this [StackOverflow question](https://stackoverflow.com/questions/572547/what-does-static-mean-in-c) gives a rather good summary of what `static` means in C (we shall see [later](../2-ObjectProgramming/5-static.ipynb) a C++-only keyword that unfortunately share the same moniker):
* Static defined local variables do not lose their value between function calls. In other words they are global variables, but scoped to the local function they are defined in.
* Static global variables are not visible outside of the C file they are defined in.
* Static functions are not visible outside of the C file they are defined in.
Only the first one is really relevant in C++, as for quantities that should be accessible only in the current file C++ provides a concept of his own: the [**unnamed namespace**](../6-InRealEnvironment/5-Namespace.ipynb#Unnamed-namespace).
Only the first one is really relevant in C++, as for variables that should be accessible only in the current file C++ provides a concept of his own: the [**unnamed namespace**](../6-InRealEnvironment/5-Namespace.ipynb#Unnamed-namespace).
Let's see the remaining case in action:
Let's see this first case in action:
%% Cell type:code id: tags:
``` C++17
#include <iostream>
void FunctionWithStatic()
{
static int n = 0; // This initialisation occurs only at first call
// But `n` is not destroyed when the end bracket is reached and remains available
// in subsequent calls. However, `n` is available only inside this function.
std::cout << "The function has been called " << ++n << " times." << std::endl;
}
```
%% Cell type:code id: tags:
``` C++17
{
for (int i = 0; i < 5; ++i)
FunctionWithStatic();
}
```
%% Cell type:markdown id: tags:
It might be used for instance if you need to initialize something on the very first call of a function:
%% Cell type:code id: tags:
``` C++17
// Pseudo-code
void FunctionWithStatic()
{
static bool is_first_call = true;
if (is_first_call)
{
// Init stuff here on first call only, for instance something that requires heavy computation.
// ...
is_first_call = false;
}
// ... code executed at each call
}
```
%% Cell type:markdown id: tags:
## Constexpr
We've seen the allocation of an array on the stack follows this syntax:
%% Cell type:code id: tags:
``` C++17
int array[5ul];
```
%% Cell type:markdown id: tags:
where the size of the array is available at compile time (if not you have to use an array allocated on the heap at runtime).
Now imagine we want to init such an array with a size that results from a computation; let's say a Fibonacci series:
%% Cell type:code id: tags:
``` C++17
// Recursive function - Xeus cling may not appreciate if you call this cell several times.
auto fibonacci (std::size_t n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
return fibonacci(n-1) + fibonacci(n-2);
}
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
std::cout << fibonacci(5) << std::endl;
std::cout << fibonacci(10) << std::endl;
```
%% Cell type:code id: tags:
``` C++17
double array[fibonacci(5)]; // COMPILATION ERROR!
```
%% Cell type:markdown id: tags:
This doesn't seem outlandish: a computation is involved and this computation happens at runtime - even if in fact all the required elements to perform it were available at runtime (there were for instance no argument read from command line involved).
In C++ 03, you had two choices to resolve this
- Using a macro...
- Or using [metaprogramming](../4-Templates/4-Metaprogramming.ipynb) which is a tad overkill... (and involves boilerplate code).
C++ introduced the keyword `constexpr`, which indicates something happens at compile time. It might be used for just a variable, or for more complicated construct such as functions or classes. The only requirement is that all the subparts used are themselves `constexpr`.
%% Cell type:code id: tags:
``` C++17
constexpr auto fibonacci_const (std::size_t n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
return fibonacci_const(n-1) + fibonacci_const(n-2);
}
```
%% Cell type:code id: tags:
``` C++17
double array[fibonacci_const(5)]; // Ok!
```
%% Cell type:markdown id: tags:
`constexpr` function may also be used as runtime function, but in this case their results can't of course be used at compile time.
%% Cell type:code id: tags:
``` C++17
#include <iostream>
int i = 7;
++i; // i is by no stretch a compile time variable!
std::cout << fibonacci_const(7) << std::endl;
```
%% Cell type:markdown id: tags:
`constexpr` becomes increasingly powerful over time:
- The function `fibonacci_const` above does not in fact work before C++ 14: this version of the standard introduced the possibility to provide several `return` in a `constexpr` function.
- `constexpr` is added wherever possible in the STL. This is still a work in progress: if you look for instance the [CppReference page](https://en.cppreference.com/w/cpp/algorithm/count) for `std::count` algorithm, you will see this algorithm becomes `constexpr` in C++ 20.
We will see another use of `constexpr` in a [later notebook](../4-Templates/2-Specialization.ipynb#If-constexpr).
%% Cell type:markdown id: tags:
© _CNRS 2016_ - _Inria 2018-2021_
_This notebook is an adaptation of a lecture prepared by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
_The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment