Commit 07816f2c authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Merge branch 'master' into 'smallsuggestions'

# Conflicts:
#   lecture/06_arrays.tex
#   lecture/08_classes.tex
#   lecture/14_metaprogramming.tex
parents 23a5b1cf 88f956a6
......@@ -3,7 +3,7 @@ Educational Community License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may
obtain a copy of the License at
http://www.osedu.org/licenses/ECL-2.0
https://opensource.org/licenses/ECL-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS"
......
......@@ -25,7 +25,7 @@ example is the `map` operation, that takes a range and applies a functor to each
range:
```python
for x in map(lambda x: 2*x, range(0,10)):
print x
print(x)
```
Here, an integer range `[0, 10)` is created and the entries are scaled by a factor 2, but only during iteration in
the loop. We want to implement something similar in C++:
......
......@@ -264,7 +264,7 @@ Example 2: The definition of a template function (included at the end of the hea
\begin{minted}[frame=lines,label={example.impl.hh}]{c++}
#pragma once
// definition of the funktion foo()
// definition of the function foo()
template <class T>
void foo() { /*...*/ }
\end{minted}
......@@ -419,7 +419,7 @@ Examples:
Test obj(); // declaration of a funktion (with return type Test)
\end{minted}
A fundamental rule is that you are not allowed two define an object twice. While it may be allowed to declare exactly the same object multiple times, even after the definition.
A fundamental rule is that you are not allowed to define an object twice. While it may be allowed to declare exactly the same object multiple times, even after the definition.
\begin{standard}{\S 6.3 (1)}
\textbf{One-definition rule:} No translation unit shall contain more than one definition of any variable, function, class type, enumeration
......@@ -603,7 +603,7 @@ Some examples of narrowing conversions:
unsigned u3 = {3};
int i3 = {2};
unsigned u4 = {i2}; // Narrowing ERROR: no negative values
unsigned u4 = {i3}; // Narrowing ERROR: no negative values
int i4 = {u3}; // Narrowing ERROR: no all values
\end{minted}
......@@ -655,7 +655,7 @@ Constants can be defined using automatic type deduction. Therefore, the keyword
\end{minted}
\subsubsection{constexpr specifier}
There is another qualifier that is stronger that \cpp{const}: The \cpp{constexpr} specifier declares that it is possible to evaluate the
There is another qualifier that is stronger than \cpp{const}: The \cpp{constexpr} specifier declares that it is possible to evaluate the
value of the variable at compile time. Such variables can then be used where only compile time constant expressions are allowed.
A \cpp{constexpr} specifier used in an object declaration implies \cpp{const}.
......@@ -679,7 +679,7 @@ The category \emph{LiteralType} cannot yet be fully explained, but especially th
\subsection{Scopes}
Each name that appears in a C++ program is only valid in some possibly discontiguous portion of the source code called its scope. Thus,
scopes determine the lifetime and visibility of (non-static) variables and constants. There are different types of scopes,
global scope, function scope, class scope, block scope, function parameter scope, namespace scope, \dots. Typically, scopes a blocks of
global scope, function scope, class scope, block scope, function parameter scope, namespace scope, \dots. Typically, scopes are blocks of
code surrounded by curly braces, except for the global scope that lives outside of functions and classes.
\begin{guideline}{Principle}
......@@ -719,7 +719,7 @@ used to declare a new variable hiding the outer one with lifetime only in that n
x = 1; // assignment to local x (1)
{
int x; // (2) hides local x (1)
x = 2; // assignment ot local x (2)
x = 2; // assignment to local x (2)
}
x = 3; // assignment to local x (1)
}
......
......@@ -129,7 +129,7 @@ Operator & Action \\
\begin{rem}
With \cxx{20}\marginpar{[\cxx{20}]} a new comparison operator will be introduced, called \emph{three-way comparison operator}
or sometimes also \emph{space-ship operator}. It is written as \cpp{<=>} and returns and object such that
or sometimes also \emph{space-ship operator}. It is written as \cpp{<=>} and returns an object such that
\begin{itemize}
\item \cpp{(a <=> b) < 0} if \cpp{lhs < rhs}
\item \cpp{(a <=> b) > 0} if \cpp{lhs > rhs}
......@@ -250,7 +250,7 @@ at all or not, \ie
int foo(int a, int b) { return a + b; }
int x = 1;
foo(++x, x++); // Variant 1 (behavior undefiniert)
foo(++x, x++); // Variant 1 (undefined behavior)
x = 1;
int a = ++x, b = x++;
......
......@@ -415,7 +415,7 @@ In order to resolve a function call, \ie to find the right function to evaluate,
int main() {
int i;
int cont ic = 0;
int const ic = 0;
short s = 0;
foo(i, 1L); // 1st argument: i -> int& is better than i -> int const&
......
\section{References and Pointers\label{sec:references}}
Although used already, the references need a revisit. References can be understood as alias to (existing) objects. Compared to classical
pointer, they do not represent the address of the references object, but the data of the objects directly.
......@@ -18,7 +17,7 @@ r = 1; // changes the value of i => i == 1
i = 2; // also r == 2
\end{minted}
References itself are no objects and do not need own memory. That is why there are no arrays of references and no references of references!
References itself are not objects and do not need own memory. That is why there are no arrays of references and no references of references!
\begin{minted}{c++}
int& a[3]; // error
int& &r; // error
......@@ -152,7 +151,7 @@ T&& problematic = xvalue();
% -------------------------------------------------------------------------------------------------
\subsection{Pointers}
Referencing to something in memory could be understood as just storing the address of that memory. An address ist just an integer indicating
the position in memory relative to some initial address. But, we need more than just the adress, we need the type of the data that we are
the position in memory relative to some initial address. But, we need more than just the address, we need the type of the data that we are
referring to, so that we can give the memory a meaning. This is called a pointer:
%
\cppline{TYPE * pointer = &OBJECT;}
......@@ -168,7 +167,7 @@ The \textit{dual} operator to the address-of operator is the de-reference operat
where \texttt{POINTER} must be any object of pointer type. So, the dereferenced pointer is again an lvalue.
Pointers can be combined with \cpp{const} qualifiers, to either indicate that the addressed data is immutable or that the address value is constant.
Which one you mean is determined by the position of the \cpp{const} qualifier, \ie
This behaviour is determined by the position of the \cpp{const} qualifier, \ie
%
\begin{minted}{c++}
int data = 42, data2 = 1234;
......
......@@ -51,7 +51,7 @@ double A[2][3] =
Example:
\cppline{int foo[5] {1,2,3}; // [1,2,3,0,0]}
(The assignment operator ``\cpp{=}'' is here replaced by \textit{universal initialisation}.)
(The assignment operator ``\cpp{=}'' is here replaced by \textit{Universal Initialization}.)
\end{rem}
A multi-dimensional array can be written with a one-dimensional initializer-list. In that case, the initialization happens arrays-wise.
......
......@@ -89,7 +89,7 @@ If you have a complicated or multiple enclosed namespaces, you can introduce a n
%
\begin{minted}{c++}
namespace Q {
namespace V { // sub-namensraum of Q
namespace V { // sub-namespace of Q
void f() {}; // declaration of Q::V::f
}
}
......
......@@ -485,7 +485,7 @@ leaving it in an undetermined state. This requires that the moved-from object is
an rvalue. So, move constructors expect as single argument an \underline{rvalue-reference} to the class-type: \cpp{MyPoint(MyPoint&& that)}.
Move constructors are introduced in \cxx{11} (together with rvalue reference) to allow the fast construction of copies of objects, that are destroyed anyway.
Thus, one just use the data ob the temporary object, without copying it. This can be motivated by a class storing a pointer to a large dynamic array
Thus, one just use the data of the temporary object, without copying it. This can be motivated by a class storing a pointer to a large dynamic array
that was allocated in some constructor and would be destroyed in a destructor. Instead of copying all the elements of that array, a move-constructor
could just copy the pointer to the array and set it to \cpp{nullptr} inside the moved-from object to forbid the deallocation:
%
......
\chapter{Iterators}
A central layer ob abstraction introduced in the C++ standard library are \emph{iterators}. Genrally speaking, iterators are objects allowing the
A central layer of abstraction introduced in the C++ standard library are \emph{iterators}. Genrally speaking, iterators are objects allowing the
programmer to traverse the elements of an arbitrary container, without knowing the specific implementation, the data storage or the access pattern to
individual elements of that data-structure. While vectors and arrays may have a direct element access, using the \cpp{operator[]}, lists and trees do
not have such a method, or it might be very expensive to retrieve a specific element in the sequence rather than traversing linearly through the container.
......@@ -164,7 +164,7 @@ In order to allow iterators to be passed to functions, one needs function templa
% -------------------------------------------------------------------------------------------------
\subsection{Iterator categories}
Not all iterators support iteration forward and backward. Some iterators not even support multiple iterations through the same sequence
(after the first traversal, als elements are invalidated), but other containers might even support jumping to an arbitrary position in the
(after the first traversal, elements are invalidated), but other containers might even support jumping to an arbitrary position in the
sequence.
To distinguish the different functionality of iterators, the standard library has introduced \emph{iterator categories}:
......@@ -372,7 +372,7 @@ only copies those elements fulfilling some condition.
\end{samepage}
%
The parameters \texttt{first} and \texttt{last} are iterators of type \texttt{InputIt} and should fulfill the concepts of an input-iterator. The
thirst parameter \texttt{d\_first} is an out-iterator pointing to the first element in the output range. It is of type \texttt{OutputIt}. The
third parameter \texttt{d\_first} is an out-iterator pointing to the first element in the output range. It is of type \texttt{OutputIt}. The
types \texttt{InputIt} and \texttt{OutputIt} are different, allowing to copy from one container in a different one.
The return value of the copy function is again of type \texttt{OutputIt} and thus an iterator into the output range. It points to one-past the element
......
......@@ -2,7 +2,7 @@
An advantage of generic programming is that we can reuse the same code for multiple types/arguments/parameters. Although this gives us a lot of flexibility
sometimes we want to be more specific, \ie some algorithms require special knowledge about the data types used to allow an efficient implementation. Some
types have additional guarantees (\eg contiguous storage of its data elements) or allow more (efficient) operations (\eg containers with optimized sorting
algorithm directly implemented and not by the generic \cpp{std::sort} function). In such cases is would be advantages to provide a more specialized implementation
algorithm directly implemented and not by the generic \cpp{std::sort} function). In such cases is would be advantageous to provide a more specialized implementation
of the same algorithm or data-structure without loosing the generic version for the other types.
\begin{example}
......@@ -68,7 +68,7 @@ Some examples:
template <class T>
class MyPoint<T, long> { ... }; // (b)
// specialization for element type `M<Point<T,int>' where `T` could be any type
// specialization for element type `MyPoint<T,int>' where `T` could be any type
// and fixed index type `int`
template <class T>
class MyPoint< MyPoint<T,int>, int > { ... }; // (c)
......@@ -77,7 +77,7 @@ Some examples:
% ==============================================================================
\section{Partielle Spezialisierung}\label{seq:partial_template_specialization}
\section{Partial Template Specialization}\label{seq:partial_template_specialization}
If not all template parameters are fixed (specialized) and the template parameter list is not empty, the specialization is called
\emph{partial template specialization}. This is allowed for class templates only! The specialization parameters can depend on some or all remaining
template parameters in the template parameter list, \eg
......
......@@ -51,7 +51,7 @@ We distinguish two types of template metaprogramming
% -------------------------------------------------------------------------------------------------
\subsection{Metafunctions}
Classical function get their inputs as values in the function parameters can return values wither in the return statement or in an output
Classical function get their inputs as values in the function parameters can return values either in the return statement or in an output
function parameter. In contrast, metafunctions get their input as template parameters and provide their results either as typedef (type alias)
or as static constant. Thereby, metafunctions are typically class templates.
......@@ -204,7 +204,7 @@ and the corresponding assembler code:
\subsubsection{Value aliases}
Instead of accessing the result of a computation in a template metafunction by the \cpp{value} member, it is common standard to
introduce a variable template for this purpose that simplifies the calles and makes it look very similar to regular function calls:
introduce a variable template for this purpose that simplifies the calls and makes it look very similar to regular function calls:
%
\begin{minted}{c++}
template <int N>
......
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