<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Coder-Studio &#187; énumération</title>
	<atom:link href="http://www.coder-studio.com/blog/tag/enumeration/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coder-studio.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 31 Mar 2010 00:00:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Préprocesseur et énumérations : la suite.</title>
		<link>http://www.coder-studio.com/blog/preprocesseur-et-enumerations-la-suite/</link>
		<comments>http://www.coder-studio.com/blog/preprocesseur-et-enumerations-la-suite/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 20:34:09 +0000</pubDate>
		<dc:creator>Funto</dc:creator>
				<category><![CDATA[C & C++]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[énumération]]></category>
		<category><![CDATA[préprocesseur]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=393</guid>
		<description><![CDATA[Cet article fait suite à mon premier article intitulé &#171;&#160;Faire un peu joujou avec le préprocesseur&#160;&#187;
(disponible ici : http://www.coder-studio.com/blog/preproc/ ).
Pour rappel, nous en sommes restés à un système de macro qui permettait d&#8217;automatiser la création
d&#8217;un opérateur &#171;&#160;]]></description>
			<content:encoded><![CDATA[<p>Cet article fait suite à mon premier article intitulé &laquo;&nbsp;Faire un peu joujou avec le préprocesseur&nbsp;&raquo;<br />
(disponible ici : http://www.coder-studio.com/blog/preproc/ ).</p>
<p>Pour rappel, nous en sommes restés à un système de macro qui permettait d&#8217;automatiser la création<br />
d&#8217;un opérateur &laquo;&nbsp;<<" pour iostream, capable d'afficher le nom d'une énumération.</p>
<p><span id="more-393"></span></p>
<p>Voici le code :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code12'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39312"><td class="code" id="p393code12"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_N(nb_vals, ...) ENUM_CASE_ ## nb_vals(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(nb_vals, enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			ENUM_CASE_N(nb_vals, __VA_ARGS__)	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(nb_vals, enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(nb_vals, enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code13'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39313"><td class="code" id="p393code13"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// main.cpp</span>
&nbsp;
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span>, MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Le plus gros problème de ce système est le fait que l&#8217;on soit obligés de donner le nombre de valeurs de l&#8217;énumération<br />
lors de l&#8217;utilisation de la macro ENUMERATE.</p>
<p>Ce qui nous oblige à spécifier ce numéro, c&#8217;est la nécessiter de &laquo;&nbsp;choisir&nbsp;&raquo; la bonne macro parmi ENUM_CASE_1, ENUM_CASE_2, &#8230;, ENUM_CASE_10.</p>
<p>Se passer de ce nombre, c&#8217;est effectuer l&#8217; &laquo;&nbsp;appel récursif&nbsp;&raquo; jusqu&#8217;à ce qu&#8217;il n&#8217;y ait plus d&#8217;argument à traiter dans la<br />
&laquo;&nbsp;liste&nbsp;&raquo; __VA_ARGS__.</p>
<p>Que se passe-t-il si l&#8217;on supprime ce nombre et que l&#8217;on remplace l&#8217;appel à ENUM_CASE_N par la version qui gère le plus d&#8217;arguments<br />
(ici ENUM_CASE_10, donc) ?</p>
<p>Version remaniée :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code14'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39314"><td class="code" id="p393code14"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			ENUM_CASE_10(__VA_ARGS__)	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code15'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39315"><td class="code" id="p393code15"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// test.cpp</span>
&nbsp;
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span>MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Après un appel au préprocesseur par &laquo;&nbsp;cpp test.cpp&nbsp;&raquo;, voici ce qu&#8217;il nous affiche (remis en forme pour être lisible et<br />
en enlevant les lignes commençant par un #, sans importance) :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code16'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39316"><td class="code" id="p393code16"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">enum</span> MonEnumeration <span style="color: #008000;">&#123;</span> E_VAL_1, E_VAL_2, E_VAL_3 <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">inline</span> std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">&lt;&lt;</span><span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> os, <span style="color: #0000ff;">const</span> MonEnumeration<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">case</span> E_VAL_1<span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_1&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> E_VAL_2<span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_2&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> E_VAL_3<span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_3&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Vous voyez le problème : on a des &laquo;&nbsp;case :&nbsp;&raquo; à partir du stade où il n&#8217;y a plus d&#8217;argument. Il faut donc remplacer<br />
chaque ligne &laquo;&nbsp;case &#8230;&nbsp;&raquo; (correspondant à ce que génère ENUM_CASE_1) par quelque chose qui puisse faire un test d&#8217;égalité<br />
entre &laquo;&nbsp;e&nbsp;&raquo; et &laquo;&nbsp;E_VAL_1&#8243;, &laquo;&nbsp;E_VAL_2&#8243;&#8230;etc, mais qui puisse aussi compiler et ne rien faire lorsqu&#8217;en lieu et place<br />
de &laquo;&nbsp;E_VAL_XXX&nbsp;&raquo;, il n&#8217;y a rien.</p>
<p>Là, on pense à la surcharge de fonction ! En effet, si l&#8217;on a une fonction surchargée ainsi :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code17'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39317"><td class="code" id="p393code17"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> f<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #666666;">// blabla</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> f<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #666666;">// blublu</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>on peut obtenir un comportement différent selon que l&#8217;on passe ou pas quelque chose en argument à la fonction !<br />
Il suffirait de remplacer chaque ligne &laquo;&nbsp;case &#8230;&nbsp;&raquo; par un test d&#8217;égalité qui aurait cette forme :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code18'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39318"><td class="code" id="p393code18"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #008000;">&#40;</span>e, E_VAL_1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_1&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>et le tour est joué !</p>
<p>Mais attendez, vous ne voyez pas un problème ? Si, si : contrairement à la fonction f() de l&#8217;exemple, ce &laquo;&nbsp;TestEgalite&nbsp;&raquo;<br />
a 2 arguments. Si l&#8217;on remplace &laquo;&nbsp;E_VAL_1&#8243; par du vide, on obtient un &laquo;&nbsp;if(TestEgalite(e, )) {blabla;}&nbsp;&raquo; : ça ne marche pas !</p>
<p>Le problème reste donc entier&#8230;<br />
Oui, pour ceux qui se demandent, cette partie de l&#8217;article n&#8217;apporte rien à la solution, c&#8217;est juste la démarche que j&#8217;ai<br />
eue : vous pouvez vous dire que ça ne sert à rien, je ne vous le reprocherai pas, mais maintenant c&#8217;est trop tard, vous<br />
l&#8217;avez lu :p</p>
<p>On pourrait se poser le problème ainsi : comment, à partir d&#8217;une fonction à 2 arguments, en faire 2 fonctions à 1 argument ?<br />
En effet, si l&#8217;on arrive à en faire 2 fonctions à 1 argument, alors le problème serait réglé <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Si je ne m&#8217;abuse, il<br />
s&#8217;agit de la &laquo;&nbsp;curryfication&nbsp;&raquo;, que l&#8217;on trouve en programmation fonctionnelle et en lambda-calcul <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Peut-être est-ce possible, je n&#8217;ai pas exploré cette possibilité. Il ne m&#8217;étonnerait pas que cela soit possible grâce à des<br />
foncteurs, i.e. une classe dont un surcharge l&#8217;opérateur &laquo;&nbsp;()&nbsp;&raquo;. On peut ainsi se retrouver avec une construction de la forme<br />
&laquo;&nbsp;MaClasse(arg1)(arg2)&nbsp;&raquo;, i.e. un appel au constructeur suivi d&#8217;un appel à l&#8217;opérateur &laquo;&nbsp;()&nbsp;&raquo;.</p>
<p>En fait, à mon avis, c&#8217;est une solution possible, je garderai peut-être pour la suite, dans un hypothétique futur article <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Quoi qu&#8217;il en soit, pour en revenir au problème : on peut aussi se le poser ainsi : est-on obligés de traiter les cas où<br />
le préprocesseur ne met rien, en lieu et place de nos &laquo;&nbsp;E_VAL_1&#8243;, &laquo;&nbsp;E_VAL_2&#8243;&#8230;etc ? Dit encore autrement, ne peut-on pas mettre<br />
quelque chose d&#8217;autre à la place ? Qu&#8217;est-ce qui nous arrangerait alors ?</p>
<p>Hmm, voyons voir, remplacer le vide par quelque chose que l&#8217;on pourrait tester lors de la compilation&#8230;<br />
Il s&#8217;agit bien de méta-programmation. Or, en méta-programmation : les 2 outils principaux que le C++ met à notre disposition<br />
sont les macros et les templates.</p>
<p>Eurêka !</p>
<p>On peut &laquo;&nbsp;surcharger&nbsp;&raquo; une fonction template qui s&#8217;occupera de faire le test d&#8217;égalité !<br />
On écrit alors les tests d&#8217;égalité comme ceci :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code19'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39319"><td class="code" id="p393code19"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #000080;">&lt;</span>E_VAL_1<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>blabla<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #000080;">&lt;</span>E_VAL_2<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>blabla<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span>
...
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">void</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>blabla<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>On déclare alors TestEgalite sous cette forme :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code20'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39320"><td class="code" id="p393code20"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span>MonEnumeration val<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> TestEgalite<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EnumType<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> e <span style="color: #000080;">==</span> val<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> TestEgalite<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EnumType<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Et le tour est joué !</p>
<p>Bon, maintenant, pour faire plus pro, en renommant ça en anglais et en préfixant par le nom de l&#8217;énumération<br />
(histoire que l&#8217;on n&#8217;ait pas de conflit s&#8217;il y a 2 énumérations différentes, au cas où), et en remettant tout<br />
ensemble, cela donne ceci :</p>
<p>Version finale :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code21'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39321"><td class="code" id="p393code21"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(EnumType, ...)	\
	enum EnumType { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(EnumType, val, ...)	\
	if(EnumType ## _EnumIsEqual&lt;val&gt;(e)) {os &lt;&lt; #val; break;}</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_1(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_3(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_2(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_4(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_3(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_5(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_4(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_6(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_5(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_7(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_6(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_8(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_7(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_9(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_8(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_10(EnumType, val, ...)	ENUM_CASE_1(EnumType, val) ENUM_CASE_9(EnumType, __VA_ARGS__, void)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(EnumType, ...)	\
	template &lt;EnumType val&gt;				\
	inline bool EnumType ## _EnumIsEqual(const EnumType&amp; e) {	\
		return e == val;										\
	}															\
																\
	template &lt;class T&gt;											\
	inline bool EnumType ## _EnumIsEqual(const EnumType&amp; e) {	\
		return false;											\
	}															\
																\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const EnumType&amp; e) {	\
		do {																\
			ENUM_CASE_10(EnumType, __VA_ARGS__, void)								\
		} while(0);											\
		return os;											\
	}</span>
&nbsp;
<span style="color: #339900;">#define ENUMERATE(EnumType, ...)		\
	MAKE_ENUM(EnumType, __VA_ARGS__)	\
	MAKE_OPERATOR(EnumType, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code22'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39322"><td class="code" id="p393code22"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// main.cpp</span>
&nbsp;
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span>MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Voilà pour cette partie <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Ceci dit, un problème est résolu, mais il en reste d&#8217;autres, notamment :<br />
- ça doit toujours aussi mal passer auprès des systèmes d&#8217;auto-complétion (enfin, j&#8217;ai pas testé sur Visual Assist<br />
  ou Eclipse à vrai dire&#8230;)<br />
- on ne peut toujours pas attribuer de valeur numérique manuellement à un symbole de l&#8217;énumération</p>
<p>Il pourrait aussi être intéressant d&#8217;associer une autre chaîne de caractères, voire toute autre valeur, à un symbole de<br />
l&#8217;énumération&#8230;<br />
Tout comme il serait intéressant d&#8217;explorer une solution à base de pseudo-curryfication plutôt que de templates, voire, qui<br />
sait, une solution entièrement à base de templates. A ce sujet, un article très intéressant est disponible ici pour les<br />
curieux : http://www.codeguru.com/cpp/cpp/cpp_mfc/templates/article.php/c4137</p>
<p>Ce sera tout pour cette fois !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/preprocesseur-et-enumerations-la-suite/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Faire un peu joujou avec le préprocesseur&#8230;</title>
		<link>http://www.coder-studio.com/blog/preproc/</link>
		<comments>http://www.coder-studio.com/blog/preproc/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 18:53:54 +0000</pubDate>
		<dc:creator>Funto</dc:creator>
				<category><![CDATA[C & C++]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[énumération]]></category>
		<category><![CDATA[préprocesseur]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=371</guid>
		<description><![CDATA[Ça faisait un bail que je n'écrivais pas sur Coder-Studio...
Chose réparée :)

Du 17 au 19 avril 2009, a eu lieu la finale de Cod'INSA, un concours de programmation inter-INSA,
qui s'est déroulée à l'INSA de Toulouse (plus d'infos sur http://codinsa.insa-lyon.fr pour les intéressés).
Faisant partie des organisateurs, j'ai eu à faire l'interfaçage C++/Java (oui parce qu'il y en a qui veulent
participer en Java...allez comprendre :p [/troll]). J'y ai découvert les joies de GCJ et de CNI, ce qui
pourra peut-être être l'objet d'un autre article, selon ma motivation...

Bref, tout ça pour dire qu'il m'a fallu interfacer une librairie écrite en C avec du Java, et qu'il a fallu
automatiser un peu le boulot pour la partie concernant les énumérations.

Dans cet article, je vais illustrer une méthode pour faciliter l'affichage des valeurs des énumérations.
En gros, le but, c'est que si l'on a :
<pre lang="cpp">
MonEnumeration e = E_VAL_1;
std::cout << e << std::endl;
</pre>

il s'affiche alors à l'écran "E_VAL_1".]]></description>
			<content:encoded><![CDATA[<p>Ça faisait un bail que je n&#8217;écrivais pas sur Coder-Studio&#8230;<br />
Chose réparée <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Du 17 au 19 avril 2009, a eu lieu la finale de Cod&#8217;INSA, un concours de programmation inter-INSA,<br />
qui s&#8217;est déroulée à l&#8217;INSA de Toulouse (plus d&#8217;infos sur http://codinsa.insa-lyon.fr pour les intéressés).<br />
Faisant partie des organisateurs, j&#8217;ai eu à faire l&#8217;interfaçage C++/Java (oui parce qu&#8217;il y en a qui veulent<br />
participer en Java&#8230;allez comprendre :p [/troll]). J&#8217;y ai découvert les joies de GCJ et de CNI, ce qui<br />
pourra peut-être être l&#8217;objet d&#8217;un autre article, selon ma motivation&#8230;</p>
<p>Bref, tout ça pour dire qu&#8217;il m&#8217;a fallu interfacer une librairie écrite en C avec du Java, et qu&#8217;il a fallu<br />
automatiser un peu le boulot pour la partie concernant les énumérations.</p>
<p>Dans cet article, je vais illustrer une méthode pour faciliter l&#8217;affichage des valeurs des énumérations.<br />
En gros, le but, c&#8217;est que si l&#8217;on a :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code23'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37123"><td class="code" id="p371code23"><pre class="cpp" style="font-family:monospace;">MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>il s&#8217;affiche alors à l&#8217;écran &laquo;&nbsp;E_VAL_1&#8243;.</p>
<p><span id="more-371"></span></p>
<p>La version non automatisée consiste en l&#8217;écriture d&#8217;une surcharge de l&#8217;opérateur &laquo;&nbsp;<<". Programme de démonstration :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code24'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37124"><td class="code" id="p371code24"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">enum</span> MonEnumeration
<span style="color: #008000;">&#123;</span>
	E_VAL_1,
	E_VAL_2
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">&lt;&lt;</span><span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> os, <span style="color: #0000ff;">const</span> MonEnumeration<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">case</span> E_VAL_1<span style="color: #008080;">:</span>
		os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_1&quot;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> E_VAL_2<span style="color: #008080;">:</span>
		os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_2&quot;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Ce programme affiche bien &laquo;&nbsp;E_VAL_1&#8243; à l&#8217;écran.</p>
<p>Mais c&#8217;est tout de même bien contraignant : la duplication des informations est évidente : entre la<br />
déclaration de l&#8217;énumération et l&#8217;opérateur &laquo;&nbsp;<<", "E_VAL_1" est écrit 3 fois ! C'est évidemment source<br />
d'erreurs (le copier-coller n'est pas le meilleur ami du programmeur, loin s'en faut...), particulièrement<br />
lorsque l'on veut rajouter de nouvelles valeurs à l'énumération. Et puis c'est tout simplement pénible<br />
de devoir maintenir l'énumération et l'opérateur.<br />
Bref, c'est moche, peut mieux faire.</p>
<p>C'est là qu'arrive le préprocesseur.</p>
<p>A partir de là, je suppose que vous utilisez GCC (ou MinGW/Cygwin sous Windows).</p>
<p>Nous allons en particulier nous baser sur 2 opérateurs spéciaux du préprocesseur, qui ne sont pas très<br />
connus : # et ##.</p>
<p>Commençons par # : il permet de rajouter des guillemets autour de l'argument d'une macro.</p>
<p>Démonstration :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code25'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37125"><td class="code" id="p371code25"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define STRINGIFY(val) #val</span>
&nbsp;
STRINGIFY<span style="color: #008000;">&#40;</span>pouet<span style="color: #008000;">&#41;</span></pre></td></tr></table></div>

<p>Supposons que vous ayez enregistré cela dans &laquo;&nbsp;pouet.h&nbsp;&raquo; : passez un coup de préprocesseur : &laquo;&nbsp;cpp pouet.h&nbsp;&raquo;<br />
(ou bien &laquo;&nbsp;g++ -E pouet.h&nbsp;&raquo;, ça revient au même).</p>
<p>Résultat affiché :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code26'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37126"><td class="code" id="p371code26"><pre class="text" style="font-family:monospace;"># 1 &quot;pouet.h&quot;
# 1 &quot;&lt;interne&gt;&quot;
# 1 &quot;&lt;command-line&gt;&quot;
# 1 &quot;pouet.h&quot;
&nbsp;
&nbsp;
&quot;pouet&quot;</pre></td></tr></table></div>

<p>Bon, déjà, ça c&#8217;est intéressant <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  On remarque que cpp écrit des lignes commençant par un #, que le compilateur<br />
qui passe derrière doit probablement interpréter pour les messages d&#8217;erreurs afin d&#8217;indiquer la ligne de l&#8217;erreur.</p>
<p>Passons à la suite : on voudrait une macro qui permette d&#8217;automatiser la création de l&#8217;opérateur &laquo;&nbsp;<<" pour<br />
l'affichage de la valeur de notre énumération.<br />
Essayons d'abord en supposant que notre énumération ne puisse contenir qu'une seule valeur :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code27'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37127"><td class="code" id="p371code27"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define MAKE_ENUM(enum_name, val)	\
	enum enum_name {	\
		val			\
	};</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(enum_name, val)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			case val:	\
				os &lt;&lt; #val;	\
				break;	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(enum_name, val)	\
	MAKE_ENUM(enum_name, val)	\
	MAKE_OPERATOR(enum_name, val)</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span>MonEnumeration,
	E_VAL_1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>On a donc une macro MAKE_ENUM qui s&#8217;occupe de déclarer l&#8217;énumération et une macro MAKE_OPERATOR qui s&#8217;occupe<br />
de définir l&#8217;operateur &laquo;&nbsp;<<". Notez le "inline" qui sert à éviter tout problème de linkage (si le même fichier .h,<br />
qui décrit l'énumération et l'opérateur, est inclus dans 2 .cpp différents, on se retrouve avec l'opérateur défini 2<br />
fois, et couic !).</p>
<p>Cool, ça marche ! (en même temps c'est un tuto...)</p>
<p>Maintenant, on peut arrêter de contourner la difficulté et s'attaquer au vrai problème : comment gérer le fait<br />
qu'une énumération n'ai pas 1, 2, ou 3 valeurs, mais un nombre variable ??</p>
<p>C'est là qu'arrive une autre astuce du préprocesseur : la macro __VA_ARGS__.</p>
<p>Démonstration, dans notre pouet.h :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code28'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37128"><td class="code" id="p371code28"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define MA_MACRO(...) __VA_ARGS__</span>
MA_MACRO<span style="color: #008000;">&#40;</span>a, b, c<span style="color: #008000;">&#41;</span></pre></td></tr></table></div>

<p>cpp pouet.h donne :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code29'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37129"><td class="code" id="p371code29"><pre class="text" style="font-family:monospace;"># 1 &quot;pouet.h&quot;
# 1 &quot;&lt;interne&gt;&quot;
# 1 &quot;&lt;command-line&gt;&quot;
# 1 &quot;pouet.h&quot;
&nbsp;
a, b, c</pre></td></tr></table></div>

<p>Pratique, quand on veut des macros avec un nombre variable d&#8217;arguments&#8230;</p>
<p>On peut dores et déjà remplacer MAKE_ENUM par une version capable de gérer un nombre variable d&#8217;arguments :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code30'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37130"><td class="code" id="p371code30"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span></pre></td></tr></table></div>

<p>Ça, c&#8217;est fait. Maintenant, reste le problème de MAKE_OPERATOR&#8230;</p>
<p>Si l&#8217;on analyse le problème, on voit que l&#8217;on a 3 parties :</p>
<p>- une introduction :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code31'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37131"><td class="code" id="p371code31"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">inline</span> std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">&lt;&lt;</span><span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> os, <span style="color: #0000ff;">const</span> enum_name<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span></pre></td></tr></table></div>

<p>- une partie qui se répète :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code32'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37132"><td class="code" id="p371code32"><pre class="cpp" style="font-family:monospace;">		<span style="color: #0000ff;">case</span> val<span style="color: #008080;">:</span>
			os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #339900;">#val;</span>
			<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>- une conclusion :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code33'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37133"><td class="code" id="p371code33"><pre class="cpp" style="font-family:monospace;">		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Il s&#8217;agit donc, à partir d&#8217;une liste variable d&#8217;arguments, de répéter plusieurs fois la partie centrale pour<br />
chaque argument &laquo;&nbsp;val&nbsp;&raquo;. C&#8217;est là que j&#8217;ai pensé à ces vieux cours de Caml, où pour traiter une liste, on écrivait<br />
une fonction récursive, qui décomposait la liste en t::q (pour tête et queue), la tête étant le 1er élément, et la<br />
queue tout le reste. Désolé pour ceux qui n&#8217;ont pas fait de Caml :p</p>
<p>Pour revenir à notre préprocesseur, cela se traduirait par une macro qui prend en argument quelque chose de la forme :<br />
#define MACRO(a, &#8230;) et qui ensuite s&#8217;appellerait récursivement jusqu&#8217;à ce qu&#8217;il n&#8217;y ait plus d&#8217;argument.</p>
<p>Malheureusement, la récursivité, en préprocesseur ça n&#8217;existe pas, ou alors j&#8217;ai pas trouvé comment&#8230;</p>
<p>Il va donc falloir trouver une parade : il s&#8217;agira d&#8217;écrire une version de la macro pour chaque appel récursif, i.e.<br />
pour chaque nombre d&#8217;arguments :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code34'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37134"><td class="code" id="p371code34"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span></pre></td></tr></table></div>

<p>Le problème n&#8217;est toujours pas totalement résolu : encore faut-il choisir la bonne macro à utiliser&#8230;</p>
<p>C&#8217;est là qu&#8217;arrive l&#8217;opérateur ## du préprocesseur <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Celui-ci permet de concaténer des symboles.</p>
<p>Exemple (dans pouet.h) :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code35'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37135"><td class="code" id="p371code35"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define CONCAT(a, b) a ## b</span>
CONCAT<span style="color: #008000;">&#40;</span>foo, bar<span style="color: #008000;">&#41;</span></pre></td></tr></table></div>

<p>&laquo;&nbsp;cpp pouet.h&nbsp;&raquo; affiche cette fois :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code36'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37136"><td class="code" id="p371code36"><pre class="text" style="font-family:monospace;"># 1 &quot;pouet.h&quot;
# 1 &quot;&lt;interne&gt;&quot;
# 1 &quot;&lt;command-line&gt;&quot;
# 1 &quot;pouet.h&quot;
&nbsp;
foobar</pre></td></tr></table></div>

<p>Cela va nous servir à choisir la bonne macro à utiliser :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code37'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37137"><td class="code" id="p371code37"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define ENUM_CASE_N(nb_vals, ...) ENUM_CASE_ ## nb_vals(__VA_ARGS__)</span></pre></td></tr></table></div>

<p>Le gros inconvénient est bien sûr qu&#8217;il nous faut préciser le nombre de valeurs de l&#8217;énumération :/</p>
<p>Il semble que l&#8217;on ait fait le tour. Voici donc la version finale de tout ça, séparée dans un .h générique<br />
et un .cpp d&#8217;exemple :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code38'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37138"><td class="code" id="p371code38"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_N(nb_vals, ...) ENUM_CASE_ ## nb_vals(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(nb_vals, enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			ENUM_CASE_N(nb_vals, __VA_ARGS__)	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(nb_vals, enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(nb_vals, enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code39'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37139"><td class="code" id="p371code39"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// main.cpp</span>
&nbsp;
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span>, MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p><strong>Conclusion</strong></p>
<p>Au final, cette méthode présente l&#8217;avantage d&#8217;éviter la duplication de code, et tous les ennuis qui vont avec.<br />
Il reste cependant plusieurs inconvénients non négligeables :<br />
- On est obligés de préciser le nombre de valeurs de l&#8217;énumération<br />
- On est limités dans le nombre de valeurs que l&#8217;on peut définir par le nombre de macros que l&#8217;on a définis dans Enumerate.h<br />
  A la limite, si l&#8217;on a besoin de plus de valeurs, il suffit de les rajouter, c&#8217;est pas bien grave ^^<br />
- Pour la plupart des IDE, je pense qu&#8217;un tel système aboutit à un type &laquo;&nbsp;MonEnumeration&nbsp;&raquo;, ainsi que les valeurs définies,<br />
  qui sont inconnus. Ça peut être un problème&#8230;<br />
- En déclarant ses énumérations de la sorte, on ne peut pas préciser de valeur numérique pour chaque valeur possible de<br />
  l&#8217;énumération.</p>
<p>La méthode a ses limites, et je me demande s&#8217;il n&#8217;y aurait pas moyen d&#8217;aller au-delà en utilisant des templates&#8230;<br />
Par ailleurs, ce petit article sur le préprocesseur ne fait aucune mention de Boost::Preprocessor, qui, selon Arnaud,<br />
est incroyable à voir&#8230;<br />
Je serais curieux de voir s&#8217;il pourrait apporter un élément de réponse au problème ^^</p>
<p>Ce sera tout !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/preproc/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
