mardi 8 octobre 2013

Generalized attributes

Quelles autres surprises g++4.8 nous réserve dans sa besace? Eh bien, une nouvelle fonctionnalité de C++11 est la gestion des attributes généralisés. L'idée est de permettre de spécifier un comportement via des directives, certaines standard, d'autres spécifiques au compilateur. La syntaxe est plutôt ésotérique: autant définir un attribut est trivial, puisqu'il s'installe [[entre double crochets]], autant le placement de l'attribut en lui même est moins évident puisqu'il va indiquer s'il s'applique à un type ou à une instance. Je vous renvoie aux exemples pour les détails sordides, intéressons nous plutôt aux attributs qui sont dès maintenant disponibles

Le premier de ces attributs est [[noreturn]], qui permet d'indiquer que la fonction ne retournera jamais (elle peut en revanche lancer une exception). Par exemple:

void runForEver [[noreturn]] ()
{
  while(1);
}

int main()
{
  runForEver();
  
  return 0;
}

L'utilité d'un tel attribut est de permettre au compilateur d'optimiser un pareil cas, en ne générant pas le code qui gère le retour de la fonction. D'ailleurs, si jamais vous vous amusiez à faire une fonction qui retourne bien qu'ayant l'attribut [[noreturn]], le verdict serait sans appel: d'abord un warning

attributes.cpp: In function ‘void runForEver()’:
attributes.cpp:3:1: warning: ‘noreturn’ function does return [enabled by default]
 }
 ^

Et ensuite, avec g++ tout du moins, un beau crash lorsque vous faites tourner le programme. Par contre, vous êtes tout à fait autorisés, comme indiqué précédemment, à lancer une exception:

#include <stdexcept>

void countToTen [[noreturn]] ()
{
  for(size_t i = 0; i < 10; ++i);
  throw std::runtime_error("End of the road");
}

int main()
{
  countToTen();
  
  return 0;
}

Les deux autres attributs sont [[final]] et [[align]]. L'attribut [[final]] sur une méthode virtuelle permet d'empêcher la redéfinition de cette méthode dans une classe fille, et sur une classe permet d'empêcher sa dérivation. Ces fonctionnalités sont déjà fournies par les explicit virtual overrides, décrits ici. Quant à l'attribut [[align]], il permet de définir l'alignement des données, ce qui est une fonctionnalité déjà fournie par une autre spécification. Comme d'habitude, le C++ fournit beaucoup trop de manières différentes de faire la même chose... Mais c'est pour ça qu'on l'aime?

Aucun commentaire: