Fonction Lambda, un incontournable

Tips and Tricks!

Cas utilisation de notre environnement de programmation

Dans notre environnement de simulation nous utilisons une discrétisation aux volumes finis, le domaine de calcul est partitionné en éléments appelé  “cell”. On résout les équations sur chacune des “cell”. Cas unidimensionnel, “cell” consiste en une paire de  “cell face”. Nous avons des utilitaires qui permettent de créer les “cell” à l’initialisation. Depuis quelques temps nous migrons notre code vers C++11/14 et j’ai commencé à utiliser les fonctions lambda dans la procédure de création des “cell”.

Je  présente 2 façons de créer  des paires d’objets en utilisant cette nouvelle fonctionnalité. Pour créer une paire d’objet il existe l’utilitaire « make_pair » qui retourne une paire.

Quelques “typedef” pour rendre le code plus lisible

   using namespace std;
   using namespace boost;
   using namespace std::placeholders;
   typedef std::list<cellFace>::iterator list_iter;         // list iterator
   typedef iterator_range<list_iter> iter_cellface;         // iterator list range
   typedef range_iterator<iter_cellface>::type range_iter;  // range iterator type
   typedef range_difference<iter_cellface>::type diff_type; // range difference

Nous définissons 2 sub-range dont les éléments sont décalés l’un par rapport à l’autre [begin,end[ et ]begin,end].

Boost iterator_range est parfaitement adapté pour effectuer ce genre de tache. Dans ce cas-ci nous n’avons pas besoin d’un container, on veut simplement parcourir la collection. C’est exactement ce que fait boost iterator range, c’est une paire d’iterator qui définit un range.

Boost web site
“The intention of the iterator_range class is to encapsulate two iterators so they fulfill the Forward Range concept.”

  // [begin,end-1[
  iter_cellface w_rngFace = make_iterator_range(m_listFaces).advance_end(-1);
  // [begin+1,end[
  iter_cellface w_rngFacep1 = make_iterator_range(m_listFaces).advance_begin(1);

Pour s’assurer que les 2 sous range ont le meme nombre d’elements, on peut utiliser algorithme distance de boost (librairie boost range algorithm).

 // check equality of both range size (use boost range algorithm)
 diff_type w_diff1 = distance(w_rngFace);
 diff_type w_diff2 = distance(w_rngFacep1);
 assert(w_diff1 == w_diff2);

 Methode 1 (fonction objet)

Pour créer une paire d’objet il existe l’utilitaire « make_pair » qui retourne une paire (std::pair).

 template <typename T,typename U>
  struct pair_creator : std::binary_function<T, U, std::pair<T, U>>
  {
    std::pair<T, U> operator() ( const T& arg1, const U& arg2 ) const 
    {
      return std::make_pair( arg1, arg2 );
    }
  };

Algorithm “transform” de la STL pour creer la paire a partir de nos 2 sub-range

Dans les deux cas que je présente, nous utilisons l’algorithme « transform » de la stl. Cet algorithme vient en plusieurs version, celle que nous allons utiliser prend comme un de ces arguments une fonction binaire.

   std::transform( w_rngFace.begin(), w_rngFace.end(), // premier range 
                   w_rngFacep1.begin(),        // second range 
                   m_cellFacesPair.begin(), // store pair of faces
                   pair_creator<cellFace, cellFace>()); // fonction object 

  Methode 2 (fonction lambda)

 

clients and partners

Autolog