mirror of
https://github.com/boostorg/callable_traits.git
synced 2026-01-28 07:02:13 +00:00
957 lines
146 KiB
HTML
957 lines
146 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
|
<title>Example: Java-style interfaces without inheritance</title>
|
|
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
|
<link rel="home" href="index.html" title="CallableTraits">
|
|
<link rel="up" href="index.html" title="CallableTraits">
|
|
<link rel="prev" href="callable_traits/example_std_function_sugar.html" title="Example: std::function sugar">
|
|
<link rel="next" href="callable_traits/contact.html" title="Contact">
|
|
</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="callable_traits/example_std_function_sugar.html"><img src="../src/images/prev.png" alt="Prev"></a><a accesskey="u" href="index.html"><img src="../src/images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="../src/images/home.png" alt="Home"></a><a accesskey="n" href="callable_traits/contact.html"><img src="../src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
<div lang="en" class="article">
|
|
<div class="titlepage">
|
|
<div>
|
|
<div><h2 class="title">
|
|
<a name="callable_traits_interface_example"></a>Example: Java-style interfaces without inheritance</h2></div>
|
|
<div><div class="authorgroup">
|
|
<div class="author"><h3 class="author">
|
|
<span class="firstname">Barrett</span> <span class="surname">Adair</span>
|
|
</h3></div>
|
|
<div class="author"><h3 class="author">
|
|
<span class="firstname">Tobias</span> <span class="surname">Schwinger</span>
|
|
</h3></div>
|
|
</div></div>
|
|
<div><p class="copyright">Copyright © 2016 (Modified Work) Barrett Adair</p></div>
|
|
<div><p class="copyright">Copyright © 2007 Tobias Schwinger</p></div>
|
|
<div><div class="legalnotice">
|
|
<a name="callable_traits_interface_example.legal"></a><p>
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE.md 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></div>
|
|
</div>
|
|
<hr>
|
|
</div>
|
|
<h3>
|
|
<a name="callable_traits_interface_example.h0"></a>
|
|
<span class="phrase"><a name="callable_traits_interface_example.explanation"></a></span><a class="link" href="callable_traits_interface_example.html#callable_traits_interface_example.explanation">Explanation</a>
|
|
</h3>
|
|
<div class="note"><table border="0" summary="Note">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../src/images/note.png"></td>
|
|
<th align="left">Note</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
This example is based on the <a href="http://www.boost.org/doc/libs/1_60_0/libs/function_types/example/interface.hpp" target="_top">Boost.FunctionTypes
|
|
interface example.</a>
|
|
</p></td></tr>
|
|
</table></div>
|
|
<p>
|
|
An interface is a collection of member function prototypes that may be implemented
|
|
by classes. Objects of classes that implement the interface can then be assigned
|
|
to an interface variable through which the interface's functions can be called.
|
|
</p>
|
|
<p>
|
|
Interfaces are a <a href="https://en.wikipedia.org/wiki/Interface_(Java)" target="_top">feature
|
|
of the Java programming language</a>. The most obvious way to model an
|
|
interface in C++ is to define a pure abstract base class. However, the inheritance
|
|
approach is neither the most efficient, nor the most flexible solution. Inheritance-based
|
|
interfaces have the following drawbacks:
|
|
</p>
|
|
<div class="orderedlist"><ol class="orderedlist" type="1">
|
|
<li class="listitem">
|
|
All functions must be virtual
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
a function that calls another function of the interface must do so
|
|
via virtual dispatch (as opposed to inlining)
|
|
</li>
|
|
<li class="listitem">
|
|
a class can not implement an interface's (overloaded) function via
|
|
a function template
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
<li class="listitem">
|
|
Inheritance is intrusive
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
object size increases
|
|
</li>
|
|
<li class="listitem">
|
|
clients are always polymorphic
|
|
</li>
|
|
<li class="listitem">
|
|
dependencies cause tighter coupling
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ol></div>
|
|
<p>
|
|
Fortunately, it is possible to eliminate all the drawbacks mentioned above
|
|
based on an alternative implementation using template metaprogramming, preprocessor
|
|
metaprogramming, and type erasure techniques. In this example, we will use
|
|
<code class="computeroutput"><span class="identifier">CallableTraits</span></code> and the <a href="http://www.boost.org/doc/libs/1_60_0/libs/preprocessor/doc/index.html" target="_top">Boost.Preprocessor
|
|
library</a> to create a macro which is used to define Java-style interfaces
|
|
<span class="bold"><strong>that can be retroactively applied to any object, with
|
|
no performance lost versus inheritance polymorphism</strong></span>. The macro is
|
|
used like this:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">DEFINE_INTERFACE</span><span class="special">(</span> <span class="identifier">interface_x</span><span class="special">,</span>
|
|
<span class="special">((</span> <span class="identifier">a_func</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">))</span>
|
|
<span class="special">((</span> <span class="identifier">a_func</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="keyword">long</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">))</span>
|
|
<span class="special">((</span> <span class="identifier">another_func</span><span class="special">,</span> <span class="keyword">int</span><span class="special">()</span> <span class="special">))</span>
|
|
<span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
This loosely corresponds to the following Java code:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">public</span> <span class="identifier">interface</span> <span class="identifier">interface_x</span> <span class="special">{</span>
|
|
<span class="keyword">void</span> <span class="identifier">a_func</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">);</span>
|
|
<span class="keyword">void</span> <span class="identifier">a_func</span><span class="special">(</span><span class="keyword">long</span> <span class="identifier">x</span><span class="special">);</span>
|
|
<span class="keyword">int</span> <span class="identifier">another_func</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
The <code class="computeroutput"><span class="identifier">DEFINE_INTERFACE</span></code> macro
|
|
is applied to object instances, rather than class definitions. This allows
|
|
the interfacing of objects whose definitions are not accessible to the programmer.
|
|
All constraints are still checked at compile time. This example implementation
|
|
even accounts for member data, such as <code class="computeroutput"><span class="identifier">some_data</span></code>
|
|
below:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">DEFINE_INTERFACE</span><span class="special">(</span> <span class="identifier">interface_y</span><span class="special">,</span>
|
|
<span class="special">((</span> <span class="identifier">a_func</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">))</span>
|
|
<span class="special">((</span> <span class="identifier">some_data</span><span class="special">,</span> <span class="keyword">int</span> <span class="special">))</span>
|
|
<span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
A more fleshed-out implementation of this would be very useful to anyone using
|
|
OOP design patterns in C++, or to developers of generic APIs. Arguably, the
|
|
<code class="computeroutput"><span class="identifier">DEFINE_INTERFACE</span></code> macro is easier
|
|
than writing pure abstract base classes. However, this implementation is not
|
|
without drawbacks. To name a few:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
This example implementation lacks features for memory management and move
|
|
semantics
|
|
</li>
|
|
<li class="listitem">
|
|
No custom error messages
|
|
</li>
|
|
<li class="listitem">
|
|
No comparison operators are overloaded
|
|
</li>
|
|
<li class="listitem">
|
|
Suboptimal compile-time performance
|
|
</li>
|
|
<li class="listitem">
|
|
Inherited members cannot be used to implement the interface
|
|
</li>
|
|
<li class="listitem">
|
|
This example implementation has not been thoroughly tested
|
|
</li>
|
|
<li class="listitem">
|
|
This example does not build in on the following platforms:
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
|
|
<li class="listitem">
|
|
MSVC
|
|
</li>
|
|
<li class="listitem">
|
|
GCC < 4.9.2
|
|
</li>
|
|
<li class="listitem">
|
|
Clang < 3.7
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
<h3>
|
|
<a name="callable_traits_interface_example.h1"></a>
|
|
<span class="phrase"><a name="callable_traits_interface_example.usage"></a></span><a class="link" href="callable_traits_interface_example.html#callable_traits_interface_example.usage">Usage</a>
|
|
</h3>
|
|
<p>
|
|
This short program shows how to use the example <code class="computeroutput"><span class="identifier">DEFINE_INTERFACE</span></code>
|
|
macro. The implementation can be found in the following section.
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="string">"interface.hpp"</span>
|
|
|
|
<span class="identifier">DEFINE_INTERFACE</span><span class="special">(</span><span class="identifier">interface_x</span><span class="special">,</span>
|
|
<span class="special">((</span> <span class="identifier">a_func</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">))</span>
|
|
<span class="special">((</span> <span class="identifier">a_func</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="keyword">long</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">))</span>
|
|
<span class="special">((</span> <span class="identifier">another_func</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">some_data</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="special">))</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="comment">// two classes that implement interface_x</span>
|
|
<span class="keyword">struct</span> <span class="identifier">a_class</span> <span class="special">{</span>
|
|
<span class="keyword">void</span> <span class="identifier">a_func</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">v</span><span class="special">)</span> <span class="keyword">const</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="string">"a_class::void a_func(int v = "</span> <span class="special"><<</span> <span class="identifier">v</span> <span class="special"><<</span> <span class="string">")"</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="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">a_func</span><span class="special">(</span><span class="keyword">long</span> <span class="identifier">v</span><span class="special">)</span> <span class="keyword">const</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="string">"a_class::void a_func(long v = "</span> <span class="special"><<</span> <span class="identifier">v</span> <span class="special"><<</span> <span class="string">")"</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="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">another_func</span><span class="special">()</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="string">"a_class::another_func() = 3"</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="keyword">return</span> <span class="number">3</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">some_data</span> <span class="special">=</span> <span class="string">"a_class's data"</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">struct</span> <span class="identifier">another_class</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// Notice a_func is implemented as a function template? No problem for our interface.</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">a_func</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">v</span><span class="special">)</span> <span class="keyword">const</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="string">"another_class::void a_func(T v = "</span> <span class="special"><<</span> <span class="identifier">v</span> <span class="special"><<</span> <span class="string">")"</span>
|
|
<span class="string">" [ T = "</span> <span class="special"><<</span> <span class="keyword">typeid</span><span class="special">(</span><span class="identifier">T</span><span class="special">).</span><span class="identifier">name</span><span class="special">()</span> <span class="special"><<</span> <span class="string">" ]"</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="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">another_func</span><span class="special">()</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="string">"another_class::another_func() = 5"</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="keyword">return</span> <span class="number">5</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">some_data</span> <span class="special">=</span> <span class="string">"another_class's data"</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">print_data</span><span class="special">(</span><span class="identifier">interface_x</span> <span class="identifier">obj</span><span class="special">)</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="identifier">obj</span><span class="special">.</span><span class="identifier">some_data</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="special">}</span>
|
|
|
|
<span class="comment">// Both classes above can be assigned to the interface variable and their</span>
|
|
<span class="comment">// member functions can be called through it.</span>
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">a_class</span> <span class="identifier">x</span><span class="special">;</span>
|
|
<span class="identifier">another_class</span> <span class="identifier">y</span><span class="special">;</span>
|
|
|
|
<span class="identifier">interface_x</span> <span class="identifier">i</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">a_func</span><span class="special">(</span><span class="number">12</span><span class="special">);</span>
|
|
<span class="identifier">i</span><span class="special">.</span><span class="identifier">a_func</span><span class="special">(</span><span class="number">77L</span><span class="special">);</span>
|
|
<span class="identifier">i</span><span class="special">.</span><span class="identifier">another_func</span><span class="special">();</span>
|
|
|
|
<span class="identifier">print_data</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
|
|
<span class="identifier">i</span><span class="special">.</span><span class="identifier">some_data</span><span class="special">()</span> <span class="special">=</span> <span class="string">"x's data has changed."</span><span class="special">;</span>
|
|
<span class="identifier">print_data</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
|
|
<span class="comment">//reusing the same interface object</span>
|
|
<span class="identifier">i</span> <span class="special">=</span> <span class="identifier">y</span><span class="special">;</span>
|
|
<span class="identifier">i</span><span class="special">.</span><span class="identifier">a_func</span><span class="special">(</span><span class="number">13</span><span class="special">);</span>
|
|
<span class="identifier">i</span><span class="special">.</span><span class="identifier">a_func</span><span class="special">(</span><span class="number">21L</span><span class="special">);</span>
|
|
<span class="identifier">i</span><span class="special">.</span><span class="identifier">another_func</span><span class="special">();</span>
|
|
<span class="identifier">print_data</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<h3>
|
|
<a name="callable_traits_interface_example.h2"></a>
|
|
<span class="phrase"><a name="callable_traits_interface_example.implementation"></a></span><a class="link" href="callable_traits_interface_example.html#callable_traits_interface_example.implementation">Implementation</a>
|
|
</h3>
|
|
<p>
|
|
If you are unfamiliar with type erasure techniques, you may want to go learn
|
|
about them before reading the implementation header.
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">arg_at</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">result_of</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">pop_front</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">push_front</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">expand_args</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">replace_args</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">function_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">set_qualifiers</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">qualifier_flags</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">copy_qualifiers</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">is_like_function</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">remove_member_cv</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">get_qualifier_flags</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">apply_member_pointer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">remove_member_pointer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">remove_member_reference</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">qualified_parent_class_of</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">get_member_qualifier_flags</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="identifier">seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">facilities</span><span class="special">/</span><span class="identifier">empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">repetition</span><span class="special">/</span><span class="identifier">repeat</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">punctuation</span><span class="special">/</span><span class="identifier">comma_if</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">utility</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">type_traits</span><span class="special">></span>
|
|
|
|
<span class="keyword">namespace</span> <span class="identifier">intrfc</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">namespace</span> <span class="identifier">ct</span> <span class="special">=</span> <span class="identifier">callable_traits</span><span class="special">;</span>
|
|
|
|
<span class="comment">//this is our placeholder parent class for member pointers</span>
|
|
<span class="keyword">struct</span> <span class="identifier">secret</span> <span class="special">{};</span>
|
|
|
|
<span class="comment">// used to forward a parameter without copying it</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">using</span> <span class="identifier">forward_t</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">conditional_t</span><span class="special"><</span> <span class="keyword">sizeof</span><span class="special">(</span><span class="keyword">void</span><span class="special">*)</span> <span class="special"><</span> <span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span>
|
|
<span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_const_t</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="comment">// The member struct erases the object reference type that is supplied by</span>
|
|
<span class="comment">// function_type, which aliases an INVOKE-aware function type when</span>
|
|
<span class="comment">// a pmf is passed to it. We replace the first argument (which is</span>
|
|
<span class="comment">// a reference to an object of the member ptr's parent class, as required</span>
|
|
<span class="comment">// by INVOKE) with void*.</span>
|
|
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Ptr</span><span class="special">,</span> <span class="identifier">Ptr</span> <span class="identifier">Value</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">IsPmf</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">is_member_function_pointer</span><span class="special"><</span><span class="identifier">Ptr</span><span class="special">>::</span><span class="identifier">value</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member</span><span class="special">;</span>
|
|
|
|
<span class="comment">// this is our type erasure "glue". member<...>::wrapper::wrap is a static member function which</span>
|
|
<span class="comment">// casts a void* back to its original object type, and invokes the appropriate member. This first</span>
|
|
<span class="comment">// definition handles member functions.</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Pmf</span><span class="special">,</span> <span class="identifier">Pmf</span> <span class="identifier">PmfValue</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member</span><span class="special"><</span><span class="identifier">Pmf</span><span class="special">,</span> <span class="identifier">PmfValue</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span> <span class="special">{</span>
|
|
|
|
<span class="comment">// qualified_parent_class_of yields a reference type which is qualified</span>
|
|
<span class="comment">// according to the member function type.</span>
|
|
<span class="keyword">using</span> <span class="identifier">context</span> <span class="special">=</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special"><</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">qualified_parent_class_of</span><span class="special"><</span><span class="identifier">Pmf</span><span class="special">>>;</span>
|
|
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_wrapper</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">static</span> <span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">wrap</span><span class="special">(</span><span class="keyword">void</span><span class="special">*</span> <span class="identifier">c</span><span class="special">,</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="special">(</span><span class="keyword">reinterpret_cast</span><span class="special"><</span><span class="identifier">context</span><span class="special">*>(</span><span class="identifier">c</span><span class="special">)->*</span><span class="identifier">PmfValue</span><span class="special">)(</span><span class="identifier">args</span><span class="special">...);</span>
|
|
<span class="special">};</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// removing the member pointer so that expand_args below doesn't include</span>
|
|
<span class="comment">// the INVOKE-required object argument</span>
|
|
<span class="keyword">using</span> <span class="identifier">abominable_function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">remove_member_pointer</span><span class="special"><</span><span class="identifier">Pmf</span><span class="special">>;</span>
|
|
|
|
<span class="comment">// expand_args is used to expand the argument types into member_wrapper</span>
|
|
<span class="keyword">using</span> <span class="identifier">wrapper</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">expand_args</span><span class="special"><</span>
|
|
<span class="identifier">abominable_function_type</span><span class="special">,</span> <span class="identifier">member_wrapper</span><span class="special">>;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// This specialization handles member data.</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">C</span><span class="special">::*</span> <span class="identifier">PmdValue</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member</span><span class="special"><</span><span class="identifier">T</span> <span class="identifier">C</span><span class="special">::*,</span> <span class="identifier">PmdValue</span><span class="special">,</span> <span class="keyword">false</span><span class="special">></span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">no_ref</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special"><</span><span class="identifier">T</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">is_const</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">no_ref</span><span class="special">>::</span><span class="identifier">value</span><span class="special">;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">context</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">conditional_t</span><span class="special"><</span><span class="identifier">is_const</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">C</span><span class="special">,</span> <span class="identifier">C</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">struct</span> <span class="identifier">wrapper</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">static</span> <span class="keyword">inline</span> <span class="identifier">T</span><span class="special">&</span>
|
|
<span class="identifier">wrap</span><span class="special">(</span><span class="keyword">void</span><span class="special">*</span> <span class="identifier">c</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="keyword">reinterpret_cast</span><span class="special"><</span><span class="identifier">context</span><span class="special">*>(</span><span class="identifier">c</span><span class="special">)->*</span><span class="identifier">PmdValue</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
<span class="special">};</span>
|
|
<span class="special">};</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// BOOST_PP_NIL is not defined - the code below is simply a large comment</span>
|
|
<span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_PP_NIL</span>
|
|
|
|
<span class="identifier">DEFINE_INTERFACE</span><span class="special">(</span><span class="identifier">interface_x</span><span class="special">,</span>
|
|
<span class="special">((</span><span class="identifier">print_member_data</span><span class="special">,</span> <span class="keyword">void</span><span class="special">()</span> <span class="keyword">const</span><span class="special">))</span>
|
|
<span class="special">((</span><span class="identifier">member_data</span><span class="special">,</span> <span class="keyword">int</span><span class="special">))</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="comment">// The above macro invocation would expand to the following code (sans comments and formatting, of course):</span>
|
|
|
|
<span class="comment">// most of our implementation logic is dumped into this</span>
|
|
<span class="comment">// class to reduce the chance of naming conflicts. We could</span>
|
|
<span class="comment">// use a namespace instead, except that namespaces can't be</span>
|
|
<span class="comment">// opened inside class definition. Anywhere you see "interface_x",</span>
|
|
<span class="comment">// "print_member_data", and "member_data", remember that these</span>
|
|
<span class="comment">// names originate from the macro parameters.</span>
|
|
<span class="keyword">struct</span> <span class="identifier">interface_x_detail</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// This will be our root base class, containing our vtable and void*</span>
|
|
<span class="comment">// necessary for type erasure.</span>
|
|
<span class="keyword">struct</span> <span class="identifier">interface_root</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">struct</span> <span class="identifier">vtable</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">secret</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info0</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// this comes from the from the macro parameters</span>
|
|
<span class="keyword">using</span> <span class="identifier">member_type</span> <span class="special">=</span> <span class="keyword">void</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
|
|
|
|
<span class="comment">// this definition is only used for member data</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Member</span> <span class="special">=</span> <span class="identifier">member_type</span><span class="special">,</span>
|
|
<span class="keyword">bool</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">has_member_qualifiers</span><span class="special"><</span><span class="identifier">member_type</span><span class="special">>::</span><span class="identifier">value</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span><span class="special"><</span><span class="identifier">Member</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="identifier">Member</span> <span class="identifier">U</span><span class="special">::*;</span>
|
|
|
|
<span class="comment">// we will use these later to correctly re-construct our interface function</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span>
|
|
<span class="keyword">decltype</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">get_qualifier_flags</span><span class="special"><</span><span class="identifier">Member</span><span class="special">>());</span>
|
|
|
|
<span class="comment">// Our type erasure scheme will use a function to dereference</span>
|
|
<span class="comment">// pointers to member data</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="identifier">result_type</span><span class="special">(*)(</span><span class="keyword">void</span> <span class="special">*);</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// this specialization is only used for member functions</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">U</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info</span><span class="special"><</span><span class="identifier">U</span><span class="special">,</span> <span class="identifier">member_type</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="identifier">member_type</span> <span class="identifier">U</span><span class="special">::*;</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>;</span>
|
|
|
|
<span class="comment">// The first argument of this function type is a qualified U</span>
|
|
<span class="comment">// reference, because function_type is defined in terms of INVOKE</span>
|
|
<span class="keyword">using</span> <span class="identifier">function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">function_type</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>;</span>
|
|
|
|
<span class="comment">// we will use these later to correctly re-construct our forwarding</span>
|
|
<span class="comment">// interface function</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span>
|
|
<span class="keyword">decltype</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">get_member_qualifier_flags</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>());</span>
|
|
|
|
<span class="comment">// overwriting the first argument with void*, "erasing" the</span>
|
|
<span class="comment">// qualified U reference. We then make it a function pointer.</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">replace_args</span><span class="special"><</span><span class="number">0</span><span class="special">,</span> <span class="identifier">function_type</span><span class="special">,</span> <span class="keyword">void</span><span class="special">*></span> <span class="special">*;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// these aliases simply make later code easier to follow</span>
|
|
<span class="keyword">using</span> <span class="identifier">info</span> <span class="special">=</span> <span class="identifier">member_info</span><span class="special"><</span><span class="identifier">T</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">ptr_type</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">result_type</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">type_erased_ptr</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">qualifiers</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// this alias saves us some typing later</span>
|
|
<span class="keyword">using</span> <span class="identifier">pmf0</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">member_info0</span><span class="special"><>::</span><span class="identifier">ptr_type</span><span class="special">;</span>
|
|
|
|
<span class="comment">// This is our vtable function pointer entry, which will be initialized</span>
|
|
<span class="comment">// at compile-time.</span>
|
|
<span class="keyword">typename</span> <span class="identifier">member_info0</span><span class="special"><>::</span><span class="identifier">type_erased_ptr</span> <span class="identifier">func0</span><span class="special">;</span>
|
|
|
|
<span class="comment">// repeating for additional members supplied by the macro</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">secret</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info1</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// this comes from the from the macro parameters</span>
|
|
<span class="keyword">using</span> <span class="identifier">member_type</span> <span class="special">=</span> <span class="keyword">int</span><span class="special">;</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Member</span> <span class="special">=</span> <span class="identifier">member_type</span><span class="special">,</span>
|
|
<span class="keyword">bool</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_like_function</span><span class="special"><</span><span class="identifier">member_type</span><span class="special">>()></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span><span class="special"><</span><span class="identifier">Member</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="identifier">Member</span> <span class="identifier">U</span><span class="special">::*;</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span>
|
|
<span class="keyword">decltype</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">get_qualifier_flags</span><span class="special"><</span><span class="identifier">Member</span><span class="special">>());</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="identifier">result_type</span><span class="special">(*)(</span><span class="keyword">void</span> <span class="special">*);</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">U</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info</span><span class="special"><</span><span class="identifier">U</span><span class="special">,</span> <span class="identifier">member_type</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="identifier">member_type</span> <span class="identifier">U</span><span class="special">::*;</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">function_type</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span>
|
|
<span class="keyword">decltype</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">get_member_qualifier_flags</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>());</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">replace_args</span><span class="special"><</span><span class="number">0</span><span class="special">,</span> <span class="identifier">function_type</span><span class="special">,</span> <span class="keyword">void</span> <span class="special">*></span> <span class="special">*;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">info</span> <span class="special">=</span> <span class="identifier">member_info</span><span class="special"><</span><span class="identifier">T</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">ptr_type</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">result_type</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">type_erased_ptr</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">qualifiers</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">pmf1</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">member_info1</span><span class="special"><>::</span><span class="identifier">ptr_type</span><span class="special">;</span>
|
|
<span class="keyword">typename</span> <span class="identifier">member_info1</span><span class="special"><>::</span><span class="identifier">type_erased_ptr</span> <span class="identifier">func1</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">//our two data members</span>
|
|
<span class="keyword">const</span> <span class="identifier">vtable</span> <span class="special">*</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">void</span> <span class="special">*</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="comment">// conversion constructor that creates an interface from an arbitrary class</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">inline</span> <span class="identifier">interface_root</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&</span><span class="identifier">that</span><span class="special">)</span>
|
|
<span class="special">:</span> <span class="identifier">ptr_vtable</span><span class="special">(&</span><span class="identifier">vtable_holder</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">val_vtable</span><span class="special">),</span>
|
|
<span class="identifier">obj_ptr</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">addressof</span><span class="special">(</span><span class="identifier">that</span><span class="special">))</span> <span class="special">{</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// This template is instantiated for every class from which this interface</span>
|
|
<span class="comment">// is constructed (see constructor above). This instantiation causes the</span>
|
|
<span class="comment">// compiler to emit an initialized vtable for this type (via aggregate</span>
|
|
<span class="comment">// assignment later in the code).</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">struct</span> <span class="identifier">vtable_holder</span> <span class="special">{</span> <span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">vtable</span> <span class="identifier">val_vtable</span><span class="special">;</span> <span class="special">};</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// this definition will not be used, but is necessary for eager template instantiation</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">int</span> <span class="identifier">I</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Ignored</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">secret</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">base</span> <span class="special">{</span>
|
|
<span class="keyword">using</span> <span class="identifier">type</span> <span class="special">=</span> <span class="identifier">Ignored</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// We use get_next_base to chain together our base classes, starting with interface_root.</span>
|
|
<span class="comment">// The rest of the classes each contain an interface member.</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">int</span> <span class="identifier">I</span><span class="special">></span>
|
|
<span class="keyword">using</span> <span class="identifier">get_next_base</span> <span class="special">=</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">conditional_t</span><span class="special"><</span><span class="identifier">I</span> <span class="special">==</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">interface_root</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">base</span><span class="special"><</span><span class="identifier">I</span> <span class="special">-</span> <span class="number">1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">>;</span>
|
|
|
|
<span class="comment">// base_impl0 defines the first member supplied by the macro, specializing on</span>
|
|
<span class="comment">// the qualifiers that exist on the supplied member. The appropriate "apply"</span>
|
|
<span class="comment">// specialization will serve as a base class for our interface.</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">base_impl0</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">flags</span> <span class="identifier">QualifierFlags</span><span class="special">,</span>
|
|
<span class="keyword">typename</span> <span class="identifier">Base</span> <span class="special">=</span> <span class="identifier">get_next_base</span><span class="special"><</span><span class="number">0</span><span class="special">>></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special">;</span>
|
|
|
|
<span class="comment">// for unqualified member functions/data</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">default_</span><span class="special">,</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">print_member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func0</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// for const-qualified member functions/data</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">const_</span><span class="special">,</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">print_member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func0</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// for volatile-qualified member functions/data</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">volatile_</span><span class="special">,</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">print_member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">volatile</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func0</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// for const-volatile-qualified member functions/data</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">const_</span> <span class="special">|</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">volatile_</span><span class="special">),</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">print_member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func0</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// this specialization helps link the bases together</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Ignored</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">base</span><span class="special"><</span><span class="number">0</span><span class="special">,</span> <span class="identifier">Ignored</span><span class="special">></span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">function_type</span><span class="special"><</span>
|
|
<span class="keyword">typename</span> <span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span><span class="special">::</span><span class="identifier">pmf0</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">impl</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">expand_args</span><span class="special"><</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">pop_front</span><span class="special"><</span><span class="identifier">function_type</span><span class="special">>,</span>
|
|
<span class="identifier">base_impl0</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span>
|
|
<span class="keyword">typename</span> <span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span><span class="special">::</span><span class="identifier">member_info0</span><span class="special"><>::</span><span class="identifier">qualifiers</span><span class="special">;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">type</span> <span class="special">=</span> <span class="identifier">impl</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">apply</span><span class="special"><</span><span class="identifier">qualifiers</span><span class="special">::</span><span class="identifier">value</span><span class="special">>;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// repeat for additional interface members</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">base_impl1</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">flags</span> <span class="identifier">QualifierFlags</span><span class="special">,</span>
|
|
<span class="keyword">typename</span> <span class="identifier">Base</span> <span class="special">=</span> <span class="identifier">get_next_base</span><span class="special"><</span><span class="number">1</span><span class="special">>></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special">;</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">default_</span><span class="special">,</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func1</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</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">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">const_</span><span class="special">,</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func1</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</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">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">volatile_</span><span class="special">,</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">volatile</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func1</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</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">typename</span> <span class="identifier">Base</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">const_</span> <span class="special">|</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">volatile_</span><span class="special">),</span> <span class="identifier">Base</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">Base</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span>
|
|
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span>
|
|
<span class="identifier">member_data</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">func1</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);</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">typename</span> <span class="identifier">Ignored</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">base</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="identifier">Ignored</span><span class="special">></span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">function_type</span><span class="special"><</span>
|
|
<span class="keyword">typename</span> <span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span><span class="special">::</span><span class="identifier">pmf1</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">impl</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">expand_args</span><span class="special"><</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">pop_front</span><span class="special"><</span><span class="identifier">function_type</span><span class="special">>,</span>
|
|
<span class="identifier">base_impl1</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span>
|
|
<span class="keyword">typename</span> <span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span><span class="special">::</span><span class="identifier">member_info1</span><span class="special"><>::</span><span class="identifier">qualifiers</span><span class="special">;</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">type</span> <span class="special">=</span> <span class="identifier">impl</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">apply</span><span class="special"><</span><span class="identifier">qualifiers</span><span class="special">::</span><span class="identifier">value</span><span class="special">>;</span>
|
|
<span class="special">};</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// this initializes the vtable at compile time for every class used to construct an</span>
|
|
<span class="comment">// interface_x object. Member functions and member data are both handled.</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="identifier">interface_x_detail</span><span class="special">::</span><span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span> <span class="keyword">const</span>
|
|
<span class="identifier">interface_x_detail</span><span class="special">::</span><span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable_holder</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">val_vtable</span> <span class="special">=</span> <span class="special">{</span>
|
|
|
|
<span class="special">&::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">member</span><span class="special"><</span>
|
|
<span class="keyword">typename</span> <span class="identifier">vtable</span><span class="special">::</span><span class="identifier">member_info0</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">ptr_type</span><span class="special">,</span>
|
|
<span class="special">&</span><span class="identifier">T</span><span class="special">::</span><span class="identifier">print_member_data</span>
|
|
<span class="special">>::</span><span class="identifier">wrapper</span><span class="special">::</span><span class="identifier">wrap</span><span class="special">,</span>
|
|
|
|
<span class="special">&::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">member</span><span class="special"><</span>
|
|
<span class="keyword">typename</span> <span class="identifier">vtable</span><span class="special">::</span><span class="identifier">member_info1</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">ptr_type</span><span class="special">,</span>
|
|
<span class="special">&</span><span class="identifier">T</span><span class="special">::</span><span class="identifier">member_data</span>
|
|
<span class="special">>::</span><span class="identifier">wrapper</span><span class="special">::</span><span class="identifier">wrap</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">// We inherit the base for the last member, which inherits all</span>
|
|
<span class="comment">// the bases before it. This strategy keeps our runtime memory layout</span>
|
|
<span class="comment">// as small as possible, but unfortunately increases compile times.</span>
|
|
<span class="keyword">struct</span> <span class="identifier">interface_x</span> <span class="special">:</span> <span class="identifier">interface_x_detail</span><span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="number">2</span> <span class="special">-</span> <span class="number">1</span><span class="special">>::</span><span class="identifier">type</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">detail</span> <span class="special">=</span> <span class="identifier">interface_x_detail</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">base</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="number">2</span> <span class="special">-</span> <span class="number">1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">;</span>
|
|
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">enable_if_t</span><span class="special"><</span>
|
|
<span class="special">!</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_base_of</span><span class="special"><</span><span class="identifier">interface_root</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span><span class="identifier">T</span><span class="special">>>::</span><span class="identifier">value</span><span class="special">,</span> <span class="keyword">int</span><span class="special">></span> <span class="special">=</span> <span class="number">0</span><span class="special">></span>
|
|
<span class="keyword">inline</span> <span class="identifier">interface_x</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&</span><span class="identifier">that</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">base</span><span class="special">(</span><span class="identifier">that</span><span class="special">)</span> <span class="special">{}</span>
|
|
|
|
<span class="keyword">inline</span> <span class="identifier">interface_x</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">interface_x</span> <span class="special">&)</span> <span class="special">=</span> <span class="keyword">default</span><span class="special">;</span>
|
|
|
|
<span class="comment">// These using declarations assist with IDE code-completion</span>
|
|
<span class="keyword">using</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="number">0</span><span class="special">>::</span><span class="identifier">type</span><span class="special">::</span><span class="identifier">print_member_data</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="number">1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">::</span><span class="identifier">member_data</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="comment">// the interface definition on the client's side</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">DEFINE_INTERFACE</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">def</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">_detail</span><span class="special">)</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">interface_root</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">vtable</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__MEMBERS</span><span class="special">(</span><span class="identifier">def</span><span class="special">,</span> <span class="identifier">VTABLE</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">};</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">const</span> <span class="identifier">vtable</span> <span class="special">*</span> <span class="identifier">ptr_vtable</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="keyword">void</span><span class="special">*</span> <span class="identifier">obj_ptr</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="special">\</span>
|
|
<span class="keyword">inline</span> <span class="identifier">interface_root</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">that</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">:</span> <span class="identifier">ptr_vtable</span><span class="special">(&</span><span class="identifier">vtable_holder</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">val_vtable</span><span class="special">),</span> <span class="special">\</span>
|
|
<span class="identifier">obj_ptr</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">addressof</span><span class="special">(</span><span class="identifier">that</span><span class="special">))</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="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">vtable_holder</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">vtable</span> <span class="identifier">val_vtable</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">};</span> <span class="special">\</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">int</span> <span class="identifier">I</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Ignored</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">secret</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">base</span><span class="special">{</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">type</span> <span class="special">=</span> <span class="identifier">Ignored</span><span class="special">;</span> <span class="special">\</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">int</span> <span class="identifier">I</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">get_next_base</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">conditional_t</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="identifier">I</span> <span class="special">==</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">interface_root</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">base</span><span class="special"><</span><span class="identifier">I</span> <span class="special">-</span> <span class="number">1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">>;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__MEMBERS</span><span class="special">(</span><span class="identifier">def</span><span class="special">,</span> <span class="identifier">BASES</span><span class="special">)</span> <span class="special">\</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">typename</span> <span class="identifier">T</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">_detail</span><span class="special">)::</span><span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span> <span class="keyword">const</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">_detail</span><span class="special">)::</span><span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable_holder</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">val_vtable</span> <span class="special">=</span> <span class="special">\</span>
|
|
<span class="special">{</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__MEMBERS</span><span class="special">(</span><span class="identifier">def</span><span class="special">,</span> <span class="identifier">INIT_VTABLE</span><span class="special">)</span> <span class="special">};</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">name</span> <span class="special">:</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">_detail</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="identifier">BOOST_PP_SEQ_SIZE</span><span class="special">(</span><span class="identifier">def</span><span class="special">)</span> <span class="special">-</span> <span class="number">1</span><span class="special">>::</span><span class="identifier">type</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">detail</span> <span class="special">=</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">_detail</span><span class="special">);</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">base</span> <span class="special">=</span> <span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="identifier">BOOST_PP_SEQ_SIZE</span><span class="special">(</span><span class="identifier">def</span><span class="special">)</span> <span class="special">-</span> <span class="number">1</span><span class="special">>::</span><span class="identifier">type</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">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">enable_if_t</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="special">!</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_base_of</span><span class="special"><</span><span class="identifier">interface_root</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span><span class="identifier">T</span><span class="special">>>::</span><span class="identifier">value</span><span class="special">,</span> <span class="keyword">int</span><span class="special">></span> <span class="special">=</span> <span class="number">0</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">inline</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">that</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">base</span><span class="special">(</span><span class="identifier">that</span><span class="special">)</span> <span class="special">{}</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">inline</span> <span class="identifier">name</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">name</span> <span class="special">&)</span> <span class="special">=</span> <span class="keyword">default</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__MEMBERS</span><span class="special">(</span><span class="identifier">def</span><span class="special">,</span> <span class="identifier">USING_DECLARATIONS</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">}</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
|
|
<span class="comment">// preprocessing code details</span>
|
|
|
|
<span class="comment">// iterate all of the interface's members and invoke a macro, prefixed</span>
|
|
<span class="comment">// with CALLABLE_TRAITS_INTERFACE__</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__MEMBERS</span><span class="special">(</span><span class="identifier">seq</span><span class="special">,</span><span class="identifier">macro</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_REPEAT</span><span class="special">(</span><span class="identifier">BOOST_PP_SEQ_SIZE</span><span class="special">(</span><span class="identifier">seq</span><span class="special">),</span> <span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__</span> <span class="special">##</span> <span class="identifier">macro</span><span class="special">,</span> <span class="identifier">seq</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="comment">// generate the vtable initilizer code</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__INIT_VTABLE</span><span class="special">(</span><span class="identifier">z</span><span class="special">,</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__INIT_VTABLE_I</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_SEQ_ELEM</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)))</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__INIT_VTABLE_I</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">mem</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_COMMA_IF</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">&::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">member</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">vtable</span><span class="special">::</span><span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">member_info</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)<</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">ptr_type</span><span class="special">,\</span>
|
|
<span class="special">&</span><span class="identifier">T</span><span class="special">::</span><span class="identifier">mem</span> <span class="special">\</span>
|
|
<span class="special">>::</span><span class="identifier">wrapper</span><span class="special">::</span><span class="identifier">wrap</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="comment">//generate the vtable</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__VTABLE</span><span class="special">(</span><span class="identifier">z</span><span class="special">,</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__VTABLE_I</span><span class="special">(</span><span class="identifier">z</span><span class="special">,</span><span class="identifier">i</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_PP_SEQ_ELEM</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)))</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__VTABLE_I</span><span class="special">(</span><span class="identifier">z</span><span class="special">,</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">signature</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">secret</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">member_info</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">member_type</span> <span class="special">=</span> <span class="identifier">signature</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">typename</span> <span class="identifier">U</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Member</span> <span class="special">=</span> <span class="identifier">member_type</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="keyword">bool</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_like_function</span><span class="special"><</span><span class="identifier">member_type</span><span class="special">>()></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span><span class="special"><</span><span class="identifier">Member</span><span class="special">>;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="identifier">Member</span> <span class="identifier">U</span><span class="special">::*;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span> <span class="special">\</span>
|
|
<span class="keyword">decltype</span><span class="special">(</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">get_qualifier_flags</span><span class="special"><</span><span class="identifier">Member</span><span class="special">>());</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="identifier">result_type</span><span class="special">(*)(</span><span class="keyword">void</span><span class="special">*);</span> <span class="special">\</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">typename</span> <span class="identifier">U</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">member_info</span> <span class="special"><</span><span class="identifier">U</span><span class="special">,</span> <span class="identifier">member_type</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="identifier">member_type</span> <span class="identifier">U</span><span class="special">::*;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">function_type</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">get_member_qualifier_flags</span><span class="special"><</span><span class="identifier">ptr_type</span><span class="special">>());</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">replace_args</span><span class="special"><</span><span class="number">0</span><span class="special">,</span> <span class="identifier">function_type</span><span class="special">,</span> <span class="keyword">void</span><span class="special">*></span> <span class="special">*;</span> <span class="special">\</span>
|
|
<span class="special">};</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">info</span> <span class="special">=</span> <span class="identifier">member_info</span><span class="special"><</span><span class="identifier">T</span><span class="special">>;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">ptr_type</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">ptr_type</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">result_type</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">result_type</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">type_erased_ptr</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">type_erased_ptr</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">info</span><span class="special">::</span><span class="identifier">qualifiers</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">};</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">pmf</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">=</span> <span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">member_info</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)<>::</span><span class="identifier">ptr_type</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">member_info</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)<></span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">type_erased_ptr</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">func</span><span class="special">,</span> <span class="identifier">i</span><span class="special">);</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="comment">// generate the bases, each of which will contain a public-facing</span>
|
|
<span class="comment">// interface function</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES</span><span class="special">(</span><span class="identifier">z</span><span class="special">,</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_I</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_SEQ_ELEM</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)))</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_I</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">mem</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">base_impl</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">template</span><span class="special"><::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">flags</span> <span class="identifier">QualifierFlags</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">Base</span> <span class="special">=</span> <span class="identifier">get_next_base</span><span class="special"><</span><span class="identifier">i</span><span class="special">>></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_APPLY</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">mem</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">default_</span><span class="special">,</span> <span class="identifier">BOOST_PP_EMPTY</span><span class="special">())</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_APPLY</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">mem</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">const_</span><span class="special">,</span> <span class="keyword">const</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_APPLY</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">mem</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">volatile_</span><span class="special">,</span> <span class="keyword">volatile</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_APPLY</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">mem</span><span class="special">,</span> <span class="special">\</span>
|
|
<span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">const_</span> <span class="special">|</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">volatile_</span><span class="special">),</span> <span class="keyword">const</span> <span class="keyword">volatile</span><span class="special">)\</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">typename</span> <span class="identifier">Ignored</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">base</span><span class="special"><</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">Ignored</span><span class="special">></span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">function_type</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">function_type</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span><span class="special">::</span><span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">pmf</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)>;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">impl</span> <span class="special">=</span> <span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">expand_args</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="special">::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">pop_front</span><span class="special"><</span><span class="identifier">function_type</span><span class="special">>,</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">base_impl</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)>;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">qualifiers</span> <span class="special">=</span> <span class="special">\</span>
|
|
<span class="keyword">typename</span> <span class="identifier">interface_root</span><span class="special">::</span><span class="identifier">vtable</span><span class="special">::</span><span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">member_info</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)<>\</span>
|
|
<span class="special">::</span><span class="identifier">qualifiers</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">type</span> <span class="special">=</span> <span class="identifier">impl</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">apply</span><span class="special"><</span><span class="identifier">qualifiers</span><span class="special">::</span><span class="identifier">value</span><span class="special">>;</span> <span class="special">\</span>
|
|
<span class="special">};</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="comment">// generate specializations based on qualifiers on member functions/data.</span>
|
|
<span class="comment">// lvalue and rvalue member functions are ignored.</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__BASES_APPLY</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">mem</span><span class="special">,</span> <span class="identifier">flags</span><span class="special">,</span> <span class="identifier">qualifiers</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Base</span><span class="special">></span> <span class="special">\</span>
|
|
<span class="keyword">struct</span> <span class="identifier">apply</span><span class="special"><</span><span class="identifier">flags</span><span class="special">,</span> <span class="identifier">Base</span><span class="special">></span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">Base</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">ptr_vtable</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">obj_ptr</span><span class="special">;</span> <span class="special">\</span>
|
|
<span class="special">\</span>
|
|
<span class="keyword">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">mem</span><span class="special">(::</span><span class="identifier">intrfc</span><span class="special">::</span><span class="identifier">forward_t</span><span class="special"><</span><span class="identifier">Args</span><span class="special">>...</span> <span class="identifier">args</span><span class="special">)</span> <span class="identifier">qualifiers</span> <span class="special">{</span> <span class="special">\</span>
|
|
<span class="keyword">return</span> <span class="identifier">ptr_vtable</span><span class="special">-></span><span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">func</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)(</span><span class="identifier">obj_ptr</span><span class="special">,</span> <span class="identifier">args</span><span class="special">...);\</span>
|
|
<span class="special">}</span> <span class="special">\</span>
|
|
<span class="special">};</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
|
|
<span class="preprocessor">#define</span> <span class="identifier">CALLABLE_TRAITS_INTERFACE__USING_DECLARATIONS</span><span class="special">(</span><span class="identifier">z</span><span class="special">,</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="keyword">using</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">base</span><span class="special"><</span><span class="identifier">i</span><span class="special">>::</span><span class="identifier">type</span><span class="special">::</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_SEQ_ELEM</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span><span class="identifier">seq</span><span class="special">));</span> <span class="special">\</span>
|
|
<span class="comment">/**/</span>
|
|
</pre>
|
|
<p>
|
|
See also: <a href="http://www.coderage.com/interfaces/" target="_top">Boost.Interfaces
|
|
(sic)</a>
|
|
</p>
|
|
</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 © 2016 Barrett Adair<p>
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE.md 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="callable_traits/example_std_function_sugar.html"><img src="../src/images/prev.png" alt="Prev"></a><a accesskey="u" href="index.html"><img src="../src/images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="../src/images/home.png" alt="Home"></a><a accesskey="n" href="callable_traits/contact.html"><img src="../src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|