Files
callable_traits/doc/html/index.html
2016-06-17 17:28:50 -05:00

508 lines
73 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>CallableTraits</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="next" href="callable_traits/compatibility.html" title="Compatibility">
</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="n" href="callable_traits/compatibility.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"></a>CallableTraits</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></div>
<div><p class="copyright">Copyright &#169; 2016 Barrett Adair</p></div>
<div><div class="legalnotice">
<a name="callable_traits.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>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl class="toc">
<dt><span class="section"><a href="index.html#callable_traits.introduction">Overview</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="index.html#callable_traits.introduction.prereqs">Prerequisite Topics</a></span></dt>
<dt><span class="section"><a href="index.html#callable_traits.introduction.motivation">Motivation</a></span></dt>
<dt><span class="section"><a href="index.html#callable_traits.introduction.boost_function_types">Regarding
<code class="literal">Boost.FunctionTypes</code></a></span></dt>
</dl></dd>
<dt><span class="section"><a href="callable_traits/compatibility.html">Compatibility</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html">FAQ</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.reasons">Why should I use <code class="literal">CallableTraits</code>?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.why_does_namespace_scoped_args_a">Why
does <code class="literal">callable_traits::</code><code class="literal">args</code> alias a <code class="literal">std::tuple</code>?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.why_use_reference_collapsing_rul">Why
use reference collapsing rules when adding member function ref-qualifiers?</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="callable_traits/building.html">Building the test suite</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_member_const.html">add_member_const</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_member_cv.html">add_member_cv</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_member_lvalue_reference.html">add_member_lvalue_reference</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_member_rvalue_reference.html">add_member_rvalue_reference</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_member_volatile.html">add_member_volatile</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_transaction_safe.html">add_transaction_safe</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_add_varargs.html">add_varargs</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_apply_member_pointer.html">apply_member_pointer</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_apply_return.html">apply_return</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_arg_at.html">arg_at</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_args.html">args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_clear_args.html">clear_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_expand_args.html">expand_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_expand_args_left.html">expand_args_left</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_expand_args_right.html">expand_args_right</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_insert_args.html">insert_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_replace_args.html">replace_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_args.html">remove_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_expand_args0.html">expand_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_function_type.html">function_type</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_has_calling_convention.html">has_calling_convention</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_has_varargs.html">has_varargs</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_has_void_return.html">has_void_return</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_is_const_member.html">is_const_member</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_is_cv_member.html">is_cv_member</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_is_lvalue_reference_member.html">is_lvalue_reference_member</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_is_reference_member.html">is_reference_member</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_is_rvalue_reference_member.html">is_rvalue_reference_member</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_has_member_qualifiers.html">has_member_qualifiers</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_is_volatile_member.html">is_volatile_member</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_member_const.html">remove_member_const</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_member_cv.html">remove_member_cv</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_member_pointer.html">remove_member_pointer</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_member_reference.html">remove_member_reference</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_varargs.html">remove_varargs</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_remove_member_volatile.html">remove_member_volatile</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_push_back_args.html">push_back_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_push_front_args.html">push_front_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_pop_back_args.html">pop_back_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_push_front_args0.html">pop_front_args</a></span></dt>
<dt><span class="section"><a href="callable_traits/ref_result_of.html">result_of</a></span></dt>
<dt><span class="article"><a href="callable_traits_interface_example.html">Example: Java-style interfaces without inheritance</a></span></dt>
<dt><span class="section"><a href="callable_traits/contact.html">Contact</a></span></dt>
</dl>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="callable_traits.introduction"></a><a class="link" href="index.html#callable_traits.introduction" title="Overview">Overview</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="index.html#callable_traits.introduction.prereqs">Prerequisite Topics</a></span></dt>
<dt><span class="section"><a href="index.html#callable_traits.introduction.motivation">Motivation</a></span></dt>
<dt><span class="section"><a href="index.html#callable_traits.introduction.boost_function_types">Regarding
<code class="literal">Boost.FunctionTypes</code></a></span></dt>
</dl></div>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">callable_traits</span><span class="special">/</span><span class="identifier">callable_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">type_traits</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">tuple</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special">;</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">callable_traits</span><span class="special">;</span>
<span class="keyword">struct</span> <span class="identifier">number</span> <span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">value</span><span class="special">;</span>
<span class="keyword">auto</span> <span class="identifier">add</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">n</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">value</span> <span class="special">+</span> <span class="identifier">n</span><span class="special">;</span> <span class="special">}</span>
<span class="special">};</span>
<span class="keyword">using</span> <span class="identifier">pmf</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(&amp;</span><span class="identifier">number</span><span class="special">::</span><span class="identifier">add</span><span class="special">);</span>
</pre>
<p>
Manipulate member functions pointers with ease:
</p>
<pre class="programlisting"><span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">remove_member_const_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">)</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">add_member_volatile_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span> <span class="keyword">volatile</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">parent_class_of_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="identifier">number</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">remove_member_pointer_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">int</span> <span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
</pre>
<p>
INVOKE-aware metafunctions:
</p>
<pre class="programlisting"><span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">args_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="identifier">number</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">&gt;</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">arg_at_t</span><span class="special">&lt;</span><span class="number">0</span><span class="special">,</span> <span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">const</span> <span class="identifier">number</span><span class="special">&amp;</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">arg_at_t</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">int</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">result_of_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">int</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">function_type_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">number</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">)</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">qualified_parent_class_of_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;,</span>
<span class="keyword">const</span> <span class="identifier">number</span><span class="special">&amp;</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
</pre>
<p>
Here are a few other trait examples:
</p>
<pre class="programlisting"><span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_const_member</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">is_volatile_member</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">has_void_return</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">has_varargs</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
</pre>
<p>
You can use <code class="literal">CallableTraits</code> to manipulate parameter lists
(not defined in terms of INVOKE, since that wouldn't make sense here):
</p>
<pre class="programlisting"><span class="keyword">using</span> <span class="identifier">pmf_2</span> <span class="special">=</span> <span class="identifier">push_back_args_t</span><span class="special">&lt;</span><span class="identifier">pmf</span><span class="special">,</span> <span class="keyword">char</span><span class="special">,</span> <span class="keyword">short</span><span class="special">,</span> <span class="keyword">long</span><span class="special">&gt;;</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">pmf_2</span><span class="special">,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">,</span> <span class="keyword">short</span><span class="special">,</span> <span class="keyword">long</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">pop_front_args_t</span><span class="special">&lt;</span><span class="identifier">pmf_2</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">char</span><span class="special">,</span> <span class="keyword">short</span><span class="special">,</span> <span class="keyword">long</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">insert_args_t</span><span class="special">&lt;</span><span class="number">2</span><span class="special">,</span> <span class="identifier">pmf_2</span><span class="special">,</span> <span class="keyword">short</span><span class="special">*,</span> <span class="keyword">long</span><span class="special">*&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">,</span> <span class="keyword">short</span><span class="special">*,</span> <span class="keyword">long</span><span class="special">*,</span> <span class="keyword">short</span><span class="special">,</span> <span class="keyword">long</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">replace_args_t</span><span class="special">&lt;</span><span class="number">2</span><span class="special">,</span> <span class="identifier">pmf_2</span><span class="special">,</span> <span class="keyword">short</span><span class="special">*,</span> <span class="keyword">long</span><span class="special">*&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">,</span> <span class="keyword">short</span><span class="special">*,</span> <span class="keyword">long</span><span class="special">*)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">remove_args_t</span><span class="special">&lt;</span><span class="number">2</span><span class="special">,</span> <span class="identifier">pmf_2</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">,</span> <span class="keyword">long</span><span class="special">)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">clear_args_t</span><span class="special">&lt;</span><span class="identifier">pmf_2</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)()</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_same</span><span class="special">&lt;</span>
<span class="identifier">add_varargs_t</span><span class="special">&lt;</span><span class="identifier">pmf_2</span><span class="special">&gt;,</span>
<span class="keyword">int</span><span class="special">(</span><span class="identifier">number</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">,</span> <span class="keyword">short</span><span class="special">,</span> <span class="keyword">long</span><span class="special">,</span> <span class="special">...)</span> <span class="keyword">const</span>
<span class="special">&gt;{},</span> <span class="string">""</span><span class="special">);</span>
</pre>
<p>
<code class="literal">CallableTraits</code> is a C++11/14/17 header-only library for
the inspection, synthesis, and decomposition of callable types. From <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;</span></code> to container-like manipulation of
parameter lists, <code class="literal">CallableTraits</code> provides all the tools you
need to rid your codebase of function type specializations. <code class="literal">CallableTraits</code>
offers a comprehensive, fine-grained assortment of traits and metafunctions
for building and ripping apart C++'s most complicated and obscure types with
ease. <code class="literal">CallableTraits</code> fills the gaps where existing library
solutions fall short, aiming to be the "complete type manipulation facility
for function types" mentioned in the last section of <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0172r0.html" target="_top">p0172</a>,
the C++17 proposal regarding "abominable function types". <code class="literal">CallableTraits</code>
currently supports GCC 4.8 and later, Clang 3.5 and later, AppleClang from
XCode 6.3 and later, and Visual Studio 2015.
</p>
<p>
<code class="literal">CallableTraits</code> is header-only, and does not depend on any
headers outside the standard library.
</p>
<p>
<code class="literal">CallableTraits</code> is currently hosted at <a href="https://github.com/badair/callable_traits" target="_top">GitHub</a>.
<span class="bold"><strong><code class="literal">CallableTraits</code> is not a Boost library.</strong></span>
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.introduction.prereqs"></a><a class="link" href="index.html#callable_traits.introduction.prereqs" title="Prerequisite Topics">Prerequisite Topics</a>
</h3></div></div></div>
<p>
This documentation will be most beneficial to readers who posess a basic
understanding of the following C++ features:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/partial_specialization" target="_top">template
specializations</a>
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/sfinae" target="_top">SFINAE</a>
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/utility/functional/invoke" target="_top"><code class="literal"><span class="emphasis"><em>INVOKE</em></span></code></a>
rules
</li>
<li class="listitem">
function types
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_functions" target="_top">function
pointers</a>
</li>
<li class="listitem">
<a href="http://stackoverflow.com/questions/480248/function-references" target="_top">function
references</a>
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions" target="_top">pointers
to member functions</a> (a.k.a. PMFs)
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members" target="_top">pointers
to data members</a> (a.k.a. PMDs)
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/operators#Function_call_operator" target="_top">the
function call operator, <code class="literal">operator()</code></a>
</li>
<li class="listitem">
<a href="https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers" target="_top">universal
references</a> and <a href="http://stackoverflow.com/questions/13725747/concise-explanation-of-reference-collapsing-rules-requested-1-a-a-2" target="_top">reference
collapsing rules</a>
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/member_functions#const-.2C_volatile-.2C_and_ref-qualified_member_functions" target="_top">cv-qualified
and ref-qualified member functions</a>
</li>
<li class="listitem">
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0172r0.html" target="_top">"abominable"
function types</a>
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/overloaded_address" target="_top">taking
the address of overloaded functions</a>
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/c/language/variadic" target="_top">C-style
variadics</a>, a.k.a. varargs
</li>
<li class="listitem">
<a href="https://en.wikipedia.org/wiki/X86_calling_conventions" target="_top">calling
conventions</a>
</li>
</ul></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.introduction.motivation"></a><a class="link" href="index.html#callable_traits.introduction.motivation" title="Motivation">Motivation</a>
</h3></div></div></div>
<div class="blockquote"><blockquote class="blockquote">
<p>
<span class="bold"><strong><span class="emphasis"><em><span class="quote">&#8220;<span class="quote">Don't try to write helper code to
detect PMFs/PMDs and dispatch on them -- it is an <span class="underline">absolute
nightmare</span>. PMF types are the worst types by far in the core
language.</span>&#8221;</span></em></span></strong></span>
</p>
<p>
-- Stephan T. Lavavej, CppCon 2015, <a href="https://www.youtube.com/watch?v=zt7ThwVfap0&amp;t=11m40s" target="_top">"functional:
What's New, And Proper Usage"</a>
</p>
</blockquote></div>
<p>
Consider for a moment the class template below, which defines all <span class="red"><span class="bold"><strong>48</strong></span></span> template specializations
necessary to account for all valid function types and member function pointer
types in C++11 and C++14:
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">;</span>
<span class="comment">//function type without varargs</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">const</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">volatile</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</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">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</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">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</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">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="comment">//function type with varargs</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">volatile</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="comment">//member function pointer type without varargs</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">const</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">volatile</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</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">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</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">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</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">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="comment">//member function pointer type with varargs</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">volatile</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span><span class="special">&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;&gt;</span> <span class="special">{};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">Args</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{};</span>
</pre>
<p>
Use cases for such obscure specializations are vitually nonexistent in run-of-the-mill
application codebases. Even in library code, these are exceedingly rare.
However, there are a handful of very specific metaprogramming scenarios that
can only be solved with such template "spam". While these use cases
are indeed rare, the writing and testing of these templates is incredibly
tedious and time consuming. On this premise, <code class="literal">CallableTraits</code>
offers a final and decisive library-level solution, so that authors of generic
code will <span class="bold"><strong>never again</strong></span> need to write these
specializations, for <span class="emphasis"><em>any</em></span> reason.
</p>
<p>
Template specializations like those in the code snippet above <span class="emphasis"><em>still</em></span>
do not account for function pointers, function references, function objects/lambdas,
or calling conventions. <code class="literal">CallableTraits</code> goes the extra
mile by accounting for all of them.
</p>
<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>
The upcoming ISO standard for C++17 includes a <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html" target="_top">change
to the core language</a> which adds the <code class="literal">noexcept</code>
qualifier to the type system. If the author's understanding is correct,
this would increase the the count of necessary template specializations
to <span class="red"><span class="bold"><strong>96</strong></span></span> (<a class="link" href="callable_traits/contact.html" title="Contact">?</a>). Currently, C++17 <code class="computeroutput"><span class="keyword">noexcept</span></code> qualifiers are not handled in
<code class="literal">CallableTraits</code>, because compiler vendors have not implemented
support for this feature (to best of the author's knowledge). However,
features to account for and manipulate <code class="computeroutput"><span class="keyword">noexcept</span></code>
qualifiers are planned in <code class="literal">CallableTraits</code>, as soon as
feature is implemented by a compiler vendor. Of course, the <code class="literal">CallableTraits</code>
feature additions will be non-breaking for currently supported compiler
versions.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.introduction.boost_function_types"></a><a class="link" href="index.html#callable_traits.introduction.boost_function_types" title="Regarding Boost.FunctionTypes">Regarding
<code class="literal">Boost.FunctionTypes</code></a>
</h3></div></div></div>
<p>
The use cases for <code class="literal">CallableTraits</code> are closely related to
those of <a href="http://www.boost.org/doc/libs/1_61_0/libs/function_types/doc/html/index.html" target="_top"><code class="literal">Boost.FunctionTypes</code></a>.
Here are some reasons why you might prefer <code class="literal">CallableTraits</code>:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
<code class="literal">Boost.FunctionTypes</code> is tightly coupled to <a href="http://www.boost.org/doc/libs/1_60_0/libs/mpl/doc/index.html" target="_top"><code class="literal">Boost.MPL</code></a>
sequences, while <code class="literal">CallableTraits</code> generally takes a
lower-level approach. No knowledge of MPL terminology is needed to use
<code class="literal">CallableTraits</code>.
</li>
<li class="listitem">
Other types in C++ receive fine-grained, low-level attention in <code class="literal">Boost.TypeTraits</code>
and <code class="literal">&lt;type_traits&gt;</code>. <code class="literal">CallableTraits</code>
gives callable types similar attention, without additional metaprogramming
dependencies.
</li>
<li class="listitem">
<code class="literal">CallableTraits</code> aims to eliminate function type template
specializations. <code class="literal">Boost.FunctionTypes</code> does not.
</li>
<li class="listitem">
<code class="literal">CallableTraits</code> targets C++11/14/17 features. <code class="literal">Boost.FunctionTypes</code>
does not.
</li>
<li class="listitem">
The <code class="literal">Boost.FunctionTypes</code> interface relies heavily on
tag types. <code class="literal">CallableTraits</code> does not.
</li>
</ol></div>
<p>
<code class="literal">Boost.FunctionTypes</code> is a good tool for projects already
dependent on the MPL, which must also support very old compilers. However,
the <code class="literal">Boost.FunctionTypes</code> interface is unpleasant. It relies
heavily on both the MPL and tag types, for problems that are more simply
solved with neither. Using <code class="literal">Boost.FunctionTypes</code> requires
an understanding of the library's "big picture."
</p>
<p>
<code class="literal">CallableTraits</code> borrows and extends much of the functionality
found in <code class="literal">Boost.FunctionTypes</code>, re-packaging it in a more
accessible <code class="computeroutput"><span class="identifier">type_traits</span></code>-style
interface. There is nothing inherently wrong with <code class="literal">Boost.FunctionTypes</code>,
but an MPL sequence-based solution with no C++11/14/17 support should not
be the only library option for inspecting and manipulating callable types.
</p>
</div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="callable_traits/compatibility.html"><img src="../src/images/next.png" alt="Next"></a></div>
</body>
</html>