mirror of
https://github.com/boostorg/callable_traits.git
synced 2026-02-18 01:52:18 +00:00
918 lines
118 KiB
HTML
918 lines
118 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/ref.html" title="Reference">
|
|
</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/ref.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 © 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">Introduction</a></span></dt>
|
|
<dd><dl>
|
|
<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.quick_example">Quick Example</a></span></dt>
|
|
<dt><span class="section"><a href="index.html#callable_traits.introduction.basic_concepts">Concept
|
|
Definitions</a></span></dt>
|
|
<dt><span class="section"><a href="index.html#callable_traits.introduction.reasons">Why use <code class="literal">CallableTraits</code>?</a></span></dt>
|
|
<dt><span class="section"><a href="index.html#callable_traits.introduction.function_sugar">Use case:<code class="literal">std::function</code>
|
|
sugar</a></span></dt>
|
|
</dl></dd>
|
|
<dt><span class="section"><a href="callable_traits/ref.html">Reference</a></span></dt>
|
|
<dd><dl>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.headers">Headers</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_calling_convention">add_calling_convention</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_function_const">add_function_const</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_function_cv">add_function_cv</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_function_lvalue">add_function_lvalue</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_function_rvalue">add_function_rvalue</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_varargs">add_varargs</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_add_function_volatile">add_function_volatile</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_apply_member_pointer">apply_member_pointer</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_apply_return">apply_return</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_arg_at">arg_at</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_args">args</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_arity">arity</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_bind">bind</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_can_invoke">can_invoke</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_can_invoke_constexpr">can_invoke_constexpr</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_function_type">function_type</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_has_calling_convention">has_calling_convention</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_has_varargs">has_varargs</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_has_void_return">has_void_return</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_const_qualified">is_const_qualified</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_constexpr">is_constexpr</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_lvalue_qualified">is_lvalue_qualified</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_reference_qualified">is_reference_qualified</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_rvalue_qualified">is_rvalue_qualified</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_qualified">is_qualified</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_is_volatile_qualified">is_volatile_qualified</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_max_arity">max_arity</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_min_arity">min_arity</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_qualified_function_type">qualified_function_type</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_calling_convention">remove_calling_convention</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_function_const">remove_function_const</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_function_cv">remove_function_cv</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_member_pointer">remove_member_pointer</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_function_reference">remove_function_reference</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_varargs">remove_varargs</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_remove_function_volatile">remove_function_volatile</a></span></dt>
|
|
<dt><span class="section"><a href="callable_traits/ref.html#callable_traits.ref.ref_result_of">result_of</a></span></dt>
|
|
</dl></dd>
|
|
<dt><span class="section"><a href="callable_traits/acknowledgements.html">Acknowledgements</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="Introduction">Introduction</a>
|
|
</h2></div></div></div>
|
|
<div class="toc"><dl class="toc">
|
|
<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.quick_example">Quick Example</a></span></dt>
|
|
<dt><span class="section"><a href="index.html#callable_traits.introduction.basic_concepts">Concept
|
|
Definitions</a></span></dt>
|
|
<dt><span class="section"><a href="index.html#callable_traits.introduction.reasons">Why use <code class="literal">CallableTraits</code>?</a></span></dt>
|
|
<dt><span class="section"><a href="index.html#callable_traits.introduction.function_sugar">Use case:<code class="literal">std::function</code>
|
|
sugar</a></span></dt>
|
|
</dl></div>
|
|
<div class="important"><table border="0" summary="Important">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../src/images/important.png"></td>
|
|
<th align="left">Important</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
<code class="literal">CallableTraits</code> is not a Boost library.
|
|
</p></td></tr>
|
|
</table></div>
|
|
<p>
|
|
<code class="literal">CallableTraits</code> is a cross-platform C++14 library for the
|
|
inspection, decomposition, and synthesis of C++ callable types. <code class="literal">CallableTraits</code>
|
|
is header-only, and does not depend on any non-standard headers.
|
|
</p>
|
|
<p>
|
|
This documentation will be most beneficial to readers with a basic understanding
|
|
of the syntax and usage 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">INVOKE</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>
|
|
</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>
|
|
</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 an overloaded function</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>
|
|
<p>
|
|
The <code class="literal">CallableTraits</code> development repository is hosted at
|
|
<a href="https://github.com/badair/callable_traits" target="_top">GitHub</a>.
|
|
</p>
|
|
<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>
|
|
<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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
|
|
<span class="comment">//function type with varargs</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
|
|
<span class="comment">//member function pointer type without varargs</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
|
|
<span class="comment">//member function pointer type with varargs</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&></span> <span class="special">{};</span>
|
|
<span class="keyword">template</span><span class="special"><</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">></span> <span class="keyword">struct</span> <span class="identifier">foo</span><span class="special"><</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">&&></span> <span class="special">{};</span>
|
|
</pre>
|
|
<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">feedback</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>
|
|
<p>
|
|
Potential 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="warning"><table border="0" summary="Warning">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../src/images/warning.png"></td>
|
|
<th align="left">Warning</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top">
|
|
<p>
|
|
Features for the manipulation and inspection of calling conventions are
|
|
optional, which must be enabled with macro definitions. The features regarding
|
|
them are currently classified as <span class="emphasis"><em>experimental</em></span>, and
|
|
are subject to breaking changes in future versions of <code class="literal">CallableTraits</code>.
|
|
</p>
|
|
<p>
|
|
The rationale for classifying the calling convention features as "experimental"
|
|
is three-fold:
|
|
</p>
|
|
<div class="orderedlist"><ol class="orderedlist" type="1">
|
|
<li class="listitem">
|
|
Calling conventions are, by definition, highly platform-specific.
|
|
</li>
|
|
<li class="listitem">
|
|
The inclusion of a single calling convention effectively doubles the
|
|
test surface of <code class="literal">CallableTraits</code> <span class="emphasis"><em>on every
|
|
platform</em></span>.
|
|
</li>
|
|
<li class="listitem">
|
|
The author's current knowledge of calling conventions is admittedly
|
|
limited.
|
|
</li>
|
|
</ol></div>
|
|
<p>
|
|
It is the author's hope that future versions of <code class="literal">CallableTraits</code>
|
|
will offer a stable, thoroughly-tested, and well-documented implementation
|
|
of these features. If you have experience in this domain, your <a class="link" href="callable_traits/contact.html" title="Contact">feedback</a>
|
|
is <span class="emphasis"><em>highly</em></span> appreciated.
|
|
</p>
|
|
</td></tr>
|
|
</table></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_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html" target="_top">function_traits</a>
|
|
and <a href="http://www.boost.org/doc/libs/1_60_0/libs/function_types/doc/html/index.html" target="_top">Boost.FunctionTypes</a>.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="callable_traits.introduction.quick_example"></a><a class="link" href="index.html#callable_traits.introduction.quick_example" title="Quick Example">Quick Example</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
This short program showcases some, but not all, of the features available
|
|
in <code class="literal">CallableTraits</code>.
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">type_traits</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">functional</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">tuple</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">callable_traits</span><span class="special">.</span><span class="identifier">hpp</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">// foo is an example of a function object</span>
|
|
<span class="keyword">struct</span> <span class="identifier">foo</span> <span class="special">{</span>
|
|
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</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="keyword">int</span><span class="special">&,</span> <span class="keyword">void</span><span class="special">*</span> <span class="special">=</span> <span class="keyword">nullptr</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{}</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// indexed argument types</span>
|
|
<span class="keyword">using</span> <span class="identifier">second_arg</span> <span class="special">=</span> <span class="identifier">ct</span><span class="special">::</span><span class="identifier">arg_at</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">>;</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">second_arg</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&&>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// arg types are packaged into std::tuple, which serves as the default</span>
|
|
<span class="comment">// type list in <code class="literal">CallableTraits</code> (runtime capabilities are not used).</span>
|
|
<span class="keyword">using</span> <span class="identifier">args</span> <span class="special">=</span> <span class="identifier">ct</span><span class="special">::</span><span class="identifier">args</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">expected_args</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special"><</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="keyword">int</span><span class="special">&,</span> <span class="keyword">void</span><span class="special">*>;</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">args</span><span class="special">,</span> <span class="identifier">expected_args</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// <code class="literal">callable_traits::</code>function_type "decays" a callable type to a plain</span>
|
|
<span class="comment">// function type, which is structured in terms of INVOKE.</span>
|
|
<span class="keyword">using</span> <span class="identifier">function_type</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">foo</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">expected_function_type</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">int</span><span class="special">&&,</span> <span class="keyword">const</span> <span class="keyword">int</span><span class="special">&,</span> <span class="keyword">void</span><span class="special">*);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">function_type</span><span class="special">,</span> <span class="identifier">expected_function_type</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// By design, the <code class="literal">CallableTraits</code> interface uses constexpr</span>
|
|
<span class="comment">// std::integral_constant functions (whenever sensible).</span>
|
|
<span class="comment">// By also defining the appropriate overloads, this gives</span>
|
|
<span class="comment">// users the option of using either type arguments or a value</span>
|
|
<span class="comment">// arguments, which often eliminates the need for decltype:</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">arity</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>()</span> <span class="special">==</span> <span class="number">4</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">arity</span><span class="special">(</span><span class="identifier">foo</span><span class="special">{})</span> <span class="special">==</span> <span class="number">4</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// Attentive readers might notice that the type of the foo{}</span>
|
|
<span class="comment">// expression above is foo&&, rather than foo. Indeed,</span>
|
|
<span class="comment">// <code class="literal">CallableTraits</code> is designed to also allow both ref-qualified</span>
|
|
<span class="comment">// and cv-qualified arguments across the board:</span>
|
|
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">arity</span><span class="special"><</span><span class="identifier">foo</span><span class="special">&&>()</span> <span class="special">==</span> <span class="number">4</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// Now, if foo had an operator() overload with a && qualifier, taking</span>
|
|
<span class="comment">// a different number of arguments, the above static assert would fail.</span>
|
|
|
|
<span class="comment">// For consistency, we'll avoid the value-style overloads</span>
|
|
<span class="comment">// for the remainder of this example (whenever possible).</span>
|
|
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">max_arity</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>()</span> <span class="special">==</span> <span class="number">4</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">min_arity</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>()</span> <span class="special">==</span> <span class="number">3</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// a quick way to check for a void return type</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">has_void_return</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// C-style variadics detection (e.g. an ellipses in a signature)</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">has_varargs</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
|
|
|
<span class="comment">// <code class="literal">callable_traits::</code>can_invoke allows us to preview whether</span>
|
|
<span class="comment">// std::invoke would compile with the given arguments.</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">can_invoke</span><span class="special">(</span><span class="identifier">foo</span><span class="special">{},</span> <span class="number">0</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">i</span><span class="special">),</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="comment">// no error: std::invoke(foo{}, 0, 0, i);</span>
|
|
|
|
<span class="comment">// This call returns std::false_type, because it's an illegal call.</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">can_invoke</span><span class="special">(</span><span class="identifier">foo</span><span class="special">{},</span> <span class="keyword">nullptr</span><span class="special">),</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="comment">// error: std::invoke(foo{}, nullptr);</span>
|
|
|
|
<span class="comment">// Note that since can_invoke models std::invoke,</span>
|
|
<span class="comment">// only a value-style function is defined.</span>
|
|
|
|
<span class="comment">// For function objects, the following checks are determined by the</span>
|
|
<span class="comment">// function qualifiers on operator(), rather than the qualifiers on</span>
|
|
<span class="comment">// of the type passed. This is done for consistency with member function</span>
|
|
<span class="comment">// pointers, where the checks below would look at the function qualifiers</span>
|
|
<span class="comment">// (rather than qualifiers on the pointer itself).</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_const_qualified</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_volatile_qualified</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_reference_qualified</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_lvalue_qualified</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_rvalue_qualified</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// is_constexpr would return std::true_type if foo's operator() were constexpr.</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_constexpr</span><span class="special"><</span><span class="identifier">foo</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// The same check can be performed using std::integral_constant</span>
|
|
<span class="comment">// in conjunction with function addresses:</span>
|
|
<span class="keyword">using</span> <span class="identifier">pmf</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(&</span><span class="identifier">foo</span><span class="special">::</span><span class="keyword">operator</span><span class="special">());</span>
|
|
<span class="keyword">using</span> <span class="identifier">pmf_constant</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">integral_constant</span><span class="special"><</span><span class="identifier">pmf</span><span class="special">,</span> <span class="special">&</span><span class="identifier">foo</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()>;</span>
|
|
<span class="keyword">static_assert</span><span class="special">(!</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">is_constexpr</span><span class="special"><</span><span class="identifier">pmf_constant</span><span class="special">>(),</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// So that you don't have to scroll to the top to check,</span>
|
|
<span class="comment">// here's the type of pmf for reference.</span>
|
|
<span class="keyword">using</span> <span class="identifier">with_const</span> <span class="special">=</span> <span class="keyword">void</span> <span class="special">(</span><span class="identifier">foo</span><span class="special">::*)(</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="keyword">int</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="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">pmf</span><span class="special">,</span> <span class="identifier">with_const</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// If you find yourself in the unfortunate-and-probably-avoidable</span>
|
|
<span class="comment">// situation of needing to transform member function pointer</span>
|
|
<span class="comment">// types, <code class="literal">CallableTraits</code> has all the tools you need to prolong</span>
|
|
<span class="comment">// your sanity.</span>
|
|
|
|
<span class="comment">// <code class="literal">CallableTraits</code> lets you manipulate qualifiers on PMF types.</span>
|
|
<span class="comment">// To remove const:</span>
|
|
<span class="keyword">using</span> <span class="identifier">mutable_pmf</span> <span class="special">=</span> <span class="identifier">ct</span><span class="special">::</span><span class="identifier">remove_function_const</span><span class="special"><</span><span class="identifier">pmf</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">without_const</span> <span class="special">=</span> <span class="keyword">void</span> <span class="special">(</span><span class="identifier">foo</span><span class="special">::*)(</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="keyword">int</span><span class="special">&,</span> <span class="keyword">void</span><span class="special">*)</span> <span class="comment">/*no const!*/</span><span class="special">;</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">mutable_pmf</span><span class="special">,</span> <span class="identifier">without_const</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// To add an rvalue qualifier:</span>
|
|
<span class="keyword">using</span> <span class="identifier">rvalue_pmf</span> <span class="special">=</span> <span class="identifier">ct</span><span class="special">::</span><span class="identifier">add_function_rvalue</span><span class="special"><</span><span class="identifier">pmf</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">with_rvalue</span> <span class="special">=</span> <span class="keyword">void</span> <span class="special">(</span><span class="identifier">foo</span><span class="special">::*)(</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="keyword">int</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="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">rvalue_pmf</span><span class="special">,</span> <span class="identifier">with_rvalue</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// Just like std::add_rvalue_reference, <code class="literal">callable_traits::</code>add_function_rvalue</span>
|
|
<span class="comment">// follows C++11 reference collapsing rules. While remove_function_const</span>
|
|
<span class="comment">// and add_function_rvalue are somewhat clumsy names, they are the best</span>
|
|
<span class="comment">// the best the author could provide while still allowing both terseness</span>
|
|
<span class="comment">// and grep-ability against std::remove_const, etc. in <type_traits>.</span>
|
|
<span class="comment">// Naturally, <code class="literal">CallableTraits</code> provides similar tools for the other C++</span>
|
|
<span class="comment">// function qualifiers. Head to the reference section of this documentation</span>
|
|
<span class="comment">// for more examples.</span>
|
|
|
|
<span class="comment">// To remove a member pointer:</span>
|
|
<span class="keyword">using</span> <span class="identifier">fn</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="keyword">using</span> <span class="identifier">expected_fn</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">int</span><span class="special">&&,</span> <span class="keyword">const</span> <span class="keyword">int</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="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">fn</span><span class="special">,</span> <span class="identifier">expected_fn</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
|
|
<span class="comment">// We just created an abominable function type - notice the const</span>
|
|
<span class="comment">// qualifier! libnsremove_function_const accepts abominable</span>
|
|
<span class="comment">// types too (and so does any feature where it is legal to do so):</span>
|
|
<span class="keyword">using</span> <span class="identifier">not_abominable</span> <span class="special">=</span> <span class="identifier">ct</span><span class="special">::</span><span class="identifier">remove_function_const</span><span class="special"><</span><span class="identifier">fn</span><span class="special">>;</span>
|
|
<span class="keyword">using</span> <span class="identifier">expected_fn2</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">int</span><span class="special">&&,</span> <span class="keyword">const</span> <span class="keyword">int</span><span class="special">&,</span> <span class="keyword">void</span><span class="special">*);</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span><span class="special"><</span><span class="identifier">not_abominable</span><span class="special">,</span> <span class="identifier">expected_fn2</span><span class="special">>::</span><span class="identifier">value</span><span class="special">,</span> <span class="string">""</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="callable_traits.introduction.basic_concepts"></a><a class="link" href="index.html#callable_traits.introduction.basic_concepts" title="Concept Definitions">Concept
|
|
Definitions</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
<code class="literal">CallableTraits</code> relies on the following concepts, and will
|
|
be referenced throughout this documentation:
|
|
</p>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h0"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_fn_ptr"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_fn_ptr"><span class="green">FunctionPtr</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any function pointer type
|
|
</li>
|
|
<li class="listitem">
|
|
the pointer may be cv-qualified and/or ref-qualified
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. <code class="computeroutput"><span class="keyword">void</span><span class="special">(*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span></code> or
|
|
<code class="computeroutput"><span class="keyword">void</span><span class="special">(*</span>
|
|
<span class="keyword">const</span> <span class="special">&)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h1"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_fn_ref"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_fn_ref"><span class="green">FunctionReference</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any function reference type
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. <code class="computeroutput"><span class="keyword">void</span><span class="special">(&)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h2"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_fn"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_fn"><span class="green">Function</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any unqualified function type
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. <code class="computeroutput"><span class="keyword">void</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h3"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_abominable"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_abominable"><span class="green">AbominableFunction</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any qualified (a.k.a. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0172r0.html" target="_top">"abominable"</a>)
|
|
function type
|
|
</li>
|
|
<li class="listitem">
|
|
Not technically "callable", but still falls under the <code class="literal">CallableTraits</code>
|
|
umbrella
|
|
</li>
|
|
<li class="listitem">
|
|
Mutually exclusive with <a class="link" href=""><span class="green">Function</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. <code class="computeroutput"><span class="keyword">void</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h4"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_pmf"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_pmf"><span class="green">MemberFunctionPtr</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any pointer to member function type
|
|
</li>
|
|
<li class="listitem">
|
|
The pointer type may be cv-qualified and/or ref-qualified
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. <code class="computeroutput"><span class="keyword">void</span> <span class="special">(</span><span class="identifier">foo</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h5"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_pmd"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_pmd"><span class="green">MemberDataPtr</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any pointer to data member type
|
|
</li>
|
|
<li class="listitem">
|
|
The pointer type may be cv-qualified and/or ref-qualified
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. <code class="computeroutput"><span class="keyword">int</span> <span class="identifier">foo</span><span class="special">::*</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h6"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_simple_fn_obj"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_simple_fn_obj"><span class="green">SimpleFunctionObject</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any class/struct with a <span class="emphasis"><em>non-templated, non-overloaded</em></span>
|
|
function call operator
|
|
</li>
|
|
<li class="listitem">
|
|
Includes non-generic lambda types
|
|
</li>
|
|
<li class="listitem">
|
|
May be cv-qualified and/or ref-qualified.
|
|
</li>
|
|
<li class="listitem">
|
|
Mutually exclusive with <a class="link" href=""><span class="green">OverloadedFunctionObject</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. the type of this lambda: <code class="computeroutput"><span class="special">[](</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span> <span class="special">}</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h7"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_overloaded_fn_obj"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_overloaded_fn_obj"><span class="green">OverloadedFunctionObject</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Any class/struct with a <span class="emphasis"><em>templated or overloaded</em></span>
|
|
function call operator, with the following limitation for those with
|
|
templated function call operators (which includes generic lambdas):
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">
|
|
If templated , all instantiations must be <a href="http://stackoverflow.com/questions/35033306/what-does-it-mean-when-one-says-something-is-sfinae-friendly" target="_top">SFINAE-friendly</a>,
|
|
and must not use <a href="http://en.cppreference.com/w/cpp/language/indent_name" target="_top">dependent
|
|
names</a>, except where the dependent "names" are
|
|
C++ operators.
|
|
</li></ul></div>
|
|
</li>
|
|
<li class="listitem">
|
|
May be cv-qualified and/or ref-qualified
|
|
</li>
|
|
<li class="listitem">
|
|
e.g. the type of this generic lambda: <code class="computeroutput"><span class="special">[](</span><span class="keyword">auto</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">auto</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span> <span class="special">}</span></code>
|
|
</li>
|
|
</ul></div>
|
|
<div class="tip"><table border="0" summary="Tip">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../src/images/tip.png"></td>
|
|
<th align="left">Tip</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
Generic lambdas or classes with templated function objects that are either
|
|
not SFINAE-friendly or rely on dependent names for template instantiations
|
|
are generally incompatible with <code class="literal">CallableTraits</code>.
|
|
</p></td></tr>
|
|
</table></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h8"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_fn_obj"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_fn_obj"><span class="green">FunctionObject</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
|
Any type that is either an <a class="link" href=""><span class="green">OverloadedFunctionObject</span></a> or a <a class="link" href=""><span class="green">SimpleFunctionObject</span></a>
|
|
</li></ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h9"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_callable"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_callable"><span class="green">Callable</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
|
The superset of the following:
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">FunctionPtr</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">FunctionReference</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">Function</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">AbominableFunction</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">MemberFunctionPtr</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">MemberDataPtr</span></a>
|
|
</li>
|
|
<li class="listitem">
|
|
<a class="link" href=""><span class="green">FunctionObject</span></a>
|
|
</li>
|
|
</ul></div>
|
|
</li></ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h10"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_simple_callable"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_simple_callable">[<span class="green">SimpleCallable</span>]</a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
|
Includes all <a class="link" href=""><span class="green">Callable</span></a>
|
|
types, <span class="bold"><strong>except</strong></span> for <a class="link" href=""><span class="green">OverloadedFunctionObject</span></a>
|
|
</li></ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h11"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_simple_invokable"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_simple_invokable"><span class="green">SimpleInvokable</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
|
Includes all <a class="link" href=""><span class="green">Callable</span></a>
|
|
types, <span class="bold"><strong>except</strong></span> for <a class="link" href=""><span class="green">OverloadedFunctionObject</span></a>, <a class="link" href=""><span class="green">Function</span></a>, and <a class="link" href=""><span class="green">AbominableFunction</span></a>
|
|
</li></ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h12"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_invokable"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_invokable"><span class="green">Invokable</span></a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
|
Includes all <a class="link" href=""><span class="green">Callable</span></a>
|
|
types, <span class="bold"><strong>except</strong></span> for <a class="link" href=""><span class="green">Function</span></a> and <a class="link" href=""><span class="green">AbominableFunction</span></a>
|
|
</li></ul></div>
|
|
<h5>
|
|
<a name="callable_traits.introduction.basic_concepts.h13"></a>
|
|
<span class="phrase"><a name="callable_traits.introduction.basic_concepts.ref_constexpr_constructble"></a></span><a class="link" href="index.html#callable_traits.introduction.basic_concepts.ref_constexpr_constructble">[constexpr_constructble]</a>
|
|
</h5>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
|
Any <a href="http://en.cppreference.com/w/cpp/concept/LiteralType" target="_top">LiteralType</a>
|
|
that is also default-constructible
|
|
</li></ul></div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="callable_traits.introduction.reasons"></a><a class="link" href="index.html#callable_traits.introduction.reasons" title="Why use CallableTraits?">Why use <code class="literal">CallableTraits</code>?</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
<span class="bold"><strong>1.</strong></span> <code class="literal">CallableTraits</code> offers
|
|
template aliases such as <code class="computeroutput"><span class="identifier">remove_function_const</span></code>
|
|
for manipulating function qualifiers, designed to parallel the <code class="computeroutput"><span class="special"><</span><span class="identifier">type_traits</span><span class="special">></span></code> aliases such as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_const_t</span></code>.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>2.</strong></span> <code class="literal">CallableTraits</code> is
|
|
designed to accept cv-qualified and ref-qualified types, which eliminates
|
|
the need to prepare template argument types with metafunctions such as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference</span></code>
|
|
and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">decay</span></code>. This is especially useful when dealing
|
|
with perfectly-forwarded parameter types in function templates.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>3.</strong></span> <code class="literal">CallableTraits</code> is
|
|
designed in terms of the <a href="http://en.cppreference.com/w/cpp/utility/functional/invoke" target="_top">INVOKE</a>
|
|
rules, with one unobtrusive and beneficial deviation: <span class="green">Function</span>
|
|
types and <span class="green">AbominableFunction</span> types are compatible
|
|
with all operations that do not specifically require an invocation.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>4.</strong></span> <code class="literal">callable_traits::</code><code class="computeroutput"><span class="identifier">arg_at</span><span class="special"><</span><span class="number">2</span><span class="special">,</span> <span class="identifier">Callable</span><span class="special">></span></code> is both more flexible and more readable
|
|
than <code class="computeroutput"><span class="keyword">typename</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">function_traits</span><span class="special"><</span><span class="identifier">Callable</span><span class="special">>::</span><span class="identifier">arg3_type</span></code>.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>5.</strong></span> <code class="literal">callable_traits::</code><code class="computeroutput"><span class="identifier">can_invoke</span></code> can be used to test <code class="computeroutput"><span class="identifier">INVOKE</span></code>-ability at compile-time, with value
|
|
semantics. For the craziest metaprogrammers, <code class="literal">callable_traits::</code><code class="computeroutput"><span class="identifier">can_invoke_constexpr</span></code> does the same as
|
|
<code class="computeroutput"><span class="identifier">can_invoke</span></code> for <span class="green">ConstexprDefaultConstructible</span>
|
|
types, with an added check for <code class="computeroutput"><span class="keyword">constexpr</span></code>-ness
|
|
(Note: for <code class="computeroutput"><span class="identifier">can_invoke_constexpr</span></code>,
|
|
argument types must also be <span class="green">ConstexprDefaultConstructible</span>)
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>6.</strong></span> <code class="literal">callable_traits::</code><code class="computeroutput"><span class="identifier">is_constexpr</span></code> can be used to check whether
|
|
a <span class="green">ConstexprDefaultConstructible</span> type is a
|
|
<span class="green">Callable</span> type that yields a <code class="computeroutput"><span class="keyword">constexpr</span></code>
|
|
result -- no arguments necessary.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>7.</strong></span> <code class="literal">callable_traits::</code><code class="computeroutput"><span class="identifier">bind</span></code> can be used by library writers to
|
|
easily accept <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">placeholder</span></code> expressions anywhere, and "intercept"
|
|
the type information before forwarding to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span></code>
|
|
or <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span></code>. This allows for more flexible APIs,
|
|
where a function template taking a "callable type" can be overloaded
|
|
to also accept placeholder expressions. It's perhaps a small improvement
|
|
from requiring <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span></code> first, but in API design, even the
|
|
smallest things count. See
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>8.</strong></span> <code class="literal">callable_traits::</code><code class="computeroutput"><span class="identifier">min_arity</span></code> can be used to detect the presence
|
|
of default arguments on a <span class="green">SimpleFunctionObject</span>
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>9.</strong></span> The <code class="literal">CallableTraits</code>
|
|
interface mainly consists of template aliases and <code class="computeroutput"><span class="keyword">constexpr</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">integral_constant</span></code> functions, which are
|
|
arguably preferable to <code class="computeroutput"><span class="keyword">typename</span> <span class="identifier">foo</span><span class="special">::</span><span class="identifier">type</span></code>
|
|
and <code class="computeroutput"><span class="identifier">foo</span><span class="special">::</span><span class="identifier">value</span></code>. While the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">integral_constant</span></code>
|
|
functions in <code class="literal">CallableTraits</code> may be a deviation from traditional
|
|
type trait designs, they facilitate a metaprogramming style that uses value-semantics
|
|
(a la <a href="https://boostorg.github.io/hana/" target="_top"><code class="literal">Boost.Hana</code></a>).
|
|
The functions can generally be used with either types or values, which eliminates
|
|
unnecessary <code class="computeroutput"><span class="keyword">decltype</span></code> usage.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>10.</strong></span> <code class="literal">CallableTraits</code> includes
|
|
optional features for the manipulation and inspection of calling conventions.
|
|
These features are currently deemed experimental, because they greatly increase
|
|
the test surface of <code class="literal">CallableTraits</code>, are platform-specific,
|
|
and are not yet fully tested on any platform.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="callable_traits.introduction.function_sugar"></a><a class="link" href="index.html#callable_traits.introduction.function_sugar" title="Use case:std::function sugar">Use case:<code class="literal">std::function</code>
|
|
sugar</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
At the time of this writing, there are around 260 <a href="http://stackoverflow.com/search?q=convert+std%3A%3Abind+to+std%3A%3Afunction" target="_top">search
|
|
results</a> on Stack Overflow concerning the conversion from <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span></code>
|
|
to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code>. There are roughly 340 <a href="http://stackoverflow.com/search?q=convert+lambda+to+std%3A%3Afunction" target="_top">search
|
|
results</a> concerning the conversion of lambdas to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code>.
|
|
In the example below, we'll kill both birds with the same stone. The <code class="computeroutput"><span class="identifier">make_function</span></code> function will leverage <code class="literal">CallableTraits</code>
|
|
to...
|
|
</p>
|
|
<div class="orderedlist"><ol class="orderedlist" type="1">
|
|
<li class="listitem">
|
|
Create an <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
|
where T is not explicitly supplied by the user
|
|
</li>
|
|
<li class="listitem">
|
|
Create an <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
|
where T is the deduced "signature" of an <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">placeholders</span></code>
|
|
expression.
|
|
</li>
|
|
</ol></div>
|
|
<p>
|
|
Without real-world context, <code class="computeroutput"><span class="identifier">make_function</span></code>
|
|
may seem rather silly to those who know the runtime costs of type erasure.
|
|
However, whenever <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code> is required by some 3rd party
|
|
API, this example might make a bit more sense.
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">functional</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">bind</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
|
|
<span class="keyword">namespace</span> <span class="identifier">example_library</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">// make_function turns a non-overloaded callable into a type-erased std::function object</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">inline</span> <span class="keyword">decltype</span><span class="special">(</span><span class="keyword">auto</span><span class="special">)</span> <span class="identifier">make_function</span><span class="special">(</span><span class="identifier">T</span><span class="special">&&</span> <span class="identifier">t</span><span class="special">)</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// callable_traits::function_type decays any non-overloaded callable type to</span>
|
|
<span class="comment">// a plain function type, which is structured in terms of INVOKE.</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">signature</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">T</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">function</span><span class="special"><</span><span class="identifier">signature</span><span class="special">>;</span>
|
|
<span class="keyword">return</span> <span class="identifier">result_type</span><span class="special">{</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">t</span><span class="special">)</span> <span class="special">};</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// this make_function overload turns a bind expression into a type-erased std::function object</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">First</span><span class="special">,</span> <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Others</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">make_function</span><span class="special">(</span><span class="identifier">T</span><span class="special">&&</span> <span class="identifier">t</span><span class="special">,</span> <span class="identifier">First</span><span class="special">&&</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">Others</span><span class="special">&&...</span> <span class="identifier">others</span><span class="special">)</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// callable_traits::bind is essentially a compile-time parser of placeholder</span>
|
|
<span class="comment">// expressions, for the purpose of retaining more type information than</span>
|
|
<span class="comment">// std::bind normally allows - specifically, callable_traits::bind is used to</span>
|
|
<span class="comment">// determine the de-facto signature of the std::bind return type, with special</span>
|
|
<span class="comment">// considerations for conversions between reused placeholders and nested</span>
|
|
<span class="comment">// placeholder expressions. For the sake of convenience, callable_traits::bind</span>
|
|
<span class="comment">// is also a thin forwarding wrapper around std::bind (which is the only true</span>
|
|
<span class="comment">// runtime element in CallableTraits).</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">bind_expr</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span><span class="identifier">ct</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">t</span><span class="special">),</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">First</span><span class="special">>(</span><span class="identifier">first</span><span class="special">),</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">Others</span><span class="special">>(</span><span class="identifier">others</span><span class="special">)...</span>
|
|
<span class="special">));</span>
|
|
|
|
<span class="keyword">using</span> <span class="identifier">signature</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">bind_expr</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">function</span><span class="special"><</span><span class="identifier">signature</span><span class="special">>;</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">result_type</span><span class="special">{</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">t</span><span class="special">),</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">First</span><span class="special">>(</span><span class="identifier">first</span><span class="special">),</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">Others</span><span class="special">>(</span><span class="identifier">others</span><span class="special">)...</span>
|
|
<span class="special">)};</span>
|
|
<span class="special">}</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// client code starts here</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span>
|
|
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">example_library</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">placeholders</span><span class="special">;</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">add</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">j</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">i</span> <span class="special">+</span> <span class="identifier">j</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">struct</span> <span class="identifier">adder</span> <span class="special">{</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">eval</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">j</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">i</span> <span class="special">+</span> <span class="identifier">j</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
|
|
|
|
<span class="comment">// function pointer</span>
|
|
<span class="keyword">auto</span> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">make_function</span><span class="special">(&</span><span class="identifier">add</span><span class="special">);</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">f</span><span class="special">(</span><span class="number">99</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span> <span class="special">==</span> <span class="number">100</span><span class="special">);</span>
|
|
|
|
<span class="comment">// function reference</span>
|
|
<span class="identifier">f</span> <span class="special">=</span> <span class="identifier">make_function</span><span class="special">(</span><span class="identifier">add</span><span class="special">);</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">f</span><span class="special">(</span><span class="number">99</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span> <span class="special">==</span> <span class="number">100</span><span class="special">);</span>
|
|
|
|
<span class="comment">// member function pointer (bound to object)</span>
|
|
<span class="identifier">f</span> <span class="special">=</span> <span class="identifier">make_function</span><span class="special">(&</span><span class="identifier">adder</span><span class="special">::</span><span class="identifier">eval</span><span class="special">,</span> <span class="identifier">adder</span><span class="special">{},</span> <span class="identifier">_1</span><span class="special">,</span> <span class="identifier">_2</span><span class="special">);</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">f</span><span class="special">(</span><span class="number">99</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span> <span class="special">==</span> <span class="number">100</span><span class="special">);</span>
|
|
|
|
<span class="comment">// lambda</span>
|
|
<span class="identifier">f</span> <span class="special">=</span> <span class="identifier">make_function</span><span class="special">([](</span><span class="keyword">int</span> <span class="identifier">i</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">j</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">return</span> <span class="identifier">i</span> <span class="special">+</span> <span class="identifier">j</span><span class="special">;</span>
|
|
<span class="special">});</span>
|
|
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">f</span><span class="special">(</span><span class="number">99</span><span class="special">,</span> <span class="number">1</span><span class="special">)</span> <span class="special">==</span> <span class="number">100</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
</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/ref.html"><img src="../src/images/next.png" alt="Next"></a></div>
|
|
</body>
|
|
</html>
|