Boost C++ Libraries: Ticket #1916: [mpl] MPL_HAS_XXX_TRAIT_DEF bug in MSVC71 https://svn.boost.org/trac10/ticket/1916 <p> The MSVC71 implementation of MPL_HAS_XXX_TRAIT_DEF does not correctly support defining a trait of the same name even if that is enclosed within a different namespace. It seems to have something to do with the instantiation of the 'msvc71_sfinae_helper'. In the code below I do the following: </p> <div class="wiki-code"><div class="code"><pre><span class="k">namespace</span> <span class="n">one</span> <span class="p">{</span> <span class="n">BOOST_MPL_HAS_XXX_TRAIT_DEF</span><span class="p">(</span><span class="n">result_type</span><span class="p">)</span> <span class="n">BOOST_MPL_HAS_XXX_TRAIT_DEF</span><span class="p">(</span><span class="n">another_type</span><span class="p">)</span> <span class="p">}</span> <span class="k">namespace</span> <span class="n">two</span> <span class="p">{</span> <span class="n">BOOST_MPL_HAS_XXX_TRAIT_DEF</span><span class="p">(</span><span class="n">result_type</span><span class="p">)</span> <span class="p">}</span> </pre></div></div><p> Namespace two's <code>has_result_type</code> actually ends up testing for the presence of <code>another_type</code> rather than <code>result_type</code>. If the declarations in namespace one are reordered so that result_type trait is last, then the namespace two trait works as expected. </p> <p> I wrote a basic sfinae trait-check implementation myself which worked ok. Maybe something similar could be used for msvc71 in the mpl? </p> <p> If the following code is compiled with -DUSE_MPL_TRAIT_DEF then the mpl is used, otherwise my own implementation is used. </p> <div class="wiki-code"><div class="code"><pre> <span class="cp">#if USE_MPL_TRAIT_DEF</span> <span class="cp">#define SELECTIVE_HAS_XXX_TRAIT_DEF BOOST_MPL_HAS_XXX_TRAIT_DEF</span> <span class="cp">#include</span> <span class="cpf">&lt;boost/mpl/has_xxx.hpp&gt;</span><span class="cp"></span> <span class="cp">#else</span> <span class="cp">#define SELECTIVE_HAS_XXX_TRAIT_DEF MY_HAS_XXX_TRAIT_DEF</span> <span class="cp">#define MY_HAS_XXX_TRAIT_DEF( trait ) \</span> <span class="cp"> template &lt;class T&gt; \</span> <span class="cp"> struct has_##trait \</span> <span class="cp"> { \</span> <span class="cp"> template &lt;typename U&gt; \</span> <span class="cp"> static char test( U const volatile*, typename U::trait* = 0 ); \</span> <span class="cp"> static long test( ... ); \</span> <span class="cp"> \</span> <span class="cp"> static const bool value = sizeof test( static_cast&lt;T*&gt;(0) ) == sizeof(char); \</span> <span class="cp"> }; \</span> <span class="cp">#endif</span> <span class="k">namespace</span> <span class="n">one</span> <span class="p">{</span> <span class="n">SELECTIVE_HAS_XXX_TRAIT_DEF</span><span class="p">(</span><span class="n">result_type</span><span class="p">)</span> <span class="n">SELECTIVE_HAS_XXX_TRAIT_DEF</span><span class="p">(</span><span class="n">another_type</span><span class="p">)</span> <span class="p">}</span> <span class="k">namespace</span> <span class="n">two</span> <span class="p">{</span> <span class="c1">// This instantiation of msvc71_sfinae_helper in the msvc71</span> <span class="c1">// implementation has been seen before --- but its function is that</span> <span class="c1">// of the last trait def.</span> <span class="c1">// </span> <span class="c1">// This line has the effect of defining a &#39;has_result_type&#39; struct</span> <span class="c1">// that tests for &#39;another_type&#39; in msvc71.</span> <span class="c1">//</span> <span class="n">SELECTIVE_HAS_XXX_TRAIT_DEF</span><span class="p">(</span><span class="n">result_type</span><span class="p">)</span> <span class="p">}</span> <span class="k">template</span> <span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">test</span><span class="p">;</span> <span class="k">template</span> <span class="o">&lt;&gt;</span> <span class="k">struct</span> <span class="n">test</span><span class="o">&lt;</span><span class="nb">true</span><span class="o">&gt;</span> <span class="p">{};</span> <span class="k">struct</span> <span class="n">X</span> <span class="p">{</span> <span class="k">typedef</span> <span class="kt">int</span> <span class="n">result_type</span><span class="p">;</span> <span class="k">typedef</span> <span class="kt">int</span> <span class="n">another_type</span><span class="p">;</span> <span class="p">};</span> <span class="k">struct</span> <span class="n">Y</span> <span class="p">{</span> <span class="k">typedef</span> <span class="kt">int</span> <span class="n">result_type</span><span class="p">;</span> <span class="p">};</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">test</span><span class="o">&lt;</span> <span class="n">one</span><span class="o">::</span><span class="n">has_another_type</span><span class="o">&lt;</span> <span class="n">X</span> <span class="o">&gt;::</span><span class="n">value</span> <span class="o">&gt;</span><span class="p">();</span> <span class="n">test</span><span class="o">&lt;</span> <span class="n">one</span><span class="o">::</span><span class="n">has_result_type</span><span class="o">&lt;</span> <span class="n">X</span> <span class="o">&gt;::</span><span class="n">value</span> <span class="o">&gt;</span><span class="p">();</span> <span class="c1">// this works but is actual testing for &#39;another_type&#39;!!!</span> <span class="n">test</span><span class="o">&lt;</span> <span class="n">two</span><span class="o">::</span><span class="n">has_result_type</span><span class="o">&lt;</span> <span class="n">X</span> <span class="o">&gt;::</span><span class="n">value</span> <span class="o">&gt;</span><span class="p">();</span> <span class="c1">// this fails as it doesn&#39;t have &#39;another_type&#39;</span> <span class="n">test</span><span class="o">&lt;</span> <span class="n">two</span><span class="o">::</span><span class="n">has_result_type</span><span class="o">&lt;</span> <span class="n">Y</span> <span class="o">&gt;::</span><span class="n">value</span> <span class="o">&gt;</span><span class="p">();</span> <span class="p">}</span> </pre></div></div> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/1916 Trac 1.4.3