dimanche 13 mars 2011

g++ 4.5 et C++0x - Les nouveautés

J'ai porté Openrailz sous g++4.5, ce qui me permet d'utiliser plus de fonctionnalités de C++0x, mais a également soulevé quelque problèmes inattendus. Petit topo.

Destructeur virtuel et = default

Tout d'abord, les mauvaises nouvelles. Je ne sais si vous avez déjà souffert du problème, mais je n'ai jamais trouvé une manière complétement satisfaisante d'implémenter le destructeur virtuel en écrivant une interface. L'on peut inliner le code:


class Miaou
{
virtual ~Miaou() {}
};

mais c'est moche. L'on peut mettre le code en dessous:

class Miaou
{
virtual ~Miaou();
};

inline Miaou::~Miaou()
{
}

mais c'est encore plus moche, sans compter la verbosité lorsque la déclaration est un peu plus complexe (gros template, par exemple). Enfin, l'on peut juste mettre la déclaration dans son .cpp, mais on se retrouve avec un .cpp qui ne contient qu'une déclaration vide, et toujours aussi potentiellement verbeuse.

Lorsque j'ai découvert le = default de C++0x, je me suis dit, bonne nouvelle, voilà enfin comment résoudre le problème:

class Miaou
{
virtual ~Miaou() = default;
};

C'est joli, moderne, et ça fait exactement ce que ça dit. Malheureusement, c'est également interdit par le standard, et si g++4.4 laissait passer, g++4.5 le bloque. Le standard interdit en effet de déclarer un destructeur virtuel par défaut à la première déclaration. C'est à dire que pour écrire du code correct, il faut faire:

class Miaou
{
virtual ~Miaou();
};

inline Miaou::~Miaou() = default;

ce qui est tout aussi moche. Retour donc a la case départ.

Strict aliasing rules et boost::optional

J'avais commencé à virer les boost::optional de ma codebase, car ils causaient un ennuyeux warning dans g++4.4:

#include <iostream>
#include <boost/optional.hpp>

int main()
{
boost::optional<int> b;
if(b)
{
std::cout << *b << std::endl;
}

return 0;
}

La compilation avec g++4.4 renvoie ce message:

optional.cpp: In function ‘int main()’:
optional.cpp:10: warning: dereferencing pointer ‘’ does break strict-aliasing rules
optional.cpp:10: note: initialized from here

Alors, bien sûr, l'on peut utiliser le flag -fno-strict-aliasing, mais l'on réduit les performances.

Les discussions sont allé bon train sur les mailing-lists de Boost, mais il semblerait que le code soit en fait bon, et qu'il s'agisse d'un bug de g++4.4. G++4.5 ne se plaint pas sur ce code, et je compte donc bien le réintégrer vite fait, en particulier pour gérer les colonnes nullables dans mon code de base de données (voir le post précédent).

Et bien sûr... Les lambdas!

Va falloir commencer à s'habituer aux listes de captures, et faire gaffe au passage par valeur / référence. Raison de plus pour commencer le plus tôt possible, et en coller partout. 'tention les yeux! Notons également des améliorations sur les variadic templates, et les chaînes de caractères unicode.

Aucun commentaire: