| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> |
| <title>Concepts in Depth</title> |
| <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.78.1"> |
| <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> |
| <link rel="up" href="../boost_typeerasure.html" title="Chapter 33. Boost.TypeErasure"> |
| <link rel="prev" href="multi.html" title="Functions with Multiple Arguments"> |
| <link rel="next" href="any.html" title="Using Any"> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
| <table cellpadding="2" width="100%"><tr> |
| <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> |
| <td align="center"><a href="../../../index.html">Home</a></td> |
| <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> |
| <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> |
| <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> |
| <td align="center"><a href="../../../more/index.htm">More</a></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="multi.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../boost_typeerasure.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="any.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h2 class="title" style="clear: both"> |
| <a name="boost_typeerasure.concept"></a><a class="link" href="concept.html" title="Concepts in Depth">Concepts in Depth</a> |
| </h2></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="concept.html#boost_typeerasure.concept.custom">Defining Custom Concepts</a></span></dt> |
| <dt><span class="section"><a href="concept.html#boost_typeerasure.concept.overload">Overloading</a></span></dt> |
| <dt><span class="section"><a href="concept.html#boost_typeerasure.concept.concept_map">Concept Maps</a></span></dt> |
| <dt><span class="section"><a href="concept.html#boost_typeerasure.concept.overload0">Associated Types</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="boost_typeerasure.concept.custom"></a><a class="link" href="concept.html#boost_typeerasure.concept.custom" title="Defining Custom Concepts">Defining Custom Concepts</a> |
| </h3></div></div></div> |
| <p> |
| (For the source of the examples in this section see <a href="../../../libs/type_erasure/example/custom.cpp" target="_top">custom.cpp</a>) |
| </p> |
| <p> |
| Earlier, we used <code class="computeroutput"><a class="link" href="../BOOST_TYPE_ERASURE_MEMBER.html" title="Macro BOOST_TYPE_ERASURE_MEMBER">BOOST_TYPE_ERASURE_MEMBER</a></code> |
| to define a concept for containers that support <code class="computeroutput"><span class="identifier">push_back</span></code>. |
| Sometimes this interface isn't flexible enough, however. The library also |
| provides a lower level interface that gives full control of the behavior. |
| Let's take a look at what we would need in order to define <code class="computeroutput"><span class="identifier">has_push_back</span><span class="special">.</span></code> |
| First, we need to define the <code class="computeroutput"><span class="identifier">has_push_back</span></code> |
| template itself. We'll give it two template parameters, one for the container |
| and one for the element type. This template must have a static member function |
| called apply which is used to execute the operation. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">has_push_back</span> |
| <span class="special">{</span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">C</span><span class="special">&</span> <span class="identifier">cont</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">arg</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">cont</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">arg</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Now, we can use this in an <code class="computeroutput">any</code> |
| using <code class="computeroutput"><a class="link" href="../boost/type_erasure/call_idp304107712.html" title="Function call">call</a></code> to |
| dispatch the operation. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">vec</span><span class="special">;</span> |
| <span class="identifier">any</span><span class="special"><</span><span class="identifier">has_push_back</span><span class="special"><</span><span class="identifier">_self</span><span class="special">,</span> <span class="keyword">int</span><span class="special">>,</span> <span class="identifier">_self</span><span class="special">&></span> <span class="identifier">c</span><span class="special">(</span><span class="identifier">vec</span><span class="special">);</span> |
| <span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> |
| <span class="identifier">call</span><span class="special">(</span><span class="identifier">has_push_back</span><span class="special"><</span><span class="identifier">_self</span><span class="special">,</span> <span class="keyword">int</span><span class="special">>(),</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">i</span><span class="special">);</span> |
| <span class="comment">// vec is [10].</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Our second task is to customize <code class="computeroutput">any</code> |
| so that we can call <code class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">10</span><span class="special">)</span></code>. We do |
| this by specializing <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code>. |
| The first argument is <code class="computeroutput"><span class="identifier">has_push_back</span></code>, |
| since we want to inject a member into every <code class="computeroutput">any</code> |
| that uses the <code class="computeroutput"><span class="identifier">has_push_back</span></code> |
| concept. The second argument, <code class="computeroutput"><span class="identifier">Base</span></code>, |
| is used by the library to chain multiple uses of <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| together. We have to inherit from it publicly. <code class="computeroutput"><span class="identifier">Base</span></code> |
| is also used to get access to the full <code class="computeroutput">any</code> |
| type. The third argument is the placeholder that represents this any. If |
| someone used <code class="computeroutput"><span class="identifier">push_back</span><span class="special"><</span><span class="identifier">_c</span><span class="special">,</span> <span class="identifier">_b</span><span class="special">></span></code>, we only want to insert a <code class="computeroutput"><span class="identifier">push_back</span></code> member in the container, not |
| the value type. Thus, the third argument is the container placeholder. |
| </p> |
| <p> |
| When we define <code class="computeroutput"><span class="identifier">push_back</span></code> |
| the argument type uses the metafunction <code class="computeroutput"><a class="link" href="../boost/type_erasure/as_param.html" title="Struct template as_param">as_param</a></code>. |
| This is just to handle the case where <code class="computeroutput"><span class="identifier">T</span></code> |
| is a placeholder. If <code class="computeroutput"><span class="identifier">T</span></code> is |
| not a placeholder, then the metafunction just returns its argument, <code class="computeroutput"><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span></code>, unchanged. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">type_erasure</span> <span class="special">{</span> |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Base</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">concept_interface</span><span class="special"><</span><span class="identifier">has_push_back</span><span class="special"><</span><span class="identifier">C</span><span class="special">,</span> <span class="identifier">T</span><span class="special">>,</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">C</span><span class="special">></span> <span class="special">:</span> <span class="identifier">Base</span> |
| <span class="special">{</span> |
| <span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">as_param</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">T</span><span class="special">&>::</span><span class="identifier">type</span> <span class="identifier">arg</span><span class="special">)</span> |
| <span class="special">{</span> <span class="identifier">call</span><span class="special">(</span><span class="identifier">has_push_back</span><span class="special"><</span><span class="identifier">C</span><span class="special">,</span> <span class="identifier">T</span><span class="special">>(),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">arg</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">};</span> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Our example now becomes |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">vec</span><span class="special">;</span> |
| <span class="identifier">any</span><span class="special"><</span><span class="identifier">has_push_back</span><span class="special"><</span><span class="identifier">_self</span><span class="special">,</span> <span class="keyword">int</span><span class="special">>,</span> <span class="identifier">_self</span><span class="special">&></span> <span class="identifier">c</span><span class="special">(</span><span class="identifier">vec</span><span class="special">);</span> |
| <span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">10</span><span class="special">);</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| which is what we want. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="boost_typeerasure.concept.overload"></a><a class="link" href="concept.html#boost_typeerasure.concept.overload" title="Overloading">Overloading</a> |
| </h3></div></div></div> |
| <p> |
| (For the source of the examples in this section see <a href="../../../libs/type_erasure/example/overload.cpp" target="_top">overload.cpp</a>) |
| </p> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| allows us to inject arbitrary declarations into an <code class="computeroutput">any</code>. |
| This is very flexible, but there are some pitfalls to watch out for. Sometimes |
| we want to use the same concept several times with different parameters. |
| Specializing <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| in a way that handles overloads correctly is a bit tricky. Given a concept |
| foo, we'd like the following to work: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="identifier">any</span><span class="special"><</span> |
| <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> |
| <span class="identifier">foo</span><span class="special"><</span><span class="identifier">_self</span><span class="special">,</span> <span class="keyword">int</span><span class="special">>,</span> |
| <span class="identifier">foo</span><span class="special"><</span><span class="identifier">_self</span><span class="special">,</span> <span class="keyword">double</span><span class="special">>,</span> |
| <span class="identifier">copy_constructible</span><span class="special"><></span> |
| <span class="special">></span> |
| <span class="special">></span> <span class="identifier">x</span> <span class="special">=</span> <span class="special">...;</span> |
| <span class="identifier">x</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// calls foo(int)</span> |
| <span class="identifier">x</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(</span><span class="number">1.0</span><span class="special">);</span> <span class="comment">// calls foo(double)</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Because <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| creates a linear inheritance chain, without some extra work, one overload |
| of foo will hide the other. |
| </p> |
| <p> |
| Here are the techniques that I found work reliably. |
| </p> |
| <p> |
| For member functions I couldn't find a way to avoid using two specializations. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">foo</span> |
| <span class="special">{</span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">t</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">U</span><span class="special">&</span> <span class="identifier">u</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">t</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(</span><span class="identifier">u</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">type_erasure</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Base</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Enable</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">concept_interface</span><span class="special"><</span> <span class="special">::</span><span class="identifier">foo</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>,</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">Enable</span><span class="special">></span> <span class="special">:</span> <span class="identifier">Base</span> |
| <span class="special">{</span> |
| <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">_fun_defined</span><span class="special">;</span> |
| <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">as_param</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">U</span><span class="special">&>::</span><span class="identifier">type</span> <span class="identifier">arg</span><span class="special">)</span> |
| <span class="special">{</span> |
| <span class="identifier">call</span><span class="special">(::</span><span class="identifier">foo</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>(),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">arg</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Base</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">concept_interface</span><span class="special"><</span> <span class="special">::</span><span class="identifier">foo</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>,</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">_fun_defined</span><span class="special">></span> <span class="special">:</span> <span class="identifier">Base</span> |
| <span class="special">{</span> |
| <span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">foo</span><span class="special">;</span> |
| <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">as_param</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">U</span><span class="special">&>::</span><span class="identifier">type</span> <span class="identifier">arg</span><span class="special">)</span> |
| <span class="special">{</span> |
| <span class="identifier">call</span><span class="special">(::</span><span class="identifier">foo</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>(),</span> <span class="special">*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">arg</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="special">}</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| This uses SFINAE to detect whether a using declaration is needed. Note that |
| the fourth argument of <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| is a dummy parameter which is always void and is intended to be used for |
| SFINAE. Another solution to the problem that I've used in the past is to |
| inject a dummy declaration of <code class="computeroutput"><span class="identifier">fun</span></code> |
| and always put in a using declaration. This is an inferior solution for several |
| reasons. It requires an extra interface to add the dummy overload. It also |
| means that <code class="computeroutput"><span class="identifier">fun</span></code> is always |
| overloaded, even if the user only asked for one overload. This makes it harder |
| to take the address of fun. |
| </p> |
| <p> |
| Note that while using SFINAE requires some code to be duplicated, the amount |
| of code that has to be duplicated is relatively small, since the implementation |
| of <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| is usually a one liner. It's a bit annoying, but I believe it's an acceptable |
| cost in lieu of a better solution. |
| </p> |
| <p> |
| For free functions you can use inline friends. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">bar_concept</span> |
| <span class="special">{</span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">t</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">U</span><span class="special">&</span> <span class="identifier">u</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">bar</span><span class="special">(</span><span class="identifier">t</span><span class="special">,</span> <span class="identifier">u</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">type_erasure</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Base</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">concept_interface</span><span class="special"><</span> <span class="special">::</span><span class="identifier">bar_concept</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>,</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">T</span><span class="special">></span> <span class="special">:</span> <span class="identifier">Base</span> |
| <span class="special">{</span> |
| <span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">bar</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">derived</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>::</span><span class="identifier">type</span><span class="special">&</span> <span class="identifier">t</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">as_param</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">U</span><span class="special">&>::</span><span class="identifier">type</span> <span class="identifier">u</span><span class="special">)</span> |
| <span class="special">{</span> |
| <span class="identifier">call</span><span class="special">(::</span><span class="identifier">bar_concept</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>(),</span> <span class="identifier">t</span><span class="special">,</span> <span class="identifier">u</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Base</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">concept_interface</span><span class="special"><</span> <span class="special">::</span><span class="identifier">bar_concept</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>,</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">disable_if</span><span class="special"><</span><span class="identifier">is_placeholder</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>::</span><span class="identifier">type</span><span class="special">></span> <span class="special">:</span> <span class="identifier">Base</span> |
| <span class="special">{</span> |
| <span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">bar</span><span class="special">;</span> |
| <span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">bar</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">t</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">typename</span> <span class="identifier">derived</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>::</span><span class="identifier">type</span><span class="special">&</span> <span class="identifier">u</span><span class="special">)</span> |
| <span class="special">{</span> |
| <span class="identifier">call</span><span class="special">(::</span><span class="identifier">bar_concept</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">U</span><span class="special">>(),</span> <span class="identifier">t</span><span class="special">,</span> <span class="identifier">u</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="special">}</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Basically we have to specialize <code class="computeroutput"><a class="link" href="../boost/type_erasure/concept_interface.html" title="Struct template concept_interface">concept_interface</a></code> |
| once for each argument to make sure that an overload is injected into the |
| first argument that's a placeholder. As you might have noticed, the argument |
| types are a bit tricky. In the first specialization, the first argument uses |
| <code class="computeroutput"><a class="link" href="../boost/type_erasure/derived.html" title="Struct template derived">derived</a></code> instead |
| of <code class="computeroutput"><a class="link" href="../boost/type_erasure/as_param.html" title="Struct template as_param">as_param</a></code>. The |
| reason for this is that if we used <code class="computeroutput"><a class="link" href="../boost/type_erasure/as_param.html" title="Struct template as_param">as_param</a></code>, |
| then we could end up violating the one definition rule by defining the same |
| function twice. Similarly, we use SFINAE in the second specialization to |
| make sure that bar is only defined once when both arguments are placeholders. |
| It's possible to merge the two specializations with a bit of metaprogramming, |
| but unless you have a lot of arguments, it's probably not worth while. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="boost_typeerasure.concept.concept_map"></a><a class="link" href="concept.html#boost_typeerasure.concept.concept_map" title="Concept Maps">Concept Maps</a> |
| </h3></div></div></div> |
| <p> |
| (For the source of the examples in this section see <a href="../../../libs/type_erasure/example/concept_map.cpp" target="_top">concept_map.cpp</a>) |
| </p> |
| <p> |
| Sometimes it is useful to non-intrusively adapt a type to model a concept. |
| For example, suppose that we want to make <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">type_info</span></code> |
| model <code class="computeroutput"><a class="link" href="../boost/type_erasure/less_than_comparable.html" title="Struct template less_than_comparable">less_than_comparable</a></code>. |
| To do this, we simply specialize the concept definition. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">type_erasure</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><></span> |
| <span class="keyword">struct</span> <span class="identifier">less_than_comparable</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">type_info</span><span class="special">></span> |
| <span class="special">{</span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">apply</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">type_info</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">type_info</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span> |
| <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">lhs</span><span class="special">.</span><span class="identifier">before</span><span class="special">(</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">!=</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span> |
| <span class="special">};</span> |
| |
| <span class="special">}</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <div class="note"><table border="0" summary="Note"> |
| <tr> |
| <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td> |
| <th align="left">Note</th> |
| </tr> |
| <tr><td align="left" valign="top"><p> |
| Most, but not all of the builtin concepts can be specialized. Constructors, |
| destructors, and RTTI need special treatment from the library and cannot |
| be specialized. Only primitive concepts can be specialized, so the iterator |
| concepts are also out. |
| </p></td></tr> |
| </table></div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="boost_typeerasure.concept.overload0"></a><a class="link" href="concept.html#boost_typeerasure.concept.overload0" title="Associated Types">Associated Types</a> |
| </h3></div></div></div> |
| <p> |
| (For the source of the examples in this section see <a href="../../../libs/type_erasure/example/associated.cpp" target="_top">associated.cpp</a>) |
| </p> |
| <p> |
| Associated types such as <code class="computeroutput"><span class="keyword">typename</span> |
| <span class="identifier">T</span><span class="special">::</span><span class="identifier">value_type</span></code> or <code class="computeroutput"><span class="keyword">typename</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">iterator_traits</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">reference</span></code> are quite common in template |
| programming. Boost.TypeErasure handles them using the <code class="computeroutput"><a class="link" href="../boost/type_erasure/deduced.html" title="Struct template deduced">deduced</a></code> |
| template. <code class="computeroutput"><a class="link" href="../boost/type_erasure/deduced.html" title="Struct template deduced">deduced</a></code> |
| is just like an ordinary <code class="computeroutput"><a class="link" href="../boost/type_erasure/placeholder.html" title="Struct placeholder">placeholder</a></code>, |
| except that the type that it binds to is determined by calling a metafunction |
| and does not need to be specified explicitly. |
| </p> |
| <p> |
| For example, we can define a concept for holding an iterator, raw pointer, |
| or smart pointer as follows. First, we define a metafunction called <code class="computeroutput"><span class="identifier">pointee</span></code> defining the associated type. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">pointee</span> |
| <span class="special">{</span> |
| <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">eval_if</span><span class="special"><</span><span class="identifier">is_placeholder</span><span class="special"><</span><span class="identifier">T</span><span class="special">>,</span> |
| <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">identity</span><span class="special"><</span><span class="keyword">void</span><span class="special">>,</span> |
| <span class="identifier">boost</span><span class="special">::</span><span class="identifier">pointee</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> |
| <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">type</span><span class="special">;</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Note that we can't just use <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">pointee</span></code>, |
| because this metafunction needs to be safe to instantiate with placeholders. |
| It doesn't matter what it returns as long as it doesn't give an error. (The |
| library never tries to instantiate it with a placeholder, but argument dependent |
| lookup can cause spurious instantiations.) |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span> <span class="special">=</span> <span class="identifier">_self</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">pointer</span> <span class="special">:</span> |
| <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> |
| <span class="identifier">copy_constructible</span><span class="special"><</span><span class="identifier">T</span><span class="special">>,</span> |
| <span class="identifier">dereferenceable</span><span class="special"><</span><span class="identifier">deduced</span><span class="special"><</span><span class="identifier">pointee</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>&,</span> <span class="identifier">T</span><span class="special">></span> |
| <span class="special">></span> |
| <span class="special">{</span> |
| <span class="comment">// provide a typedef for convenience</span> |
| <span class="keyword">typedef</span> <span class="identifier">deduced</span><span class="special"><</span><span class="identifier">pointee</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span> <span class="identifier">element_type</span><span class="special">;</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Now the Concept of <code class="computeroutput"><span class="identifier">x</span></code> uses |
| two placeholders, <code class="computeroutput"><span class="identifier">_self</span></code> and |
| <code class="computeroutput"><span class="identifier">pointer</span><span class="special"><>::</span><span class="identifier">element_type</span></code>. When we construct <code class="computeroutput"><span class="identifier">x</span></code>, with an <code class="computeroutput"><span class="keyword">int</span><span class="special">*</span></code>, <code class="computeroutput"><span class="identifier">pointer</span><span class="special"><>::</span><span class="identifier">element_type</span></code> |
| is deduced as <code class="computeroutput"><span class="identifier">pointee</span><span class="special"><</span><span class="keyword">int</span><span class="special">*>::</span><span class="identifier">type</span></code> which is <code class="computeroutput"><span class="keyword">int</span></code>. |
| Thus, dereferencing <code class="computeroutput"><span class="identifier">x</span></code> returns |
| an <code class="computeroutput">any</code> that contains |
| an <code class="computeroutput"><span class="keyword">int</span></code>. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> |
| <span class="identifier">any</span><span class="special"><</span> |
| <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> |
| <span class="identifier">pointer</span><span class="special"><>,</span> |
| <span class="identifier">typeid_</span><span class="special"><</span><span class="identifier">pointer</span><span class="special"><>::</span><span class="identifier">element_type</span><span class="special">></span> |
| <span class="special">></span> |
| <span class="special">></span> <span class="identifier">x</span><span class="special">(&</span><span class="identifier">i</span><span class="special">);</span> |
| <span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="identifier">any_cast</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(*</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// j == i</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Sometimes we want to require that the associated type be a specific type. |
| This can be solved using the <code class="computeroutput"><a class="link" href="../boost/type_erasure/same_type.html" title="Struct template same_type">same_type</a></code> |
| concept. Here we create an any that can hold any pointer whose element type |
| is <code class="computeroutput"><span class="keyword">int</span></code>. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> |
| <span class="identifier">any</span><span class="special"><</span> |
| <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> |
| <span class="identifier">pointer</span><span class="special"><>,</span> |
| <span class="identifier">same_type</span><span class="special"><</span><span class="identifier">pointer</span><span class="special"><>::</span><span class="identifier">element_type</span><span class="special">,</span> <span class="keyword">int</span><span class="special">></span> |
| <span class="special">></span> |
| <span class="special">></span> <span class="identifier">x</span><span class="special">(&</span><span class="identifier">i</span><span class="special">);</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="special">*</span><span class="identifier">x</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> <span class="comment">// prints 10</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Using <code class="computeroutput"><a class="link" href="../boost/type_erasure/same_type.html" title="Struct template same_type">same_type</a></code> |
| like this effectively causes the library to replace all uses of <code class="computeroutput"><span class="identifier">pointer</span><span class="special"><>::</span><span class="identifier">element_type</span></code> with <code class="computeroutput"><span class="keyword">int</span></code> |
| and validate that it is always bound to <code class="computeroutput"><span class="keyword">int</span></code>. |
| Thus, dereferencing <code class="computeroutput"><span class="identifier">x</span></code> now |
| returns an <code class="computeroutput"><span class="keyword">int</span></code>. |
| </p> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/type_erasure/same_type.html" title="Struct template same_type">same_type</a></code> can |
| also be used for two placeholders. This allows us to use a simple name instead |
| of writing out an associated type over and over. |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">10</span><span class="special">;</span> |
| <span class="identifier">any</span><span class="special"><</span> |
| <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> |
| <span class="identifier">pointer</span><span class="special"><>,</span> |
| <span class="identifier">same_type</span><span class="special"><</span><span class="identifier">pointer</span><span class="special"><>::</span><span class="identifier">element_type</span><span class="special">,</span> <span class="identifier">_a</span><span class="special">>,</span> |
| <span class="identifier">typeid_</span><span class="special"><</span><span class="identifier">_a</span><span class="special">>,</span> |
| <span class="identifier">copy_constructible</span><span class="special"><</span><span class="identifier">_a</span><span class="special">>,</span> |
| <span class="identifier">addable</span><span class="special"><</span><span class="identifier">_a</span><span class="special">>,</span> |
| <span class="identifier">ostreamable</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">,</span> <span class="identifier">_a</span><span class="special">></span> |
| <span class="special">></span> |
| <span class="special">></span> <span class="identifier">x</span><span class="special">(&</span><span class="identifier">i</span><span class="special">);</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="special">(*</span><span class="identifier">x</span> <span class="special">+</span> <span class="special">*</span><span class="identifier">x</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> <span class="comment">// prints 20</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> |
| <td align="left"></td> |
| <td align="right"><div class="copyright-footer">Copyright © 2011-2013 Steven Watanabe<p> |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| </div></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="multi.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../boost_typeerasure.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="any.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| </body> |
| </html> |