Commit 0f97246e authored by CHAMONT David's avatar CHAMONT David
Browse files

Preparation de la seance 2 et des premiers travaux individuels.

parent cafd7d1a
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"nbgrader": {
"grade": false,
"grade_id": "cell-fa19ba3560e6cca6",
"locked": true,
"schema_version": 3,
"solution": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Modern C++: type inference"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Keyword `auto` as a variable type"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Starting with C++11, the type of a variable can be deduced from its initial value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"attributes": {
"classes": [
"cpp"
],
"id": ""
},
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"#include <vector>\n",
"#include <list>\n",
"std::map<std::vector<int>,std::list<float>> m ;\n",
"auto itr = m.begin() ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Possible `const` and `&` are dropped"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"int const i = 2 ; // int const\n",
"auto j = i ; // int\n",
"int & k = j ; // int &\n",
"auto l = k ; // int"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### On the contrary, one can add `const`, `&` or `*`"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"int i = 2 ;\n",
"auto & j = i ;\n",
"auto const & k = j ;\n",
"auto const * l = &k ;\n",
"auto const * const m = &l ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"attributes": {
"classes": [
"cpp"
],
"id": ""
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Keyword `decltype`"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### In order to reuse the type of an expression "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"std::map<std::vector<int>,std::list<float>> collection1 ;\n",
"decltype(collection1) collection2 ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### So to help type inference, when there is no initial value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"std::map<std::vector<int>,std::list<float>> collection ;\n",
"decltype(collection)::iterator itr ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### So to avoid `const` and `&` dropping"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"int i = 10 ; // int\n",
"int & j = i ; // int &\n",
"decltype(auto) k = i ; // int\n",
"decltype(auto) l = j ; // int &"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## How to know which type has infered the compiler ?\n",
"\n",
"* Your editor, if smart enough, may help.\n",
"* To be sure, you can also trigger an intentional compiler error, whose message contains the type name."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting tmp.inference.cpp\n"
]
}
],
"source": [
"%%file tmp.inference.cpp\n",
"\n",
"#include <vector>\n",
"\n",
"template <typename T> struct TypeDisplayer ;\n",
"\n",
"int main()\n",
" {\n",
" int const i = 2 ;\n",
" auto & j = i ;\n",
" TypeDisplayer<decltype(j)> td ;\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"scrolled": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tmp.inference.cpp: In function 'int main()':\n",
"tmp.inference.cpp:10:30: error: aggregate 'TypeDisplayer<const int&> td' has incomplete type and cannot be defined\n",
" 10 | TypeDisplayer<decltype(j)> td ;\n",
" | ^~\n"
]
}
],
"source": [
"!rm -f tmp.inference.exe && g++ -std=c++17 tmp.inference.cpp -o tmp.inference.exe"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Keyword `auto` as function return type\n",
"\n",
"When `auto` is used instead of the usual return type, the compiler will infer it from the return statements in the function body."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"auto nb( int i )\n",
" {\n",
" if (i<10) return 1 ;\n",
" if (i<100) return 2 ;\n",
" return 99 ;\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nb(15)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Keyword `auto` in a range-based for"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### What is a range-based for ?\n",
"\n",
"For any collection which is supported by `std::begin()` and `std::end()`, one can now use the **ranged-based for** notation."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"attributes": {
"classes": [
"cpp"
],
"id": ""
},
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.1 2.2 3.3 4.4 5.5 "
]
}
],
"source": [
"#include <iostream>\n",
"\n",
"int const MAX = 5 ;\n",
"double values[MAX] = { 1.1, 2.2, 3.3, 4.4, 5.5 } ;\n",
"\n",
"for ( double value : values )\n",
" { std::cout << value << \" \" ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Combined with `auto`"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"attributes": {
"classes": [
"cpp"
],
"id": ""
},
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.1 2.2 3.3 4.4 5.5 "
]
}
],
"source": [
"#include <vector>\n",
"#include <iostream>\n",
"\n",
"int i = 0 ;\n",
"double values[MAX] = { 1.1, 2.2, 3.3, 4.4, 5.5 } ;\n",
"\n",
"for ( auto value : values )\n",
" { std::cout << value << \" \" ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Modifications requires &"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"attributes": {
"classes": [
"cpp"
],
"id": ""
},
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 2 3 4 5 "
]
}
],
"source": [
"#include <iostream>\n",
"\n",
"int i = 0 ;\n",
"std::vector<int> values(5,0) ;\n",
"\n",
"for ( auto & value : values )\n",
" { value = ++i ; }\n",
"\n",
"for ( auto value : values ) \n",
" { std::cout << value << \" \" ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Questions ?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"## Exercise\n",
"\n",
"1. In the code below, simplify the operator `<<`.\n",
"2. Provide the class with methods `begin()` and `end()`.\n",
"3. Move the operator `` << '' outside the class."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Writing tmp.inference.cpp\n"
]
}
],
"source": [
"%%file tmp.inference.cpp\n",
"\n",
"#include <iostream>\n",
"#include <string>\n",
"#include <vector>\n",
"\n",
"class Sentence\n",
" {\n",
" public :\n",
" void add( char const * word )\n",
" { m_words.push_back(static_cast<std::string>(word)) ; }\n",
" friend std::ostream & operator<<( std::ostream & os, Sentence const & s )\n",
" {\n",
" typedef typename std::vector<std::string>::const_iterator Iterator ;\n",
" for ( Iterator word = s.m_words.begin() ; word != s.m_words.end() ; ++word )\n",
" { os<<(*word)<<\" \" ; }\n",
" return os ;\n",
" }\n",
" private :\n",
" std::vector<std::string> m_words ;\n",
" } ;\n",
"\n",
"int main()\n",
" {\n",
" Sentence s ;\n",
" s.add(\"Hello\") ;\n",
" s.add(\"world\") ;\n",
" s.add(\"!\") ;\n",
" std::cout<<s<<std::endl ;\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"!rm -f tmp.inference.exe && g++ -std=c++17 tmp.inference.cpp -o tmp.inference.exe"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello world ! \n"
]
}
],
"source": [
"!./tmp.inference.exe"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"© *CNRS 2020* \n",
"*This document was created by David Chamont and translated by Olga Abramkina. It is available under the [License Creative Commons - Attribution - No commercial use - Shared under the conditions 4.0 International](http://creativecommons.org/licenses/by-nc-sa/4.0/)*"
]
}
],
"metadata": {
"celltoolbar": "Diaporama",
"kernelspec": {
"display_name": "C++17",