/* Modex ACM c.durr (2008)
   
   boucles horribles pour iterer de maniere elegante
*/

#include <iostream>
#include <vector>
#include <map>

using namespace std;

/* forall(i,v) permet de boucler sur toutes les valeurs i stockees dans
   le conteneur v. 

   v peut etre un vecteur, une liste, un set, etc.  La variable i doit
   etre declaree.
   
   On espere que la variable xXx n'est utilise nulle part ailleurs que
   dans ces boucles.

   L'utilisation de typeof ne fonctionne que dans g++.
*/
#define forall(i, v) for(typeof(v.end()) xXx = v.begin();        \
			 xXx != v.end() ? (i=*xXx), true: false; \
			 xXx++)

/* forall(cle,valeur,m) permet de boucler sur toutes les paires (cle, valeur)
   dans la table d'association m.
   cle et valeur doivent etre declares.
*/
#define forallPairs(k,v, m)                                          \
  for(typeof(m.end()) xXx = m.begin();				     \
      xXx != m.end() ? (k=xXx->first), (v=xXx->second), true: false; \
      xXx++)

/* forallIdx(i,t) permet de boucler sur tous les indices d'un tableau
   donnee.  Il faut alors que le tableau soit declare avec toute sa
   longueur.  Comme dans "int tab[20]", et pas comme un pointeur comme
   dans un parametre par exemple de type "int tab[]" ou "int *tab".
*/
#define forallIdx(i,t) for(typeof(t[0]) i=0; i<sizeof(t)/sizeof(t[0]); i++)

/* exemple d'utilisation.
 */
int main() {
  vector<int> v;
  int i,j;
  v.push_back(23);
  v.push_back(42);
  v.push_back(17);

  forall(i, v)
    forall(j, v)
    cout << i+j << ' ';
  cout << endl;

  map<string, int> m;
  m["un"]   = 1;
  m["Zwei"]  = 2;
  m["three"] = 3;
  m["bon"]   = 4;
  string key;
  int    val;

  forallPairs(key, val, m)
    cout << key << " -> " << val << endl;
  
  int tab[4] = {12,4,123,2};
  forallIdx(i,tab)
    cout << "tab["<<i<<"]="<<tab[i]<<endl;
}

