C++11
# C++11

C++11, anciennement connu sous le nom de C++0x, est une norme pour le langage C++ en informatique. Elle a été approuvée unanimement le 12 août 2011. Elle remplace la précédente norme, ISO/CEI 14882, publiée en 1998 et mise à jour en 2003. Ces dernières sont plus connues sous les noms informels de C++98 et C++03. C++11 introduit plusieurs nouveautés au langage initial, ainsi que de nouvelles fonctionnalités à la bibliothèque standard du C++ comme la plupart des bibliothèques du Technical Report 1, à l'exception de la bibliothèque de fonctions mathématiques spéciales.

C++11 a été publié sous le nom de ISO/CEI 14882:2011 en septembre 2011. Une version payante est disponible sur le site de l'ISO. Le dernier working draft gratuit est le N3337, qui date du 12 janvier 2012, les seules différences avec le standard étant des corrections éditoriales.

Un langage de programmation comme le C++ suit une évolution qui permet aux programmeurs de coder plus rapidement, de façon plus élégante et permettant de faire du code maintenable. Ce processus soulève inévitablement des questions de compatibilité avec le code existant, ce qui s'est produit de temps en temps pendant le processus de développement du C++. Cependant, d'après l'annonce faite par Bjarne Stroustrup (l'inventeur du langage C++ et membre du comité), la nouvelle norme est presque totalement compatible avec la norme précédente.

## Changements prévus pour la mise à jour de la norme

Comme dit précédemment, les changements du langage C++ concernent aussi bien le langage initial que la bibliothèque standard.

Durant le développement de chaque fonctionnalité de la nouvelle norme, le comité a appliqué les directives suivantes :

* Garder la stabilité et la compatibilité avec le C++98 et, si possible, avec le C.
* Préférer l'introduction de nouvelles fonctionnalités par la bibliothèque standard, plutôt que par le langage lui-même.
* Préférer les changements qui peuvent faire évoluer les techniques de programmation.
* Améliorer le C++ pour faciliter la mise en place de systèmes et de bibliothèques, plutôt qu'introduire de nouvelles fonctionnalités seulement utiles pour des applications spécifiques.
* Augmenter la protection des types en fournissant des alternatives plus sécurisées que les actuelles, plutôt non sécurisées.
* Augmenter les performances et les capacités à travailler directement avec le matériel.
* Proposer des solutions propres aux problèmes actuels.
* Implémenter le principe du « zero-overhead » (on ne paye le coût d'une fonctionnalité que si l'on s'en sert).
* Rendre le C++ facile à apprendre et à enseigner sans enlever les fonctionnalités requises par les programmeurs experts.

## Extensions du langage

### Multitâche

La mémoire locale de thread ou Thread Local Storage n'est pas un concept inventé par la nouvelle norme : de nombreux compilateurs proposent déjà cette fonctionnalité, ainsi que la bibliothèque threads de Boost. C++11 introduit le mot-clef thread_local​ pour déclarer qu'une variable doit être stockée dans une zone mémoire appartenant au thread. Chaque thread embarque ainsi sa propre copie d'une variable déclarée de la sorte, et les modifications d'une de ces copies n'affectent pas les copies appartenant aux autres threads. Lorsqu'une variable statique (ou une variable de classe) est ainsi définie, sa durée de vie est alors réduite à celle du thread (le destructeur des objets, notamment, est appelé lorsque le thread s'achève).

### Les classes

**Délégation du constructeur**

En C++03, un constructeur appartenant à une classe ne peut pas appeler un autre constructeur de cette même classe, ce qui peut entraîner de la duplication de code lors de l'initialisation de ses attributs. En permettant au constructeur de déléguer la création d'une instance à un autre constructeur, C++11 apporte donc une solution.

Dans l'exemple ci-dessus, on peut voir que le second constructeur appelle le premier constructeur, ce qui aurait conduit à une erreur de compilation en C++03.

**Héritage du constructeur**

En C++03, les constructeurs d'une classe de base ne sont pas hérités par ses classes dérivées. C++11 permet d'hériter explicitement des constructeurs de la classe de base grâce à l'instruction using​

**Initialiseurs d'attributs**

En C++03, il est possible d'assigner une valeur par défaut aux variables constantes directement dans le fichier d'en-tête. C++11 étend cette possibilité aux attributs des classes. Par exemple il est désormais tout à fait possible d'écrire:

Dans ce code, tous les constructeurs de la classe vont initialiser m_valeur​ à 5, si le constructeur ne remplace pas l'initialisation avec la sienne.

Par exemple, le constructeur vide ci-dessus va initialiser m_valeur​ selon la définition de la classe, mais le constructeur qui prend un int​ en paramètre initialisera m_valeur​ à ce paramètre.

Il est également possible d'utiliser d'autres attributs dans l'initialisation, et d'utiliser un constructeur ou l'utilisation uniforme au lieu de l'initialisation par assignation.

**Sizeof sur les attributs de classes sans objet explicite**

En C++03, sizeof​ peut être utilisé sur des types ou des objets, mais pas sur un membre de classe (excepté dans la bibliothèque Qt). C++11 le rend possible. On peut donc maintenant faire :

Ce qui résultait en une erreur de compilation avant.

**Liste d'initialiseurs**

Pour initialiser un conteneur à l'aide de valeurs connues, il fallait le faire élément par élément. C++11 introduit le patron de classe std::initializer_list​ qui permet d'initialiser les conteneurs avec la même syntaxe que celle permettant en C d'initialiser les tableaux, donc à l'aide d'une suite de valeurs entre accolades.

### Les Templates

**Les templates $variadiques^,**$

Pour remplacer les fonctions variadiques du C (déconseillées en C++, car contournant toute vérification du type des paramètres), C++11 introduit les templates variadiques. Ces templates étendent le concept précédent en lui ajoutant la possibilité de prendre un nombre quelconque d'arguments. Elles sont supportées par le compilateur GCC depuis la version 4.3 car elles font partie de l'expérimentation du support de C++0x.

L'utilité de templates possédant un nombre quelconque d'arguments se perçoit aisément avec la classe tuple​, qui généralise le concept de paire (triplet, n-uplet, etc.) ou bien avec cet exemple d'implémentation de la fonction printf​ :

C++11 définit un certain nombre de concepts que nous pouvons approcher grâce au code source suivant :

* À la première déclaration, l'argument template class ... T​ est appelé un pack de paramètres template car il regroupe un nombre fini d'arguments (déterminé à la compilation).
* À la seconde déclaration, T ... args​ s'appelle un pack de paramètres de fonction. C'est un paramètre de fonction qui englobe un paramètre pour chaque argument contenu par le pack de paramètres template class ... T​.
* Enfin, la troisième déclaration nous apprend comment utiliser un pack étendu de paramètres. Le mot extension est utilisé car lors de l'appel à g, le pack de paramètres sera étendu avant d'être passé à g.

**Les concepts**

Les concepts ont été retirés de la norme.

**Les chevrons (<>​)**

Les compilateurs C++ actuels traitent toujours une séquence de deux signes supérieur à comme un opérateur de décalage binaire vers la droite. En conséquence, lors de l'imbrication de l'utilisation de patrons, les programmeurs sont obligés d'insérer un espace entre les deux chevrons fermants.

Par exemple, en C++03, ce code provoque une erreur de compilation :

C++11 tentera de détecter automatiquement si les symboles doivent jouer le rôle de chevrons fermants ou d'opérateur de décalage binaire.

**Template externe**

Les templates ne sont actuellement pas pris en compte par l'éditeur de liens : il est nécessaire d'incorporer leur définition dans tous les fichiers sources les utilisant en programmation modulaire. Leur compilation était donc longue et gourmande puisque la classe était recompilée dans chaque fichier source, pour chaque type utilisé.

C++11 permettra l'utilisation du mot-clé extern​ pour rendre les templates globaux. Les fichiers désirant utiliser le template n'ont qu'à le déclarer.

### Autres nouvelles fonctionnalités du C++11

**Assertions statiques**

La bibliothèque Boost propose déjà cette facilité à travers la macro BOOST_STATIC_ASSERT​. Cependant, son implémentation est étrange, basée sur la métaprogrammation et des comparaisons de taille de structures intermédiaires créées pour l'assertion sans trop de rapport avec le concept. Par conséquent, intégrer la fonction dans le langage apporte une solution propre au problème.

En pratique, une assertion statique permet de vérifier à la compilation qu'une valeur est vraie. Par exemple, il est possible d'implémenter les concepts en utilisant boost::traits​ et BOOST_STATIC_ASSERT​. Si une classe template nécessite que son type template soit un POD (Plain Old Data), elle peut faire une assertion statique sur boost::is_pod<T>::type::value​, ce qui est une constante intégrale de type unspecified-bool-type​ et remplit dont le critère pour paraître dans une assertion statique.

En outre, en C++11, l'expression :

permettrait à une bibliothèque d'être certaine qu'elle est compilée sur un système vérifiant cette condition (x86-64 par exemple).

**Inférence de types**

Le mot clé auto​ se voit assigner une nouvelle sémantique par le nouveau standard. Nous connaissions son unique sémantique d'indicateur de classe de stockage pour une variable. En effet, déclarer une variable automatique revenait à indiquer au compilateur qu'elle était valide seulement dans l'espace où elle était déclarée ; ce comportement étant aussi celui par défaut, le mot clé était inutile. Dans le nouveau standard, il change de sémantique et prend la place du type dans la déclaration. Le type sera alors automatiquement décidé par correspondance avec le type retourné par l'objet utilisé pour l'initialisation de la variable. Les variables étant déclarées avec auto​ devront donc impérativement être initialisées. Exemple :

Le type de f​ est un type interne de la bibliothèque surchargé environ quatre-vingts fois avec un script Perl. Trouver le type exact pour stocker le résultat d'un bind​ dans un objet n'était pas pratique du tout avant le nouveau rôle du mot clé auto​, d'où son apparition.

D'une manière générale, l'utilisation du mot clé auto​ permet de passer moins de temps à écrire ce que le compilateur sait déjà.

Le nouveau standard ajoute le mot clé decltype​ qui permet de typer une variable à partir du type d'une autre variable. Exemple:

Le type de j​ sera du même type que i​, soit int​. Cette déclaration automatique du type d'une variable peut être très utile dans les templates.

**Expressions et fonctions $lambda^,^,**$

Une fonction lambda construit une fermeture; c.-à-d. un objet fonction anonyme capable de capturer des variables dans la portée, de prendre des paramètres en entrée et de retourner un résultat. La syntaxe générale et complète est :

. En particulier :

* si aucune variable n'est à capturer, on écrira​;
* si aucun paramètre n'est à passer, on écrira​;
* si aucun retour n'est effectué ou si le compilateur peut déterminer le type de retour, on n'écrira pas la partie -> ret;
* enfin, les parties mutable​, exception​ et attribute​ sont optionnelles.

Exemple qui réalise l'extraction d'un nom de fichier à l'image de la commande basename​ :

**Sémantique des RValues Reference/Move**

L'introduction de la sémantique move (déplacement) prend son sens en constatant qu'en C++, il n'y a aucune manière générique de déplacer un objet sans le copier. Par exemple lorsqu'une fonction retourne un objet de grosse taille, celui-ci est copié dans une zone temporaire avant d'être à nouveau copié là où le résultat de la fonction est affecté. Après chaque étape de copie l'objet copié devient inutile et est détruit. Cela est très peu efficace car il serait beaucoup plus rapide de déplacer l'objet plutôt que de le recopier et détruire l'original. C'est particulièrement vrai si l'objet est d'un type proche du type T​ ci-dessous, où LargeDataT​ est un type d'objet coûteux à dupliquer :

En effet le déplacement d'un objet de ce type T​ requiert simplement la recopie du membre ptr​ alors que sa duplication alloue et copie un nouvel objet LargeDataT​. Le problème que résout C++11 par l'ajout des RValues reference est de pouvoir appeler la fonction MoveFrom​ en lieu et place du constructeur de recopie dans les cas où la copie correspond à un déplacement. Ceci s'obtient par l'ajout du constructeur de déplacement ci-dessous :

Le double & marque la référence sur rvalue (parfois aussi appelée temporaire). C'est-à-dire une référence sur quelque chose qui est temporaire ou est sur le point d'être détruit. Le constructeur de déplacement sera donc choisi par le compilateur à la place du constructeur de recopie en cas de copie d'un objet temporaire ou sur le point d'être supprimé. Sur tous les autres aspects une référence sur une rvalue est identique à une référence classique maintenant appelée référence sur lvalue (que l'on peut définir grossièrement par : tout ce qui a une adresse). De cette définition ressort un fait qui peut sembler paradoxal : une variable de type référence sur une rvalue n'est généralement pas une référence sur une rvalue ! En effet à partir du moment où une référence sur une rvalue est écrite dans une variable, y compris si elle est de type référence sur rvalue, elle perd son caractère temporaire dans l'espace de définition de cette variable.

Mais parfois il est utile d'appeler le constructeur de déplacement même à partir d'une variable qui n'est pas temporaire. Par exemple la commande swap​ est souvent introduite par le patron de fonction ci-dessous :

Cette fonction a pour inconvénient d'appeler d'abord le constructeur de recopie, puis deux opérateurs d'assignation. Ce sont donc 3 copies au total, qui peuvent être des opérations extrêmement coûteuses, voire impossibles si les objets impliqués sont de taille importante. Ici le constructeur de déplacement n'est pas appelé car a, b et c comme source de la copie ne sont pas temporaires. C++11 introduit la fonction std::move​ qui retourne une référence à une rvalue et prend pour paramètre une référence à une lvalue ou à une rvalue. Son patron est le suivant :

La fonction move​ donne à ce qu'il retourne la valeur de son paramètre. La fonction move ne modifie pas l'objet qui lui est passé mais reçoit et fournit une référence sur un objet non constant. L'objet d'origine peut donc être modifié à partir du résultat de la fonction move​. Le point important de move est qu'il n'y a aucune copie de faite. En utilisant move, on peut ainsi réécrire de façon concise swap​, sans qu'il n'y ait de copie.

Un autre intérêt de move​ est de permettre d'obtenir une copie d'un objet volumineux sans qu'il y ait de copie réelle de celui-ci, en particulier de la partie volumineuse.

De plus, move​ est impératif dans le cas d'un objet non copiable comme le “smart pointer” unique_ptr​.

**Énumérations fortement typées**

L'énumération du langage C était similaire à une liste de définitions de symboles (macros) correspondant à des nombres entiers, et C++ n'avait répondu qu'en interdisant la conversion d'un type énumération dans un autre.

C++11 proposera des énumérations « fortement typées ». Ces énumérations seront obtenues en remplaçant enum​ par enum class​ ou enum struct​. La conversion implicite d'éléments de ces énumérations vers les entiers sera prohibée et l'accès aux éléments se fera à l'aide de l'opérateur de résolution de portée. Voici un exemple d'utilisation :

L'opérateur de résolution de portée sera optionnel avec des énumérations faiblement typées :

De plus, C++11 vous permettra de choisir le type d'entier sous-jacent des énumérations (tous sauf wchar_t​):

Par défaut, ce type sera int​. Ce comportement sera aussi possible avec les énumérations normalement typées, et il sera bien sûr toujours possible de définir la valeur d'une partie de l'énumération :

**Boucles basées sur des intervalles**

Le code nécessaire en C++ pour le parcours d'un intervalle et l'action sur ses éléments est répétitif et long. De nombreux langages, comme Java, ont fourni à leurs utilisateurs un opérateur foreach​ qui permet de parcourir une liste avec aisance. Pour répondre aux attentes, la norme C++11 fournira une nouvelle syntaxe de l'instruction for​ qui s'implémentera de cette façon :

Ce code permet de doubler tous les éléments du tableau mon_tableau​. L'entier x​ défini pour le corps de la boucle for​ référence successivement chacun des éléments du tableau.

Ce type de parcours fonctionnera pour les listes classiques, les listes d'initialiseurs, ainsi que les conteneurs de la STL définissant les fonctions membres begin​ et end​ comme dans l'exemple suivant :

**Littéraux définis par l'utilisateur**

Les littéraux définis par l'utilisateur permettent d'ajouter de nouveaux suffixes, au même titre que UL​, ULL​, L​... Les suffixes créés ainsi doivent commencer par un tiret bas (_​) afin de ne pas entrer en conflit avec les futurs littéraux introduits dans la librairie standard.

Exemple :

**Pointeur NULL​**

Le nouveau mot-clé nullptr​ a été proposé comme constante du langage avec le caractère particulier d'être assignable à tous les types de pointeurs. En effet, contrairement au C où la macro préprocesseur est généralement définie avec #define NULL ((void*)0)​, en C++ il est interdit d'assigner un void*​ à un pointeur d'un type différent. L'usage était donc de définir NULL​ avec l'entier 0​. Ce comportement restera compatible, mais il sera aussi possible d'écrire :

La constante NULL​ définie comme l'entier 0​ ne permettait pas au compilateur de déterminer quelle surcharge de f​ choisir dans le code suivant:

Le mot clé nullptr​ est une constante du type nullptr_t​, non convertible en entier. Pour appeler la fonction f​ avec un pointeur NULL​, la surcharge est correctement choisie en C++11 dans le code suivant:

## Extension de la bibliothèque standard

### Threads

La bibliothèque standard a implémenté dans la nouvelle norme du C++, le modèle de classe std::thread​, celui-ci n'est qu'une implémentation des threads de la bibliothèque Boost.

Voici, un exemple résumant quelque peu son utilisation:

### Type tuple

Un tuple est une collection de dimension fixe d'objets de types différents. Tout type d'objet peut être élément d'un tuple. Cette nouvelle fonctionnalité est implémentée dans un nouvel en-tête et bénéficie des extensions de C++11 comme :

* Les templates variadiques
* Référence sur référence
* Arguments par défaut pour les fonctions template

Le patron de classe tuple​ est déclaré par la ligne :

Un exemple de définition et d'utilisation du type tuple​ :

Il est possible de créer le tuple proof​ sans définir son contenu si les éléments du tuple possèdent un constructeur par défaut. De plus, il est possible d'assigner un tuple à un autre tuple : si les deux tuples sont de même type, il est nécessaire que chaque élément du tuple ait un constructeur par copie, sinon il faut que le type de chaque élément de l'opérande de droite soit compatible avec le type correspondant dans l'opérande de gauche ou que l'élément correspondant de l'opérande gauche ait un constructeur approprié.

Les opérateurs relationnels sont disponibles (pour les tuples ayant le même nombre d'éléments). Deux expressions sont introduites pour vérifier les caractéristiques d'un tuple (à la compilation) :

* tuple_size<T>::value<​ retourne le nombre d'éléments du tuple T​,
* tuple_element<I, T>::type​ retourne le type de l'objet placé en position I​ du tuple T​.

### Table de hachage

Intégrer les tables de hachage (conteneurs associatifs non ordonnés) dans la bibliothèque standard du C++ est l'une des demandes les plus récurrentes. Cela n'avait pas été réalisé pour la norme actuelle (celle écrite en 1995 et approuvée en 1998) à cause des contraintes de temps. Bien que cette solution soit moins efficace que les arbres équilibrés dans le pire des cas (en cas de collisions importantes), elle est cependant la meilleure dans la plupart des applications réelles.

Les collisions seront uniquement gérées par chaînage linéaire car le comité ne considère pas opportun de standardiser des solutions d'adressage ouvert qui introduisent un nombre important de problèmes intrinsèques (en particulier quand la suppression d'éléments est permise). Pour éviter les conflits de noms avec les bibliothèques non standards qui ont leur propre implémentation des tables de hachage, on utilisera le préfixe unordered​, au lieu de hash​.

Cette nouvelle fonctionnalité intégrera quatre types de tables de hachage, différentes selon qu'elles acceptent ou non des éléments de même clé (clé unique ou clé équivalente) et qu'elles associent chaque clé à la valeur associée.

| Type de table de hachage | Type associé arbitraire | Clés équivalentes |
| - | - | - |
| unordered_set | | |
| unordered_multiset | | • |
| unordered_map | • | |
| unordered_multimap | • | • |

Ces nouvelles classes remplissent toutes les demandes des classes de conteneurs et contiennent toutes les méthodes nécessaires pour accéder aux éléments : insert​, erase​, begin​, end​.

Ces classes n'ont pas nécessité les nouvelles extensions du langage C++ mais seulement une légère extension du header <functional>​ et l'introduction des headers <unordered_set>​ et <unordered_map>​. Aucun autre changement aux classes de la norme actuelle n'est nécessaire et elles ne dépendent d'aucune autre extension de la bibliothèque standard.

### Expressions rationnelles

La bibliothèque définie dans le fichier d'en-tête <regex>​ est fait d'un ensemble de nouvelles classes :

* Les expressions rationnelles sont représentées par une instance de la classe template std::regex​
* Les résultats sont représentés par une instance de la classe template std::match_results​

La fonction std::regex_search​ est utilisée pour une recherche. std::regex_replace​ est utilisée pour effectuer un "chercher-remplacer", elle renvoie pour cela une nouvelle chaîne.

Les algorithmes std::regex_search​ et std::regex_replace​ prennent une expression rationnelle et une chaîne et écrivent les occurrences trouvées dans la structure std::match_results​.

Voici, un exemple d'utilisation de std::match_results​ :

Notez l'utilisation du double backslash, car le C++ utilise le backslash comme un caractère d'échappement. Les chaînes littérales en C++11 peuvent permettre d'éviter le problème.

L'utilisation de la bibliothèque <regex>​ ne requiert aucune dépendance explicite.

### Amélioration des nombres aléatoires extensibles

La bibliothèque standard du C permet de générer des nombres pseudo-aléatoires grâce à la fonction rand​. L'algorithme de génération n'est pas standardisé mais laissé au choix du fournisseur de la bibliothèque. Le C++ n'y a rien changé, mais C++11 va fournir une manière différente de générer les nombres pseudo-aléatoires.

Cette fonctionnalité est découpée en deux parties qui forment un objet de génération de nombres aléatoires :

* un moteur de génération, qui contient l'état du générateur et produit les nombres pseudo-aléatoires ;
* une distribution, qui détermine les valeurs que le résultat peut prendre ainsi que sa loi de probabilité.

C++11 définit trois algorithmes de génération, chacun ayant des avantages et des inconvénients.

| Template | Entier/flottant | Qualité | Vitesse | Taille d'état |
| - | - | - | - | - |
| linear_congruential​ | Entier | Moyenne | Moyenne | 1 |
| subtract with carry​ | Les deux | Moyenne | Rapide | 25 |
| mersenne_twister​ | Entier | Bonne | Rapide | 624 |

C++11 fournira un certain nombre de lois standard : uniform_int_distribution​, bernoulli_distribution​, geometric_distribution​, poisson_distribution​, binomial_distribution​, uniform_real_distribution​, exponential_distribution​, normal_distribution​ et gamma_distribution​.

Le générateur et la distribution se combinent comme dans l'exemple suivant :

### Fonctions mathématiques spéciales

Le fichier header <math> définit déjà plusieurs fonctions mathématiques usuelles :

* trigonométriques : sin​, cos​, tan​, asin​, acos​, atan​, atan2​;
* hyperboliques : sinh​, cosh​, tanh​, asinh​, acosh​, atanh​;
* exponentielles : exp​, exp2​, frexp​, ldexp​, expm1​;
* logarithmiques : log10​, log2​, logb​, ilogb​, log1p​;
* puissances : pow​, sqrt​, cbrt​, hypot​;
* spéciales : erf​, erfc​, tgamma​, lgamma​.

Le comité a décidé d'ajouter de nouvelles fonctions qui nécessitent actuellement l'utilisation de bibliothèques non-standards. Ces nouvelles fonctions auront un intérêt principalement pour les programmeurs de disciplines scientifiques et pour l'ingénierie.

Le tableau suivant montre les 23 fonctions décrites dans TR1.

| Nom de la fonction | Prototype de la fonction | Expression mathématique |
| - | - | - |
| Polynômes de Laguerre généralisés | double assoc_laguerre(unsigned n, unsigned m, double x);​ | ${L_{n}}^{m}(x)=(-1)^{m}{\frac {d^{m}}{dx^{m}}}L_{n+m}(x),{\text{ pour }}x\geq 0$ |
| Polynômes de Legendre généralisés | double assoc_legendre(unsigned l, unsigned m, double x);​ | ${P_{l}}^{m}(x)=(1-x^{2})^{m/2}{\frac {d^{m}}{dx^{m}}}P_{l}(x),{\text{ pour }}x\geq 0$ |
| Fonction bêta | double beta(double x, double y);​ | $B(x,y)={\frac {\Gamma (x)\Gamma (y)}{\Gamma (x+y)}}$ |
| Intégrale elliptique complète de premier genre | double comp_ellint_1(double k);​ | $K(k)=F\left(k,\textstyle {\frac {\pi }{2}}\right)=\int _{0}^{\frac {\pi }{2}}{\frac {d\theta }{\sqrt {1-k^{2}\sin ^{2}\theta }}}$ |
| Intégrale elliptique complète de deuxième genre | double comp_ellint_2(double k);​ | $E\left(k,\textstyle {\frac {\pi }{2}}\right)=\int _{0}^{\frac {\pi }{2}}{\sqrt {1-k^{2}\sin ^{2}\theta }}\;d\theta$ |
| Intégrale elliptique complète de troisième genre | double comp_ellint_3(double k, double nu);​ | $\Pi \left(\nu ,k,\textstyle {\frac {\pi }{2}}\right)=\int _{0}^{\frac {\pi }{2}}{\frac {d\theta }{(1-\nu \sin ^{2}\theta ){\sqrt {1-k^{2}\sin ^{2}\theta }}}}$ |
| Fonctions hypergéométriques confluentes | double conf_hyperg(double a, double c, double x);​ | $F(a,c,x)={\frac {\Gamma (c)}{\Gamma (a)}}\sum _{n=0}^{\infty }{\frac {\Gamma (a+n)x^{n}}{\Gamma (c+n)n!}}$ |
| Fonctions de Bessel cylindriques modifiées régulières | double cyl_bessel_i(double nu, double x);​ | $I_{\nu }(x)=i^{-\nu }J_{\nu }(ix)=\sum _{k=0}^{\infty }{\frac {(x/2)^{\nu +2k}}{k!\;\Gamma (\nu +k+1)}},{\text{ pour }}x\geq 0$ |
| Fonctions de Bessel cylindriques du premier genre | double cyl_bessel_j(double nu, double x);​ | $J_{\nu }(x)=\sum _{k=0}^{\infty }{\frac {(-1)^{k}\;(x/2)^{\nu +2k}}{k!\;\Gamma (\nu +k+1)}},{\text{ pour }}x\geq 0$ |
| Fonctions de Bessel cylindriques modifiées irrégulières | double cyl_bessel_k(double nu, double x);​ | ${\begin{aligned}K_{\nu }(x)&=\textstyle {\frac {\pi }{2}}i^{\nu +1}{\bigJ_{\nu }(ix)+iN_{\nu }(ix){\big )}\\&={\begin{cases}\displaystyle {\frac {I_{-\nu }(x)-I_{\nu }(x)}{\sin \nu \pi }},&{\text{ pour }}x\geq 0{\text{ et }}\nu \notin \mathbb {Z} \\[10pt]\displaystyle {\frac {\pi }{2}}\lim _{\mu \to \nu }{\frac {I_{-\mu }(x)-I_{\mu }(x)}{\sin \mu \pi }},&{\text{ pour }}x<0{\text{ et }}\nu \in \mathbb {Z} \\\end{cases}}\end{aligned}}$ |
| Fonctions de Neumann cylindriques Fonctions de Bessel cylindriques du deuxième genre | double cyl_neumann(double nu, double x);​ | $N_{\nu }(x)={\begin{cases}\displaystyle {\frac {J_{\nu }(x)\cos \nu \pi -J_{-\nu }(x)}{\sin \nu \pi }},&{\text{ pour }}x\geq 0{\text{ et }}\nu \notin \mathbb {Z} \\[10pt]\displaystyle \lim _{\mu \to \nu }{\frac {J_{\mu }(x)\cos \mu \pi -J_{-\mu }(x)}{\sin \mu \pi }},&{\text{ pour }}x<0{\text{ et }}\nu \in \mathbb {Z} \\\end{cases}}$ |
| Intégrale elliptique incomplète du premier genre | double ellint_1(double k, double phi);​ | $F(k,\phi )=\int _{0}^{\phi }{\frac {d\theta }{\sqrt {1-k^{2}\sin ^{2}\theta }}},{\text{ pour }}\left|k\right|\leq 1$ |
| Intégrale elliptique incomplète du deuxième genre | double ellint_2(double k, double phi);​ | $\displaystyle E(k,\phi )=\int _{0}^{\phi }{\sqrt {1-k^{2}\sin ^{2}\theta }}d\theta ,{\text{ pour }}\left|k\right|\leq 1$ |
| Intégrale elliptique incomplète du troisième genre | double ellint_3(double k, double nu, double phi);​ | $\Pi (k,\nu ,\phi )=\int _{0}^{\phi }{\frac {d\theta }{\left(1-\nu \sin ^{2}\theta \right){\sqrt {1-k^{2}\sin ^{2}\theta }}}},{\text{ pour }}\left|k\right|\leq 1$ |
| Intégrale exponentielle | double expint(double x);​ | ${\mbox{E}}i(x)=-\int _{-x}^{\infty }{\frac {e^{-t}}{t}}\,dt$ |
| Polynômes d'Hermite | double hermite(unsigned n, double x);​ | $H_{n}(x)=(-1)^{n}e^{x^{2}}{\frac {d^{n}}{dx^{n}}}e^{-x^{2}}\,\!$ |
| Séries hypergéométriques | double hyperg(double a, double b, double c, double x);​ | $F(a,b,c,x)={\frac {\Gamma (c)}{\Gamma (a)\Gamma (b)}}\sum _{n=0}^{\infty }{\frac {\Gamma (a+n)\Gamma (b+n)}{\Gamma (c+n)}}{\frac {x^{n}}{n!}}$ |
| Polynômes de Laguerre | double laguerre(unsigned n, double x);​ | $L_{n}(x)={\frac {e^{x}}{n!}}{\frac {d^{n}}{dx^{n}}}\left(x^{n}e^{-x}\right),{\text{ pour }}x\geq 0$ |
| Polynômes de Legendre | double legendre(unsigned l, double x);​ | $P_{l}(x)={1 \over 2^{l}l!}{d^{l} \over dx^{l}}(x^{2}-1)^{l},{\text{ pour }}\left|x\right|\leq 1$ |
| Fonction zêta de Riemann | double riemann_zeta(double x);​ | $\mathrm {Z} (x)={\begin{cases}\displaystyle \sum _{k=1}^{\infty }k^{-x},&{\text{ pour }}x>1\\[10pt]\displaystyle 2^{x}\pi ^{x-1}\sin \left({\frac {x\pi }{2}}\right)\Gamma (1-x)\zeta (1-x),&{\text{ pour }}x<1\\\end{cases}}$ |
| Fonctions sphériques de Bessel du premier genre | double sph_bessel(unsigned n, double x);​ | $j_{n}(x)={\sqrt {\frac {\pi }{2x}}}J_{n+1/2}(x),{\text{ pour }}x\geq 0$ |
| Fonctions sphériques de Legendre généralisées | double sph_legendre(unsigned l, unsigned m, double theta);​ | $Y_{l}^{m}(\theta ,0){\text{ avec }}Y_{l}^{m}(\theta ,\phi )=(-1)^{m}\left[{\frac {(2l+1)}{4\pi }}{\frac {(l-m)!}{(l+m)!}}\right]^{1 \over 2}P_{l}^{m}(cos\theta )e^{im\phi }{\text{ pour }}|m|\leq l$ |
| Fonctions sphériques de Neumann Fonctions sphériques de Bessel du deuxième genre | double sph_neumann(unsigned n, double x);​ | $n_{n}(x)={\sqrt {\frac {\pi }{2x}}}N_{n+1/2}(x){\text{ pour }}x\geq 0$ |

Chacune de ces fonctions possède deux variantes supplémentaires. En rajoutant le suffixe f​ ou l​ au nom de la fonction, on obtient les mêmes fonctions agissant sur des float​ ou des long double​ respectivement. Par exemple :

