incomplete-support-for.html 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  4. <!-- Copyright Aleksey Gurtovoy 2006. Distributed under the Boost -->
  5. <!-- Software License, Version 1.0. (See accompanying -->
  6. <!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
  7. <head>
  8. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  9. <meta name="generator" content="Docutils 0.3.6: http://docutils.sourceforge.net/" />
  10. <title>THE BOOST MPL LIBRARY: Incomplete Support for Lambda Expressions</title>
  11. <link rel="stylesheet" href="../style.css" type="text/css" />
  12. </head>
  13. <body class="docframe">
  14. <table class="header"><tr class="header"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./broken-integral-constant.html" class="navigation-link">Prev</a>&nbsp;<a href="./eti.html" class="navigation-link">Next</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./broken-integral-constant.html" class="navigation-link">Back</a>&nbsp;<a href="./eti.html" class="navigation-link">Along</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./portability.html" class="navigation-link">Up</a>&nbsp;<a href="../index.html" class="navigation-link">Home</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./tutorial_toc.html" class="navigation-link">Full TOC</a></span></td>
  15. <td class="header-group page-location"><a href="../index.html" class="navigation-link">Front Page</a> / <a href="./technical-details.html" class="navigation-link">Technical Details</a> / <a href="./portability.html" class="navigation-link">Portability</a> / <a href="./incomplete-support-for.html" class="navigation-link">Incomplete Support for Lambda Expressions</a></td>
  16. </tr></table><div class="header-separator"></div>
  17. <div class="section" id="incomplete-support-for">
  18. <h1><a class="toc-backref" href="./portability.html#id75" name="incomplete-support-for">Incomplete Support for Lambda Expressions</a></h1>
  19. <p>Seasoned MPL users will agree with us that if there is
  20. anything in the MPL that is seemingly magical both in power and
  21. its nature, then it's MPL lambda expressions. In reality, the
  22. mechanism that bring this to life is very straightforward and
  23. probably can be explained to anyone generally familiar with C++
  24. templates in less than 10 minutes.</p>
  25. <!-- People are going to hate you for saying so and not actually -->
  26. <!-- explaining it. -->
  27. <p>Unfortunately, this mechanism also happens to rely on support for
  28. partial template specialization and template template parameters.
  29. Among the so-called deficient compilers — basically, most of the
  30. compilers released before the year 2000 — the chances are poor
  31. that you'll find <em>complete</em> support for <em>both</em> of these features.
  32. Please see our <a class="reference" href="./portability.html#compatibility-table">compatibility table</a> for the list of the products
  33. which fall into this category.</p>
  34. <p>Although it's not possible to implement <em>fully transparent</em> lambda
  35. expressions without these two features, a slightly more limited
  36. implementation that requires some manual assistance from the
  37. metafunction author is possible. This section describes the manual
  38. work required and the limitations of the result.</p>
  39. <div class="section" id="incomplete-the-problem">
  40. <h2><a name="incomplete-the-problem">The Problem</a></h2>
  41. <p>If your compiler falls into the &quot;deficient&quot; category, the following
  42. valid MPL metaprogram will fail to compile for you:</p>
  43. <pre class="literal-block">
  44. #include &lt;boost/mpl/apply.hpp&gt;
  45. using namespace boost::mpl;
  46. template&lt; typename T &gt; struct add_const
  47. {
  48. typedef T const type;
  49. };
  50. typedef apply1&lt; add_const&lt;_1&gt;,int &gt;::type t; // t == int const
  51. </pre>
  52. <p>Worse yet, chances are it wil fail with a diagnostic backtrace
  53. leading you into the inside of the library and possibly creating an
  54. impression that there's something's wrong there. The fact is, both
  55. the program and the library are defect free (for the
  56. purpose of this particular demonstraction), and it's your compiler
  57. that is to blame.</p>
  58. </div>
  59. <div class="section" id="incomplete-the-solution">
  60. <h2><a name="incomplete-the-solution">The Solution</a></h2>
  61. <p>As previously mentioned, the solution requires some work from
  62. metafunction authors, but for the users of those metafunctions, the
  63. result is relatively transparent. Here's what we have to do to our
  64. earlier example:</p>
  65. <pre class="literal-block">
  66. #include &lt;boost/mpl/apply.hpp&gt;
  67. <strong>#include &lt;boost/mpl/aux_/lambda_support.hpp&gt;</strong>
  68. using namespace boost::mpl;
  69. template&lt; typename T &gt; struct add_const
  70. {
  71. typedef T const type;
  72. <strong>BOOST_MPL_AUX_LAMBDA_SUPPORT(1, add_const, (T))</strong>
  73. };
  74. typedef apply1&lt; add_const&lt;_1&gt;,int &gt;::type t; // t == int const
  75. </pre>
  76. <p>With these two modifications, now the compiler that has been barking at us now
  77. happily accepts it. &quot;Hey, that's not that bad at all!&quot; you might say. Just put a
  78. little macro inside and be happy again.</p>
  79. </div>
  80. <div class="section" id="limitations">
  81. <h2><a name="limitations">Limitations</a></h2>
  82. <p>Unfortunately, that's not quite the end of the story. There are
  83. still cases where the above approach will fail and we will have to
  84. resort to writing out-of-line metafunction class. Here are the
  85. details:</p>
  86. <blockquote>
  87. <p>To make the lambda expression work without partial template
  88. specialization and
  89. template template parameters, the MPL has to implement some other way of
  90. pulling apart the template instantiations' expression tree, and the only way
  91. to do it is through an intrusive metafunction introspection
  92. mechanism. That's what hidden behind the <tt class="literal"><span class="pre">BOOST_MPL_AUX_LAMBDA_SUPPORT</span></tt> macro
  93. we've seen above.</p>
  94. <p>But then, after we've got the information we need (the metafunction's arity
  95. and its exact template arguments) stored inside the metafunction itself,
  96. the only way for the library to access it is to look inside the metafunction.
  97. The latter, in its turn, means instantiating the metafunction, prematurely,
  98. before the actuall call, <em>with one or more placeholder arguments</em>. This last
  99. part is a potential problem.</p>
  100. </blockquote>
  101. <p>In other words, the mechanism works as long as your metafunction is
  102. &quot;placeholder-safe&quot; (can be safely instantiated on placeholder
  103. arguments), which comes down to the follwing two criteria:</p>
  104. <ol class="arabic simple">
  105. <li>The metafunction doesn't access its arguments' nested members, or</li>
  106. <li>The only accessed members are types named <tt class="literal"><span class="pre">::tag</span></tt> or <tt class="literal"><span class="pre">::type</span></tt> (the
  107. placeholders do contain these).</li>
  108. </ol>
  109. <p>If these two hold, you can safely put <tt class="literal"><span class="pre">BOOST_MPL_AUX_LAMBDA_SUPPORT</span></tt> inside
  110. your metafunction and forget about the issue. If not, you are out of luck and
  111. probably have to write a metafunction class instead.</p>
  112. <p>The good news are that most of the MPL's own metafunctions and <a class="reference" href="../../../type_traits/index.html" target="_top">Boost.Type Traits</a>
  113. templates are &quot;placeholder-safe&quot; and have the workaround applied to them, so
  114. even on broken compilers things &quot;just work&quot; in about 90% of use cases.</p>
  115. <p>Please refer to the MPL <a class="reference" href="./reference-manual.html">reference manual</a> for the details on the
  116. <tt class="literal"><span class="pre">BOOST_MPL_AUX_LAMBDA_SUPPORT</span></tt> macro.</p>
  117. </div>
  118. </div>
  119. <div class="footer-separator"></div>
  120. <table class="footer"><tr class="footer"><td class="header-group navigation-bar"><span class="navigation-group"><a href="./broken-integral-constant.html" class="navigation-link">Prev</a>&nbsp;<a href="./eti.html" class="navigation-link">Next</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./broken-integral-constant.html" class="navigation-link">Back</a>&nbsp;<a href="./eti.html" class="navigation-link">Along</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./portability.html" class="navigation-link">Up</a>&nbsp;<a href="../index.html" class="navigation-link">Home</a></span><span class="navigation-group-separator">&nbsp;|&nbsp;</span><span class="navigation-group"><a href="./tutorial_toc.html" class="navigation-link">Full TOC</a></span></td>
  121. </tr></table></body>
  122. </html>