Greboca  

Suport technique et veille technologique

Aujourd’hui, les grandes entreprises et administrations publiques hésitent entre continuer à utiliser des logiciels propriétaires ou basculer vers les Logiciels Libres. Pourtant, la plupart des logiciels libres sont capables de bien traiter les données issues des logiciels propriétaire, et parfois avec une meilleur compatibilité.

C’est alors la barrière de la prise en main qui fait peur, et pourtant...

Les logiciels libres

L’aspect « Logiciel Libre » permet une évolution rapide et une plus grande participation des utilisateurs. Les aides et tutoriels foisonnent sur Internet ou sont directement inclus dans le logiciel lui-même.

Enfin, les concepteurs sont plus proches des utilisateurs, ce qui rend les logiciels libres plus agréable à utiliser et conviviaux.

Grâce à la disponibilité des logiciels libres, vous trouverez facilement des services de support techniques et la licence n’est plus un frein à l’utilisation de ces logiciels par votre personnel.

Notre support technique concerne essentiellement les logiciels libres, que ce soit sous forme de services ponctuels ou de tutoriels.

DLFP - Dépêches  -  Le standard C++0x a enfin été voté

 -  Août 2011 - 

Le nouveau standard du langage C++ a été voté ce vendredi 12 août. Initialement prévu pour 2008 ou 2009, il a pris du retard, notamment à cause de problèmes avec certaines fonctionnalités. Malgré cette date, beaucoup l'appellent quand même C++0x et il suffit de le nommer C++0xB pour que le nom soit conservé. La publication officielle ne devrait cependant pas arriver avant quelques mois.

Heureusement pour les utilisateurs, ces fonctionnalités ont déjà commencé à être implémentées dans les différents compilateurs et bibliothèques standard. Ceci devrait permettre de ne pas attendre trop longtemps avant de pouvoir profiter de ces nouveautés, voire d'en profiter dès à présent pour certaines. Par exemple, sous GCC, il faut passer l'option -std=c++0x au compilateur pour utiliser des évolutions qui sont déjà implémentées.

Une sélection des principales nouveautés est présentée en seconde partie de dépêche.

Merci à moules< pour son aide lors de la rédaction de cette dépêche.

Sommaire

Les évolutions du langage

La délégation de constructeur

Il est désormais possible d'appeler un constructeur dans un autre (du même objet), cela permet d'écrire plus facilement des contructeurs par défaut. Par exemple, le code suivant :

class MyClass {
    private:
        constructor(int num);

    public:
        MyClass(int num) {constructor(num);};
        MyClass() {constructor(42);};
}

pourra être remplacé par :

class MyClass {
    public:
        MyClass(int num);
        MyClass() {MyClass(42)};
}

L'inférence de type

L'inférence de types est un mécanisme qui permet à un compilateur ou un interpréteur de rechercher automatiquement les types associés à des expressions, sans qu'ils soient indiqués explicitement dans le code source. Elle est disponible via deux moyen. D'abord avec le mot-clef auto quand on déclare une variable, cette dernière prendra le type de son assignation. Cela donne :

auto maVariable = 5;

Et la variable aura le type int. Bien sûr, ce n'est pas à utiliser dans n'importe quel cas et l'utilisation la plus courante sera sans doute lors du parcours d'une liste dans une boucle :

for (std::vector<int>::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr)

sera remplacé par :

for (auto itr = myvec.cbegin(); itr != myvec.cend(); ++itr)

Une autre utilisation de l'inférence de type se fait avec le mot-clef en:decltype. Cela permet de typer une variable non pas avec le type de l'assignation mais avec celui d'une autre variable :

char a;
decltype(a) b=5;

Dans ce cas, b sera du type char. L'utilisation devient intéressante lorsqu'on utilise une variable avec auto ou lors de l'utilisation importante de la surcharge d'opérateur et des types spécialisés.

Le foreach

Il est désormais possible de parcourir une liste d'élément assez simplement :

int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
    x *= 2;
}

Cette forme est utilisable avec les tableaux de style C et tous les objets qui possèdent les méthodes begin() et end() renvoyant un itérateur.

Les fonctions lambdas

Les fonctions lambdas sont des fonctions anonymes qui peuvent être définies au mileu d'une autre fonction. Elle sont utiles pour définir une action sans devoir renvoyer le lecteur et l'auteur du code à un autre endroit. Par exemple, avec la fonction std::find, il peut être utile de définir directement le prédicat plutôt que d'indiquer le nom d'une fonction dont le contenu est inconnu.

Les fonctions lambdas s'utilisent de la manière suivante :

[](int x, int y) { return x + y; }

Le type du retour peut être explicitement défini :

[](int x, int y) -> int { int z = x + y; return z; }

Les listes d'initialisations

Les listes d'initialisations permettent d'initialiser les objets en passant une liste de variable entre accolades, comme pour les tableaux et les structures. Pour que cela fonctionne, il faut définir un constructeur qui prend un seul argument de type std::initializer_list. Concrètement cela donne :

class SequenceClass {
public:
    SequenceClass(std::initializer_list<int> list);
};

Et cela s'utilise :

SequenceClass some_var = {1, 4, 5, 6};

Et cela peut même s'utiliser avec une fonction.

Le pointeur NULL

Pour comprendre son intérêt, il faut savoir que la constante NULL est, la plupart du temps, définie comme 0, qui est de type int, ce qui peut poser des problèmes lors de l'appel de méthodes surchargées. Il a donc été décidé d'introduire nullptr qui peut avoir comme type n'importe quelle valeur de pointeur ou un booléen mais pas un autre type :

char *pc = nullptr;     // OK
int  *pi = nullptr;     // OK
bool   b = nullptr;     // OK. b est faux.
int    i = nullptr;     // KO

Ceci permet lorsqu'on a deux fonctions telles que :

void foo(char *);
void foo(int);

que lorsque l'appel suivant est écrit :

foo(nullptr);

le compilateur choisisse la fonction foo(char *) au lieu de foo(int), ce qui est le comportement le plus souvent désiré.

Les chaînes de caractères

Afin d'améliorer la prise en charge de l'unicode, des nouveaux préfixes ont été introduits :

u8"Une chaîne UTF-8"
u"Une chaîne UTF-16"
U"Une chaîne UTF-32"

Pour cela, les types char16_t et char32_t ont été créés. Il est aussi possible d'insérer un caractère unicode en tapant son code en hexadécimal et le préfixant de \u, par exemple \u2603.

Les chaînes raw ont aussi été ajoutées, elle permettent d'éviter de devoir échapper les caractères :

R"(Un slash \ au milieu)"
R"delimiteur(Un slash \ et des guillemets " au milieu )delimiteur"

(Attention, la coloration syntaxique n'est pas encore prévue pour ce nouveau standard).
Comme on le voit, il est possible de définir son propre délimiteur pour ces chaînes afin de pouvoir mettre n'importe quel texte.

Les évolutions de la bibliothèque standard

Les threads

Les threads sont pris officiellement en charge par la bibliothèque standard via l'objet std::thread. Afin de pouvoir les utiliser efficacement, les mutex, variables conditionnelles, les tâches futures et les opérations atomiques sont aussi disponibles.

On peut quand même regretter l'absence de sémaphore dans la spécification.

Containers

Les tuples

Le tuple, ou n-uplets, est une collection ordonnée de n objets. Cette structure est désormais dipsonible et s'utilise de la manière suivante :

typedef std::tuple <int, double, long &, const char *> test_tuple;
long lengthy = 12;
test_tuple proof (18, 6.5, lengthy, "Ciao!");
 
lengthy = std::get<0>(proof);  // Assign to 'lengthy' the value 18.
std::get<3>(proof) = " Beautiful!";  // Modify the tuple’s fourth element.

Les tables de hachage

Quatre nouveaux containers ont été ajoutés :

  • std::unordered_set
  • std::unordered_multiset
  • std::unordered_map
  • std::unordered_multimap

Les versions multi acceptent des entrées avec des clefs identiques. Les set sont des ensembles d'objets non-ordonnés tandis que les map font correspondre à chaque entrée une clef.

Les expressions régulières

Les expressions régulières font leur entrée dans la bibliothèques standard. La fonction std::regex_search est utilisée pour chercher une correspondance tandis que la fonction std::regex_replace sert à remplacer des occurrences dans la chaîne.

const char *reg_esp = R"([ ,.\t\n;:])"; // Une liste de caractères de séparation
    // on utilise les chaîne raw pour éviter de doubler les antislash
std::regex rgx(reg_esp);  
std::cmatch match;  // match est utilisé pour stocker le résultat 
const wchar32_t *target = u"Université de l'invisible - Ankh-Morpork";
 
// Identifie tous les mots de 'target' séparés par les caractères de 'reg_esp'.
if( std::regex_search( target, match, rgx ) ) { // Si des mots séparés par les caractères sont présent.
    const size_t n = match.size();
    for( size_t a = 0; a < n; a++ ) {
        std::string str( match[a].first, match[a].second );
        std::cout << str << std::endl;
    }
}

Gestion des nombres pseudo-aléatoires

Cette nouvelle version du langage introduit une gestion supplémentaire des nombres pseudo-aléatoires, en remplacement de la vénérable fonction rand() que C++ avait conservé du C.

Un objet de génération de nombre pseudo-aléatoire est composé de deux mécanismes :

  • un générateur qui produit les nombres pseudo-aléatoires ;
  • un distributeur, qui détermine la série et la distribution mathématique du résultat.

Contrairement à la fonction standard C rand, le mécanisme du C++1x fournit trois algorithmes de génération :

  • linear_congruential, ayant une qualité de génération et une rapidité moyenne, mais est très économe en mémoire ;
  • subtract_with_carry, rapide mais de qualité moyenne ;
  • mersenne_twister, de bonne qualité et très rapide, mais a l'inconvénient d'être plus gourmand en mémoire.

En revanche, un nombre appréciable de distributeurs existe : uniform_int_distribution, bernoulli_distribution (à ne pas confondre avec berlusconi_distribution), geometric_distribution, poisson_distribution, binomial_distribution, uniform_real_distribution, exponential_distribution, normal_distribution, et gamma_distribution.

Un exemple d'utilisation :

#include 
#include 
 
std::uniform_int_distribution<int> distribution(0, 99);
std::mt19937 engine; // Mersenne twister MT19937
auto generator = std::bind(distribution, engine);
int random = generator();  // Génère un entier entre 0 et 99.
int random2 = distribution(engine); // Génère un autre entier en utilisant directement le générateur avec le moteur de distribution.

L'utilisation de ces objets permet de ne pas laisser à l'application le soin de s'occuper de l'initialisation de la graine, ou de mal l'initialiser, ce qui est source de nombreuses failles de sécurité.

Cet article est, en partie, une traduction de l'article Wikipedia C++0x

par Xavier Claude

DLFP - Dépêches

LinuxFr.org

RootDB - une application web de reporting, auto-hebergée

 -  3 mai - 

Présentation rapide de RootDB, une application auto-hébergeable open-source (AGPLv3), permettant de générer des rapports à base de requêtes SQL. (...)


Libre Graphics Meeting 2024, les 9-11 mai, à Rennes, France

 -  30 avril - 

Le Libre Graphics Meeting (LGM) est la plus grande rencontre mondiale des logiciels libres de graphisme. Née en 2006 de la proposition de l’équipe (...)


Proxmox Virtual Environment 8.2 avec assistant d'import VMware disponible

 -  26 avril - 

Proxmox Server Solutions GmbH a publié la version 8.2 de sa plate-forme de virtualisation libre Proxmox Virtual Environment (VE).La solution (...)


Codeberg, la forge en devenir pour les projets libres ?

 -  25 avril - 

Face aux risques que fait peser GitHub sur le monde des logiciels libres suite à son rachat par Microsoft en 2018, une alternative semble avoir (...)


L’informatique sans écran

 -  21 avril - 

Lors d’un Noël de ma tendre jeunesse pré-adolescente est arrivé un « ordinateur » dans le foyer. Ce PC (Intel 386) a été installé dans le bureau et a (...)