Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
c_1y_-_les_tableaux [2014/03/09 22:09] gbdivers |
c_1y_-_les_tableaux [2020/10/25 03:52] (Version actuelle) issam Correction nom de variable |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ====== C++1y - Les tableaux ====== | ||
+ | |||
Pour commencer le tour des nouvelles fonctionnalités proposées par les prochaines normes du C++ (je parle au pluriel puisqu'il devrait y avoir la sortie d'une nouvelle norme, le C++14, et de plusieurs //Technical Specification//. Voir l'article [[Les derniers jours du C++11 ?]] pour les détails), je vais faire le tour des différents TS avant d'aborder les détails du C++14. Enfin, je terminerais par faire une review des différents drafts pour le [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/#mailing2014-01|meeting de Issaquah]]. Dans cet article, je vais donc parler des nouvelles fonctionnalités concernant les tableaux : | Pour commencer le tour des nouvelles fonctionnalités proposées par les prochaines normes du C++ (je parle au pluriel puisqu'il devrait y avoir la sortie d'une nouvelle norme, le C++14, et de plusieurs //Technical Specification//. Voir l'article [[Les derniers jours du C++11 ?]] pour les détails), je vais faire le tour des différents TS avant d'aborder les détails du C++14. Enfin, je terminerais par faire une review des différents drafts pour le [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/#mailing2014-01|meeting de Issaquah]]. Dans cet article, je vais donc parler des nouvelles fonctionnalités concernant les tableaux : | ||
Ligne 4: | Ligne 6: | ||
* [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3824.htm|N3824]], qui propose l'ajout d'une fonction //make_array// pour créer des tableaux statiques [[http://en.cppreference.com/w/cpp/container/array|std::array]] ; | * [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3824.htm|N3824]], qui propose l'ajout d'une fonction //make_array// pour créer des tableaux statiques [[http://en.cppreference.com/w/cpp/container/array|std::array]] ; | ||
* [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3869.html|N3869]] et [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html|N3870]], pour étendre l'utilisation de [[http://en.cppreference.com/w/cpp/memory/shared_ptr|std::shared_ptr]] et [[http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared|std::make_shared]] aux tableaux style C ; | * [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3869.html|N3869]] et [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html|N3870]], pour étendre l'utilisation de [[http://en.cppreference.com/w/cpp/memory/shared_ptr|std::shared_ptr]] et [[http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared|std::make_shared]] aux tableaux style C ; | ||
- | * [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3851.pdf|N3851]], qui propose l'ajout des tableaux à plusieurs dimensions. | + | * [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3851.pdf|N3851]] et la mise à jour [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3976.html|N3976]], qui propose l'ajout des tableaux à plusieurs dimensions. |
- | ====== Les tableaux de taille connue à l'exécution ====== | + | ===== Les tableaux de taille connue à l'exécution ===== |
Pour créer un tableau d'éléments contiguë en mémoire, nous avons actuellement plusieurs approches possibles. Les critères permettant d'orienter le choix sont : | Pour créer un tableau d'éléments contiguë en mémoire, nous avons actuellement plusieurs approches possibles. Les critères permettant d'orienter le choix sont : | ||
Ligne 15: | Ligne 17: | ||
Selon ces 2 critères, nous allons donc avoir 4 choix possibles : | Selon ces 2 critères, nous allons donc avoir 4 choix possibles : | ||
- | ===== 1. Utiliser les tableaux statiques style C ===== | + | ==== 1. Utiliser les tableaux statiques style C ==== |
<code cpp> | <code cpp> | ||
- | auto t1 = {0, 1, 2, 3}; // tableau d'entier | + | int t1[] = {0, 1, 2, 3}; // tableau de 4 entiers |
- | int t2[] = {0, 1, 2, 3}; // déclaration explicite du type | + | auto s = "un chaine"; // tableau de caractères constants (const char) |
- | auto s = "un chaine"; // tableau de caractères const char* | + | |
</code> | </code> | ||
Ligne 31: | Ligne 32: | ||
L'inconvénient est que le tableau n'encapsule pas l'information sur sa taille et donc le risque de se tromper et sortir des limites du tableau est plus grand. De plus, ce code n'est pas évolutif, si on change la taille du tableau, il faut modifier toutes les lignes de code utilisant ce tableau. | L'inconvénient est que le tableau n'encapsule pas l'information sur sa taille et donc le risque de se tromper et sortir des limites du tableau est plus grand. De plus, ce code n'est pas évolutif, si on change la taille du tableau, il faut modifier toutes les lignes de code utilisant ce tableau. | ||
- | ===== 2. Utiliser les tableaux statiques std::array ===== | + | ==== 2. Utiliser les tableaux statiques std::array ==== |
Ce type de tableau a été introduit dans le C++11 pour fournir des tableaux statiques similaires aux tableaux statiques style C, mais avec une interface proche de [[http://en.cppreference.com/w/cpp/container/vector|std::vector]]. En particulier, la fonction size pour connaitre la taille du tableau ou les fonctions [[http://en.cppreference.com/w/cpp/container/array/begin|begin]] et [[http://en.cppreference.com/w/cpp/container/array/end|end]] pour manipuler des itérateurs : | Ce type de tableau a été introduit dans le C++11 pour fournir des tableaux statiques similaires aux tableaux statiques style C, mais avec une interface proche de [[http://en.cppreference.com/w/cpp/container/vector|std::vector]]. En particulier, la fonction size pour connaitre la taille du tableau ou les fonctions [[http://en.cppreference.com/w/cpp/container/array/begin|begin]] et [[http://en.cppreference.com/w/cpp/container/array/end|end]] pour manipuler des itérateurs : | ||
Ligne 37: | Ligne 38: | ||
<code cpp> | <code cpp> | ||
std::array<int, 4> a1 = {0, 1, 2, 3}; // tableau d'entier | std::array<int, 4> a1 = {0, 1, 2, 3}; // tableau d'entier | ||
- | std::find(begin(a1), end(t1), 2); // itérateurs | + | std::find(begin(a1), end(a1), 2); // itérateurs |
</code> | </code> | ||
- | ===== 3. Utiliser les tableaux dynamiques style C ===== | + | ==== 3. Utiliser les tableaux dynamiques style C ==== |
Ces tableaux sont l'un des problèmes majeurs du C++ old-school, que l'on retrouve dans beaucoup de tutoriels sur internet et dans les livres (même certains livres récents). On voit également beaucoup de débutants sur les forums utiliser ce type de syntaxe, sans maîtriser les problématiques que cela pose. La sanction est généralement simple : le programme plante, avec des messages d'erreurs qui n'indiquent pas correctement la source du problème (je parle souvent d'erreur cryptique. On est tous déjà eu ce type d'erreur, qui prend parfois des heures à déboguer, pour un petit oubli dans une ligne de code). | Ces tableaux sont l'un des problèmes majeurs du C++ old-school, que l'on retrouve dans beaucoup de tutoriels sur internet et dans les livres (même certains livres récents). On voit également beaucoup de débutants sur les forums utiliser ce type de syntaxe, sans maîtriser les problématiques que cela pose. La sanction est généralement simple : le programme plante, avec des messages d'erreurs qui n'indiquent pas correctement la source du problème (je parle souvent d'erreur cryptique. On est tous déjà eu ce type d'erreur, qui prend parfois des heures à déboguer, pour un petit oubli dans une ligne de code). | ||
Ligne 51: | Ligne 52: | ||
Ce code pose aussi souvent des problèmes de fuite mémoire (oublier d'appeler [[http://en.cppreference.com/w/cpp/memory/new/operator_delete|delete[]]] ou appelle de [[http://en.cppreference.com/w/cpp/memory/new/operator_delete|delete]]), les accès hors de limites du tableau et la taille du tableau ne sont pas gérés, l'utilisation des algorithmes de la bibliothèque standard est moins naturelle. | Ce code pose aussi souvent des problèmes de fuite mémoire (oublier d'appeler [[http://en.cppreference.com/w/cpp/memory/new/operator_delete|delete[]]] ou appelle de [[http://en.cppreference.com/w/cpp/memory/new/operator_delete|delete]]), les accès hors de limites du tableau et la taille du tableau ne sont pas gérés, l'utilisation des algorithmes de la bibliothèque standard est moins naturelle. | ||
- | ===== 4. Utiliser les tableaux dynamiques std::vector ===== | + | ==== 4. Utiliser les tableaux dynamiques std::vector ==== |
Ces tableaux ont été ajoutés dans le C++ depuis très longtemps. Lors de leur ajout, les différentes implémentations de [[http://en.cppreference.com/w/cpp/container/vector|std::vector]] n'étaient pas toujours performantes, ce qui a justifié à l'époque que beaucoup continuaient d'utiliser les tableaux dynamiques style C. De nos jours, cet argument n'est plus du tout valable, l'utilisation de [[http://en.cppreference.com/w/cpp/container/vector|std::vector]] devrait être le comportement par défaut des débutants et moins débutants. | Ces tableaux ont été ajoutés dans le C++ depuis très longtemps. Lors de leur ajout, les différentes implémentations de [[http://en.cppreference.com/w/cpp/container/vector|std::vector]] n'étaient pas toujours performantes, ce qui a justifié à l'époque que beaucoup continuaient d'utiliser les tableaux dynamiques style C. De nos jours, cet argument n'est plus du tout valable, l'utilisation de [[http://en.cppreference.com/w/cpp/container/vector|std::vector]] devrait être le comportement par défaut des débutants et moins débutants. | ||
Ligne 69: | Ligne 70: | ||
Cette classe présente tous les avantages des conteneurs de la bibliothèque standard : expressivité, sécurité du code (libération de la mémoire, vérification des accès hors limite), évolutivité du core. Remarque : pour les accès aléatoires dans un tableau, il est préférable d'utiliser par défaut la fonction [[http://en.cppreference.com/w/cpp/container/vector/at|at]], qui vérifie les accès en dehors des limites du tableau, au lieu de [[http://en.cppreference.com/w/cpp/container/vector/operator_at|l'opérateur []]], qui ne le fait pas (en pratique, certain compilateur vérifie les limites avec [[http://en.cppreference.com/w/cpp/container/vector/operator_at|l'opérateur []]], mais cela n'est pas garantie par la norme). | Cette classe présente tous les avantages des conteneurs de la bibliothèque standard : expressivité, sécurité du code (libération de la mémoire, vérification des accès hors limite), évolutivité du core. Remarque : pour les accès aléatoires dans un tableau, il est préférable d'utiliser par défaut la fonction [[http://en.cppreference.com/w/cpp/container/vector/at|at]], qui vérifie les accès en dehors des limites du tableau, au lieu de [[http://en.cppreference.com/w/cpp/container/vector/operator_at|l'opérateur []]], qui ne le fait pas (en pratique, certain compilateur vérifie les limites avec [[http://en.cppreference.com/w/cpp/container/vector/operator_at|l'opérateur []]], mais cela n'est pas garantie par la norme). | ||
- | ===== Pourquoi ne pas utiliser les syntaxes style C ? ===== | + | ==== Pourquoi ne pas utiliser les syntaxes style C ? ==== |
Ceux qui utilisent les tableaux style C et qui recommandent leur utilisation essaient de transposer les pratiques du C (bonnes ou mauvaises, je ne saurais juger, je ne suis pas assez expert en C) en C++. En faisant cela, ils font une erreur fondamentale : ils pensent que le C++, c'est une évolution du C. Ce qui est vrai historiquement, mais faux en termes de syntaxe : le C et le C++ sont bien deux langages différents, avec leurs problématiques et modes de conceptions différents. Et un code parfaitement valable en C peut être très problématique en C++. | Ceux qui utilisent les tableaux style C et qui recommandent leur utilisation essaient de transposer les pratiques du C (bonnes ou mauvaises, je ne saurais juger, je ne suis pas assez expert en C) en C++. En faisant cela, ils font une erreur fondamentale : ils pensent que le C++, c'est une évolution du C. Ce qui est vrai historiquement, mais faux en termes de syntaxe : le C et le C++ sont bien deux langages différents, avec leurs problématiques et modes de conceptions différents. Et un code parfaitement valable en C peut être très problématique en C++. | ||
Ligne 103: | Ligne 104: | ||
Ce sont ces problèmes qui justifient la règle suivante : en C++ moderne, il faut bannir l'utilisation des pointeurs nus, de [[http://en.cppreference.com/w/cpp/language/new|new]] et de [[http://en.cppreference.com/w/cpp/memory/new/operator_delete|delete]]. (Comme toutes les règles, celle-ci peut être enfreint, mais uniquement lorsque l'on connait les risques et limites de ces syntaxes et que l'on a une très bonne raison de le faire). | Ce sont ces problèmes qui justifient la règle suivante : en C++ moderne, il faut bannir l'utilisation des pointeurs nus, de [[http://en.cppreference.com/w/cpp/language/new|new]] et de [[http://en.cppreference.com/w/cpp/memory/new/operator_delete|delete]]. (Comme toutes les règles, celle-ci peut être enfreint, mais uniquement lorsque l'on connait les risques et limites de ces syntaxes et que l'on a une très bonne raison de le faire). | ||
- | ===== Utiliser les tableaux de taille fixée à l’exécution (runtime-sized arrays) ===== | + | ==== Utiliser les tableaux de taille fixée à l’exécution (runtime-sized arrays) ==== |
Il reste un dernier cas d'utilisation que je n'ai pas évoqué. Lorsque l'on souhaite avoir un tableau de taille constante, mais non connue à la compilation, on peut utiliser ce type de syntaxe avec les tableaux statiques style C : | Il reste un dernier cas d'utilisation que je n'ai pas évoqué. Lorsque l'on souhaite avoir un tableau de taille constante, mais non connue à la compilation, on peut utiliser ce type de syntaxe avec les tableaux statiques style C : | ||
Ligne 162: | Ligne 163: | ||
</code> | </code> | ||
- | Un point important à noter lors de l'utilisation de ce type de tableau. Ces tableaux sont alloués sur la pile, qui a une taille limitée (différente selon le système et les options de compilation). Lorsque l'on souhaite créer des tableaux de taille importante, il faut utiliser des tableaux dynamiques std::vector. Lors de la création d'un tableau de taille fixée à l’exécution, si l'allocation échoue à cause d'un manque de mémoire disponible, le comportement est indéterminé (undefined behavior). En pratique, cela signifie que le comportement est laissé à l'appréciation des concepteurs de compilateurs (et donc potentiellement non reproductible selon le compilateur), bien qu'il est encouragé à lancer une exception de type std::bad_array_length (nouveau type d'exception également ajoutée dans ce TS). La seule garantie est que la mémoire sera libérée correctement (local object with automatic storage duration). Remarque : pour le constructeur des conteneurs avec un initializer-list, il est possible de ne pas mettre le signe égal. Il faut faire attention dans ce cas à ne pas confondre les deux syntaxes, avec parenthèses et avec crochets, qui sont visuellement proches, mais ont des comportements totalement différents : | + | Lors de la création d'un tableau de taille fixée à l’exécution, si l'allocation échoue à cause d'un manque de mémoire disponible, le comportement est indéterminé (undefined behavior). En pratique, cela signifie que le comportement est laissé à l'appréciation des concepteurs de compilateurs (et donc potentiellement non reproductible selon le compilateur), bien qu'il est encouragé à lancer une exception de type std::bad_array_length (nouveau type d'exception également ajoutée dans ce TS). La seule garantie est que la mémoire sera libérée correctement (local object with automatic storage duration). Remarque : pour le constructeur des conteneurs avec un initializer-list, il est possible de ne pas mettre le signe égal. Il faut faire attention dans ce cas à ne pas confondre les deux syntaxes, avec parenthèses et avec crochets, qui sont visuellement proches, mais ont des comportements totalement différents : |
<code cpp> | <code cpp> | ||
Ligne 169: | Ligne 170: | ||
</code> | </code> | ||
- | ====== La fonction make_array ====== | + | ===== La fonction make_array ===== |
N3824 est le seul draft du Working Group - Library Evolution pour le meeting de février (les autres travaux de ce WG sont déjà acceptés dans un TS ou dans le C++14). Il propose d'ajouter une fonction make_array, similaire aux fonctions make existantes (make_pair, make_tuple, make_shared et make_unique) pour créer un tableau statique (std::array). Les deux syntaxes suivantes seront donc possibles : | N3824 est le seul draft du Working Group - Library Evolution pour le meeting de février (les autres travaux de ce WG sont déjà acceptés dans un TS ou dans le C++14). Il propose d'ajouter une fonction make_array, similaire aux fonctions make existantes (make_pair, make_tuple, make_shared et make_unique) pour créer un tableau statique (std::array). Les deux syntaxes suivantes seront donc possibles : | ||
Ligne 252: | Ligne 253: | ||
</code> | </code> | ||
- | ====== Utiliser shared_ptr et make_shared avec des tableaux ====== | + | ===== Utiliser shared_ptr et make_shared avec des tableaux ===== |
Les pointeurs intelligents permettent de prendre en charge la destruction automatique des objets dont ils ont la responsabilité. C'est un ajout majeur du C++11, puisqu'il permet de garantir l'exception-safe des pointeurs, contrairement aux pointeurs nus (c'est la même problématique que l'utilisation des tableaux style C présentée au-dessus) : | Les pointeurs intelligents permettent de prendre en charge la destruction automatique des objets dont ils ont la responsabilité. C'est un ajout majeur du C++11, puisqu'il permet de garantir l'exception-safe des pointeurs, contrairement aux pointeurs nus (c'est la même problématique que l'utilisation des tableaux style C présentée au-dessus) : | ||
Ligne 291: | Ligne 292: | ||
</code> | </code> | ||
- | ====== Les tableaux multidimensionnels ====== | + | ===== Les tableaux multidimensionnels ===== |
+ | |||
+ | **EDIT Mai 2018 : les propositions pour les vues sur les tableaux ont été largement modifiées depuis la publication de cet article. Vous pouvez consulter les propositions suivantes :** | ||
+ | |||
+ | * [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0009r5.html|P0009r5 : Polymorphic Multidimensional Array Reference]] | ||
+ | * [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0122r6.pdf|P0122r6 : span: bounds-safe views for sequences of objects]] | ||
+ | |||
La manipulation de tableaux multidimensionnels est un problème classique en C++. Il est possible d'utiliser des solutions génériques, comme Boost.MultiArray, ou domaine spécifique, comme les outils de manipulation des images (Boost.GIL), la géométrie (Boost.Geometry) ou des matrices (Boost.uBLAS). Le draft N3851 propose d'ajouter ce type de tableau dans le C++. La création de tableaux à plusieurs dimensions pose un certain nombre de problématique sur : | La manipulation de tableaux multidimensionnels est un problème classique en C++. Il est possible d'utiliser des solutions génériques, comme Boost.MultiArray, ou domaine spécifique, comme les outils de manipulation des images (Boost.GIL), la géométrie (Boost.Geometry) ou des matrices (Boost.uBLAS). Le draft N3851 propose d'ajouter ce type de tableau dans le C++. La création de tableaux à plusieurs dimensions pose un certain nombre de problématique sur : | ||
Ligne 307: | Ligne 315: | ||
Les différentes classes permettront de gérer les limites (std::bounds), les index (std::index), les vues (std::array_view et std::strided_array_view) et la linéarisation (std::bounds_iterator). | Les différentes classes permettront de gérer les limites (std::bounds), les index (std::index), les vues (std::array_view et std::strided_array_view) et la linéarisation (std::bounds_iterator). | ||
- | ===== La gestion des limites (std::bounds) ===== | + | ==== La gestion des limites (std::bounds) ==== |
La classe std::bounds permet représenter les limites d'un tableau sous forme carrée (c'est-à-dire que chaque ligne possède le même nombre d'éléments, chaque colonne possède également le même nombre d'éléments, etc. Ce que ne garantit pas par exemple vector<vector<T>>). La définition de cette classe est la suivante (avec Rank le nombre de dimensions) : | La classe std::bounds permet représenter les limites d'un tableau sous forme carrée (c'est-à-dire que chaque ligne possède le même nombre d'éléments, chaque colonne possède également le même nombre d'éléments, etc. Ce que ne garantit pas par exemple vector<vector<T>>). La définition de cette classe est la suivante (avec Rank le nombre de dimensions) : | ||
Ligne 318: | Ligne 326: | ||
<code cpp> | <code cpp> | ||
- | bounds b1(5); // tableau 1D avec 5 éléments | + | bounds<1> b1(5); // tableau 1D avec 5 éléments |
- | bounds b2({4, 5, 6}); // tableau 3D, avec 4 éléments dans | + | bounds<3> b2({4, 5, 6}); // tableau 3D, avec 4 éléments dans |
// la première dimension, 5 éléments dans la seconde et | // la première dimension, 5 éléments dans la seconde et | ||
// 6 éléments dans la dernière | // 6 éléments dans la dernière | ||
- | bounds<3> b3({4, 5, 6}); // dimensions explicite | ||
</code> | </code> | ||
Ligne 334: | Ligne 341: | ||
<code cpp> | <code cpp> | ||
- | geomtery::get<geomtery::min_corner, 0>(array); | + | geometry::get<geometry::min_corner, 0>(array); |
</code> | </code> | ||
Ligne 367: | Ligne 374: | ||
* pour les itérateurs : begin(), end(). | * pour les itérateurs : begin(), end(). | ||
- | ===== La gestion des index (std::index) ===== | + | ==== La gestion des index (std::index) ==== |
La classe std::index permet de gérer un élément dans un tableau. Sémantiquement, cela correspond à un vecteur dans un espace à plusieurs dimensions par rapport à l'origine. Cette classe est proche de std::bounds et propose un certain nombre de fonctionnalités similaires : | La classe std::index permet de gérer un élément dans un tableau. Sémantiquement, cela correspond à un vecteur dans un espace à plusieurs dimensions par rapport à l'origine. Cette classe est proche de std::bounds et propose un certain nombre de fonctionnalités similaires : | ||
Ligne 374: | Ligne 381: | ||
* en complément, std::index ajoute les opérateurs d'incrémentation et décrémentation : +i, -i, ++i, --i. | * en complément, std::index ajoute les opérateurs d'incrémentation et décrémentation : +i, -i, ++i, --i. | ||
- | ===== La gestion des vues ===== | + | ==== La gestion des vues ==== |
Pour la gestion des vues, vous avez la possibilité d'utiliser deux classes : std::array_view et std::strided_array_view. | Pour la gestion des vues, vous avez la possibilité d'utiliser deux classes : std::array_view et std::strided_array_view. | ||
Ligne 429: | Ligne 436: | ||
</code> | </code> | ||
- | ===== Le slicing ===== | + | ==== Le slicing ==== |
Le slicing est une opération permettant d'obtenir un tableau de dimension (N-1) à partir d'un tableau de dimension N (voir l'image suivante), en fixant la première dimension (un tableau (x,y,z) donnera un tableau (y,z) par slicing). Cette opération est réalisée en utilisant l'opérateur [] avec un index de dimension 1. | Le slicing est une opération permettant d'obtenir un tableau de dimension (N-1) à partir d'un tableau de dimension N (voir l'image suivante), en fixant la première dimension (un tableau (x,y,z) donnera un tableau (y,z) par slicing). Cette opération est réalisée en utilisant l'opérateur [] avec un index de dimension 1. | ||
Ligne 447: | Ligne 454: | ||
</code> | </code> | ||
- | ===== Le sectionning ===== | + | ==== Le sectionning ==== |
Cette opération permet d'extraire un sous tableau de dimension N à partir d'un tableau de dimension N (voir image précédente), utilisant la fonction section et en précisant l'origine et les dimensions du nouveau tableau. Le nouveau tableau est de type strided_array_view, excepté si le tableau d'origine est un array_view et si le nouveau tableau ne redéfinit pas de nouvelles limites. | Cette opération permet d'extraire un sous tableau de dimension N à partir d'un tableau de dimension N (voir image précédente), utilisant la fonction section et en précisant l'origine et les dimensions du nouveau tableau. Le nouveau tableau est de type strided_array_view, excepté si le tableau d'origine est un array_view et si le nouveau tableau ne redéfinit pas de nouvelles limites. | ||
Ligne 456: | Ligne 463: | ||
</code> | </code> | ||
- | ===== Linéarisation avec bounds_iterator ===== | + | ==== Linéarisation avec bounds_iterator ==== |
Pour terminer, il est parfois nécessaire de linéariser un tableau, pour que l'ensemble de ses éléments soient vu comme une seule collection 1D (par exemple avec les algorithmes standards). La différence avec un itérateur obtenu avec v.begin() et v.end() est que les bounds_iterator respectent les limites et strides des tableaux. | Pour terminer, il est parfois nécessaire de linéariser un tableau, pour que l'ensemble de ses éléments soient vu comme une seule collection 1D (par exemple avec les algorithmes standards). La différence avec un itérateur obtenu avec v.begin() et v.end() est que les bounds_iterator respectent les limites et strides des tableaux. | ||
Ligne 482: | Ligne 489: | ||
</code> | </code> | ||
- | ====== Conclusion ====== | + | ===== Conclusion ===== |
Remarque importante : les fonctions présentées dans cet articles ne sont pas encore implémentées dans GCC, je n'ai pas testé les codes d'exemple donnés dans cet article. Certaines images et codes d'exemples proviennent directement des drafts du comité C++. | Remarque importante : les fonctions présentées dans cet articles ne sont pas encore implémentées dans GCC, je n'ai pas testé les codes d'exemple donnés dans cet article. Certaines images et codes d'exemples proviennent directement des drafts du comité C++. | ||
+ | |||
+ | ==== Mise à jour ==== | ||
+ | |||
+ | * Mise à jour du draft [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3976.html|N3976]] "Multidimensional bounds, index and array_view, revision 2", qui remplace N3851. | ||
+ | * Ajout d'un header <array_view>, qui contient les classes ''array_view'' et ''stride_array_view'' ; | ||
+ | * Ajout d'un header <coordinate>, qui contient les classes utilitaires permettant de gérer des coordonnées (index, bounds et bounds_iterator). | ||
+ | * Correction : suppression syntaxe du constructeur avec déduction de l'argument template (où j'ai pondu un truc pareil...) | ||
{{tag> C++ C++1y}} | {{tag> C++ C++1y}} |