mirror of
https://github.com/boostorg/utility.git
synced 2025-07-29 12:27:45 +02:00
Compare commits
36 Commits
boost-1.49
...
boost-1.52
Author | SHA1 | Date | |
---|---|---|---|
9dc0cc931d | |||
b35ef27b35 | |||
124f4ea879 | |||
0f43c44e97 | |||
7d8353f46a | |||
1920623a4f | |||
c0cca9e8cc | |||
d63444f22e | |||
1f23425baa | |||
a89b0101fc | |||
fb2d391928 | |||
ad5cf8cf08 | |||
2fc827ad23 | |||
88e7d86270 | |||
6b9f0103d5 | |||
7aa68731b4 | |||
ef0f82f62b | |||
9a16aaa2b9 | |||
e763315b55 | |||
87b3643647 | |||
fe653d0a9a | |||
26b39384e3 | |||
9525d062b3 | |||
6d196c4244 | |||
e83682c091 | |||
1d146d010a | |||
5684a2f2b3 | |||
95d2c38379 | |||
7d23c75eef | |||
3279399fe3 | |||
87875cadda | |||
c58748cfd9 | |||
58bb88d4bd | |||
11d50ecb9f | |||
636283d7c2 | |||
1df0bf80bc |
@ -1,7 +1,6 @@
|
||||
[/
|
||||
/ Copyright (c) 2008 Howard Hinnant
|
||||
/ Copyright (c) 2008 Beman Dawes
|
||||
/ Copyright (c) 2009-20010 Vicente J. Botet Escriba
|
||||
/ Copyright (c) 2009-20012 Vicente J. Botet Escriba
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -10,11 +9,9 @@
|
||||
[article Declval
|
||||
[quickbook 1.5]
|
||||
[authors [Hinnant, Howard]]
|
||||
[authors [Dawes, Beman]]
|
||||
[authors [Botet Escriba, Vicente J.]]
|
||||
[copyright 2008 Howard Hinnant]
|
||||
[copyright 2008 Beman Dawes]
|
||||
[copyright 2009-2010 Vicente J. Botet Escriba]
|
||||
[copyright 2009-2012 Vicente J. Botet Escriba]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -59,9 +56,9 @@ T is an lvalue-reference, otherwise an rvalue. To extend the domain of this func
|
||||
typename std::add_rvalue_reference<T>::type declval(); // not used
|
||||
|
||||
which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()`
|
||||
already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C==0x standard.
|
||||
already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard.
|
||||
|
||||
The provision of a new library component that allows the production of values in unevaluated expressions is considered as
|
||||
The provision of a new library component that allows the production of values in unevaluated expressions is considered
|
||||
important to realize constrained templates in C++0x where concepts are not available.
|
||||
This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer.
|
||||
|
||||
@ -77,7 +74,7 @@ This extremely light-weight function is expected to be part of the daily tool-bo
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval(); //noexcept; // as unevaluated operand
|
||||
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@ -96,9 +93,23 @@ The library provides the function template declval to simplify the definition of
|
||||
template <class To, class From>
|
||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
||||
|
||||
Declares a function template convert which only participats in overloading if the type From can be explicitly converted to type To.
|
||||
Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.50]
|
||||
|
||||
Fixes:
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Declval</title>
|
||||
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.74.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.76.0">
|
||||
<link rel="home" href="declval.html" title="Declval">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@ -17,7 +17,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
<div class="article" lang="en">
|
||||
<div class="article">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div><h2 class="title">
|
||||
@ -27,17 +27,13 @@
|
||||
<span class="firstname">Howard</span> <span class="surname">Hinnant</span>
|
||||
</h3></div>
|
||||
<div class="author"><h3 class="author">
|
||||
<span class="firstname">Beman</span> <span class="surname">Dawes</span>
|
||||
</h3></div>
|
||||
<div class="author"><h3 class="author">
|
||||
<span class="firstname">Vicente J.</span> <span class="surname">Botet Escriba</span>
|
||||
</h3></div>
|
||||
</div></div>
|
||||
<div><p class="copyright">Copyright © 2008 Howard Hinnant</p></div>
|
||||
<div><p class="copyright">Copyright © 2008 Beman Dawes</p></div>
|
||||
<div><p class="copyright">Copyright © 2009 -2010 Vicente J. Botet Escriba</p></div>
|
||||
<div><p class="copyright">Copyright © 2009 -2012 Vicente J. Botet Escriba</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id879409"></a><p>
|
||||
<a name="idp13449552"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
@ -49,10 +45,11 @@
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="declval.html#declval.overview">Overview</a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.reference"> Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.reference">Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="declval.html#declval.history">History</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.overview"></a><a class="link" href="declval.html#declval.overview" title="Overview">Overview</a>
|
||||
</h2></div></div></div>
|
||||
@ -103,18 +100,18 @@
|
||||
which ensures that we can also use cv void as template parameter. The careful
|
||||
reader might have noticed that <code class="computeroutput"><span class="identifier">declval</span><span class="special">()</span></code> already exists under the name create() as
|
||||
part of the definition of the semantics of the type trait is_convertible in
|
||||
the C==0x standard.
|
||||
the C++0x standard.
|
||||
</p>
|
||||
<p>
|
||||
The provision of a new library component that allows the production of values
|
||||
in unevaluated expressions is considered as important to realize constrained
|
||||
templates in C++0x where concepts are not available. This extremely light-weight
|
||||
function is expected to be part of the daily tool-box of the C++0x programmer.
|
||||
in unevaluated expressions is considered important to realize constrained templates
|
||||
in C++0x where concepts are not available. This extremely light-weight function
|
||||
is expected to be part of the daily tool-box of the C++0x programmer.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.reference"></a><a class="link" href="declval.html#declval.reference" title="Reference"> Reference </a>
|
||||
<a name="declval.reference"></a><a class="link" href="declval.html#declval.reference" title="Reference">Reference </a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">declval</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>
|
||||
@ -122,7 +119,7 @@
|
||||
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">();</span> <span class="comment">//noexcept; // as unevaluated operand
|
||||
<span class="keyword">typename</span> <span class="identifier">add_rvalue_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">declval</span><span class="special">()</span> <span class="identifier">noexcept</span><span class="special">;</span> <span class="comment">// as unevaluated operand
|
||||
</span>
|
||||
<span class="special">}</span> <span class="comment">// namespace boost
|
||||
</span></pre>
|
||||
@ -148,13 +145,29 @@
|
||||
<span class="identifier">decltype</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">To</span><span class="special">>(</span><span class="identifier">declval</span><span class="special"><</span><span class="identifier">From</span><span class="special">>()))</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">From</span><span class="special">&&);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Declares a function template convert which only participats in overloading
|
||||
Declares a function template convert which only participates in overloading
|
||||
if the type From can be explicitly converted to type To.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="declval.history"></a><a class="link" href="declval.html#declval.history" title="History">History</a>
|
||||
</h2></div></div></div>
|
||||
<a name="declval.history.boost_1_50"></a><h4>
|
||||
<a name="idp13553216"></a>
|
||||
<a class="link" href="declval.html#declval.history.boost_1_50">boost 1.50</a>
|
||||
</h4>
|
||||
<p>
|
||||
Fixes:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
|
||||
<a href="http://svn.boost.org/trac/boost/ticket/6570" target="_top">#6570</a>
|
||||
Adding noexcept to boost::declval.
|
||||
</li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: September 16, 2010 at 16:19:10 GMT</small></p></td>
|
||||
<td align="left"><p><small>Last revised: May 28, 2012 at 18:59:06 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
44
identity_type/doc/Jamfile.v2
Normal file
44
identity_type/doc/Jamfile.v2
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
# Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
# Distributed under the Boost Software License, Version 1.0
|
||||
# (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
import quickbook ;
|
||||
using boostbook ;
|
||||
|
||||
doxygen reference : ../../../../boost/utility/identity_type.hpp
|
||||
: <reftitle>"Reference"
|
||||
<doxygen:param>PREDEFINED="DOXYGEN"
|
||||
<doxygen:param>QUIET=YES
|
||||
<doxygen:param>WARN_IF_UNDOCUMENTED=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>HIDE_UNDOC_CLASSES=YES
|
||||
<doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{2}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
|
||||
;
|
||||
|
||||
# This target must be called "index" so to generate "index.html" file.
|
||||
xml index : identity_type.qbk : <dependency>reference ;
|
||||
|
||||
boostbook doc : index
|
||||
: <location>html
|
||||
<format>onehtml
|
||||
<xsl:param>toc.section.depth=0
|
||||
<xsl:param>html.stylesheet=../../../../../doc/src/boostbook.css
|
||||
<xsl:param>boost.root=../../../../..
|
||||
;
|
||||
|
||||
#
|
||||
# This is very imperfect - it results in both html and pdf docs being built,
|
||||
# for some reason I can't get the "onehtml" format specified above to play nice
|
||||
# with the usual incantations for mixed pdf/html builds. JM 06/2012.
|
||||
#
|
||||
boostbook pdf_doc : index
|
||||
:
|
||||
<format>pdf
|
||||
<format>html:<build>no
|
||||
;
|
||||
|
||||
install pdf_doc_install : pdf_doc : <location>. <name>identity_type.pdf <install-type>PDF ;
|
||||
explicit pdf_doc_install ;
|
252
identity_type/doc/html/index.html
Normal file
252
identity_type/doc/html/index.html
Normal file
@ -0,0 +1,252 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Boost.Utility/IdentityType 1.0.0</title><link rel="stylesheet" type="text/css" href="../../../../../doc/src/boostbook.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" title="Boost.Utility/IdentityType 1.0.0"><div class="titlepage"><div><div><h2 class="title"><a name="boost_utility_identitytype"></a>Boost.Utility/IdentityType 1.0.0</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Lorenzo</span> <span class="surname">Caminiti <code class="email"><<a class="email" href="mailto:lorcaminiti@gmail.com">lorcaminiti@gmail.com</a>></code></span></h3></div></div><div><p class="copyright">Copyright © 2009-2012 Lorenzo
|
||||
Caminiti</p></div><div><div class="legalnotice" title="Legal Notice"><a name="boost_utility_identitytype.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
||||
file LICENSE_1_0.txt or a 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></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#boost_utility_identitytype.motivation">Motivation</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.solution">Solution</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.templates">Templates</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.abstract_types">Abstract Types</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__usage">Annex: Usage</a></span></dt><dt><span class="section"><a href="#boost_utility_identitytype.annex__implementation">Annex:
|
||||
Implementation</a></span></dt><dt><span class="section"><a href="#reference">Reference</a></span></dt></dl></div><p>
|
||||
This library allows to wrap types within round parenthesis so they can always
|
||||
be passed as macro parameters.
|
||||
</p><div class="section boost_utility_identitytype_motivation" title="Motivation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.motivation"></a><a class="link" href="#boost_utility_identitytype.motivation" title="Motivation">Motivation</a></h2></div></div></div><p>
|
||||
Consider the following macro which declares a variable named <code class="computeroutput"><span class="identifier">var</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
|
||||
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
|
||||
<a href="../../test/var_error.cpp" target="_top"><code class="literal">var_error.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">VAR</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">var</span> <span class="error">#</span><span class="preprocessor"># n</span>
|
||||
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="number">1</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>,</span> <span class="number">2</span><span class="special">);</span> <span class="comment">// Error.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
The first macro invocation works correctly declaring a variable named <code class="computeroutput"><span class="identifier">var1</span></code> of type <code class="computeroutput"><span class="keyword">int</span></code>.
|
||||
However, the second macro invocation fails generating a preprocessor error
|
||||
similar to the following:
|
||||
</p><pre class="programlisting">error: macro "VAR" passed 3 arguments, but takes just 2
|
||||
</pre><p>
|
||||
That is because the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code> type passed as the first macro parameter
|
||||
contains a comma <code class="computeroutput"><span class="special">,</span></code> not wrapped
|
||||
by round parenthesis <code class="computeroutput"><span class="special">()</span></code>. The preprocessor
|
||||
interprets that unwrapped comma as a separation between macro parameters concluding
|
||||
that a total of three (and not two) parameters are passed to the macro in the
|
||||
following order:
|
||||
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span></code>
|
||||
</li><li class="listitem">
|
||||
<code class="computeroutput"><span class="keyword">char</span><span class="special">></span></code>
|
||||
</li><li class="listitem">
|
||||
<code class="computeroutput"><span class="number">2</span></code>
|
||||
</li></ol></div><p>
|
||||
Note that, differently from the compiler, the preprocessor only recognizes
|
||||
round parenthesis <code class="computeroutput"><span class="special">()</span></code>. Angular
|
||||
<code class="computeroutput"><span class="special"><></span></code> and squared <code class="computeroutput"><span class="special">[]</span></code> parenthesis are not recognized by the preprocessor
|
||||
when parsing macro parameters.
|
||||
</p></div><div class="section boost_utility_identitytype_solution" title="Solution"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.solution"></a><a class="link" href="#boost_utility_identitytype.solution" title="Solution">Solution</a></h2></div></div></div><p>
|
||||
In some cases, it might be possible to workaround this issue by avoiding to
|
||||
pass the type expression to the macro all together. For example, in the case
|
||||
above a <code class="computeroutput"><span class="keyword">typedef</span></code> could have been
|
||||
used to specify the type expression with the commas outside the macro (see
|
||||
also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="identifier">map_type</span><span class="special">;</span>
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">map_type</span><span class="special">,</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
When this is neither possible nor desired (e.g., see the function template
|
||||
<code class="computeroutput"><span class="identifier">f</span></code> in the section below), this
|
||||
library header <code class="computeroutput"><a class="link" href="#header.boost.utility.identity_type_hpp" title="Header <boost/utility/identity_type.hpp>">boost/utility/identity_type.hpp</a></code>
|
||||
defines a macro <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
which can be used to workaround the issue while keeping the type expression
|
||||
as one of the macro parameters (see also <a href="../../test/var.cpp" target="_top"><code class="literal">var.cpp</code></a>).
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">identity_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
|
||||
<span class="identifier">VAR</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>)),</span> <span class="number">4</span><span class="special">);</span> <span class="comment">// OK.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
|
||||
expands to an expression that evaluates (at compile-time) to the specified
|
||||
type. The specified type is never split into multiple macro parameters because
|
||||
it is always wrapped by a set of extra round parenthesis <code class="computeroutput"><span class="special">()</span></code>.
|
||||
In fact, a total of two sets of round parenthesis must be used: The parenthesis
|
||||
to invoke the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(...)</span></code> plus the inner parenthesis to wrap the
|
||||
type passed to the macro <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((...))</span></code>.
|
||||
</p><p>
|
||||
This macro works on any <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/standards" target="_top">C++03</a>
|
||||
compiler (and it does not use <a href="http://en.wikipedia.org/wiki/Variadic_macro" target="_top">variadic
|
||||
macros</a>). <sup>[<a name="boost_utility_identitytype.solution.f0" href="#ftn.boost_utility_identitytype.solution.f0" class="footnote">1</a>]</sup> The authors originally developed and tested this library using
|
||||
GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled
|
||||
<code class="computeroutput"><span class="special">-</span><span class="identifier">std</span><span class="special">=</span><span class="identifier">c</span><span class="special">++</span><span class="number">0</span><span class="identifier">x</span></code>) on Cygwin
|
||||
and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. See the library <a href="http://www.boost.org/development/tests/release/developer/utility-identity_type.html" target="_top">regressions
|
||||
test results</a> for more information on supported compilers and platforms.
|
||||
</p></div><div class="section boost_utility_identitytype_templates" title="Templates"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.templates"></a><a class="link" href="#boost_utility_identitytype.templates" title="Templates">Templates</a></h2></div></div></div><p>
|
||||
This macro must be prefixed by <code class="computeroutput"><span class="keyword">typename</span></code>
|
||||
when used within templates. For example, let's program a macro that declares
|
||||
a function parameter named <code class="computeroutput"><span class="identifier">arg</span></code><code class="literal"><span class="emphasis"><em>n</em></span></code>
|
||||
with the specified <code class="literal"><span class="emphasis"><em>type</em></span></code> (see also
|
||||
<a href="../../test/template.cpp" target="_top"><code class="literal">template.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ARG</span><span class="special">(</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span> <span class="identifier">type</span> <span class="identifier">arg</span> <span class="error">#</span><span class="preprocessor"># n</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span> <span class="comment">// Prefix macro with `typename` in templates.</span>
|
||||
<span class="identifier">ARG</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">>)),</span> <span class="number">1</span><span class="special">)</span>
|
||||
<span class="special">)</span> <span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="identifier">a</span><span class="special">;</span>
|
||||
<span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">=</span> <span class="char">'a'</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">f</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
|
||||
<span class="comment">// f(a); // ... but error.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
However, note that the template parameter <code class="computeroutput"><span class="keyword">char</span></code>
|
||||
must be manually specified when invoking the function as in <code class="computeroutput"><span class="identifier">f</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span></code>. In fact,
|
||||
when the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
macro is used to wrap a function template parameter, the template parameter
|
||||
can no longer be automatically deduced by the compiler form the function call
|
||||
as <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code> would
|
||||
have done. <sup>[<a name="boost_utility_identitytype.templates.f0" href="#ftn.boost_utility_identitytype.templates.f0" class="footnote">2</a>]</sup> (This limitation does not apply to class templates because class
|
||||
template parameters must always be explicitly specified.) In other words, without
|
||||
using the <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
macro, C++ would normally be able to automatically deduce the function template
|
||||
parameter as shown below:
|
||||
</p><p>
|
||||
</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">void</span> <span class="identifier">g</span><span class="special">(</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">T</span><span class="special">></span> <span class="identifier">arg1</span>
|
||||
<span class="special">)</span> <span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">g</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// OK...</span>
|
||||
<span class="identifier">g</span><span class="special">(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// ... and also OK.</span>
|
||||
</pre><p>
|
||||
</p></div><div class="section boost_utility_identitytype_abstract_types" title="Abstract Types"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.abstract_types"></a><a class="link" href="#boost_utility_identitytype.abstract_types" title="Abstract Types">Abstract Types</a></h2></div></div></div><p>
|
||||
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes
|
||||
with one or more pure virtual functions) generates a compiler error. This can
|
||||
be avoided by manipulating the type adding and removing a reference to it.
|
||||
</p><p>
|
||||
Let's program a macro that performs a static assertion on a <a href="http://en.wikipedia.org/wiki/Template_metaprogramming" target="_top">Template
|
||||
Meta-Programming</a> (TMP) meta-function (similarly to Boost.MPL <a href="http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html" target="_top"><code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code></a>). The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro can be used
|
||||
to pass a meta-function with multiple template parameters to the assert macro
|
||||
(so to handle the commas separating the template parameters). In this case,
|
||||
if the meta-function is an abstract type, it needs to be manipulated adding
|
||||
and removing a reference to it (see also <a href="../../test/abstract.cpp" target="_top"><code class="literal">abstract.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">b</span><span class="special">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">abstract</span> <span class="special">{</span>
|
||||
<span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">value</span> <span class="special">=</span> <span class="identifier">b</span><span class="special">;</span>
|
||||
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// Pure virtual function.</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="identifier">TMP_ASSERT</span><span class="special">(</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">remove_reference</span><span class="special"><</span> <span class="comment">// Add and remove</span>
|
||||
<span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span> <span class="comment">// reference for</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">add_reference</span><span class="special"><</span> <span class="comment">// abstract type.</span>
|
||||
<span class="identifier">abstract</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">true</span><span class="special">></span>
|
||||
<span class="special">>::</span><span class="identifier">type</span>
|
||||
<span class="special">))</span>
|
||||
<span class="special">>::</span><span class="identifier">type</span>
|
||||
<span class="special">);</span>
|
||||
</pre><p>
|
||||
</p></div><div class="section boost_utility_identitytype_annex__usage" title="Annex: Usage"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__usage"></a><a class="link" href="#boost_utility_identitytype.annex__usage" title="Annex: Usage">Annex: Usage</a></h2></div></div></div><p>
|
||||
The <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> macro
|
||||
can be used either when calling a user-defined macro (as shown by the examples
|
||||
so far), or internally when implementing a user-defined macro (as shown below).
|
||||
When <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code> is
|
||||
used in the implementation of the user-defined macro, the caller of the user
|
||||
macro will have to specify the extra parenthesis (see also <a href="../../test/paren.cpp" target="_top"><code class="literal">paren.cpp</code></a>):
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT_PAREN</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="comment">/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_metafunction</span><span class="special">)::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="preprocessor">#define</span> <span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span><span class="identifier">metafunction</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span>
|
||||
|
||||
<span class="comment">// Specify only extra parenthesis `((...))`.</span>
|
||||
<span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="keyword">const</span><span class="special">>));</span>
|
||||
|
||||
<span class="comment">// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.</span>
|
||||
<span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">></span> <span class="keyword">const</span><span class="special">>)));</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
However, note that the caller will <span class="emphasis"><em>always</em></span> have to specify
|
||||
the extra parenthesis even when the macro parameters contain no comma:
|
||||
</p><p>
|
||||
</p><pre class="programlisting"><span class="identifier">TMP_ASSERT_PAREN</span><span class="special">((</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">>));</span> <span class="comment">// Always extra `((...))`.</span>
|
||||
|
||||
<span class="identifier">TMP_ASSERT</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">>);</span> <span class="comment">// No extra `((...))` and no macro.</span>
|
||||
</pre><p>
|
||||
</p><p>
|
||||
In some cases, using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
in the implementation of the user-defined macro might provide the best syntax
|
||||
for the caller. For example, this is the case for <code class="computeroutput"><span class="identifier">BOOST_MPL_ASSERT</span></code>
|
||||
because the majority of template meta-programming expressions contain unwrapped
|
||||
commas so it is less confusing for the user to always specify the extra parenthesis
|
||||
<code class="computeroutput"><span class="special">((...))</span></code> instead of using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>:
|
||||
</p><pre class="programlisting"><span class="identifier">BOOST_MPL_ASSERT</span><span class="special">((</span> <span class="comment">// Natural syntax.</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">and_</span><span class="special"><</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_const</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||||
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
||||
<span class="special">></span>
|
||||
<span class="special">));</span>
|
||||
</pre><p>
|
||||
However, in other situations it might be preferable to not require the extra
|
||||
parenthesis in the common cases and handle commas as special cases using <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>. For example, this
|
||||
is the case for <a href="http://www.boost.org/libs/local_function" target="_top"><code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span></code></a> for which always
|
||||
requiring the extra parenthesis <code class="computeroutput"><span class="special">((...))</span></code>
|
||||
around the types would lead to an unnatural syntax for the local function signature:
|
||||
</p><pre class="programlisting"><span class="keyword">int</span> <span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&))</span> <span class="identifier">x</span><span class="special">,</span> <span class="special">((</span><span class="keyword">int</span><span class="special">&))</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">// Unnatural syntax.</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> <span class="identifier">BOOST_LOCAL_FUNCTION_NAME</span><span class="special">(</span><span class="identifier">add</span><span class="special">)</span>
|
||||
</pre><p>
|
||||
Instead requiring the user to specify <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
only when needed allows for the more natural syntax <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span>
|
||||
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span></code> in the common cases when the parameter types
|
||||
contain no comma (while still allowing to specify parameter types with commas
|
||||
as special cases using <code class="computeroutput"><span class="identifier">BOOST_LOCAL_FUNCTION</span><span class="special">(</span><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>))&</span>
|
||||
<span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span></code>).
|
||||
</p></div><div class="section boost_utility_identitytype_annex__implementation" title="Annex: Implementation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="boost_utility_identitytype.annex__implementation"></a><a class="link" href="#boost_utility_identitytype.annex__implementation" title="Annex: Implementation">Annex:
|
||||
Implementation</a></h2></div></div></div><p>
|
||||
The implementation of this library macro is equivalent to the following: <sup>[<a name="boost_utility_identitytype.annex__implementation.f0" href="#ftn.boost_utility_identitytype.annex__implementation.f0" class="footnote">3</a>]</sup>
|
||||
</p><pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">function_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
|
||||
<span class="preprocessor">#define</span> <span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span><span class="identifier">parenthesized_type</span><span class="special">)</span> <span class="special">\</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">function_traits</span><span class="special"><</span><span class="keyword">void</span> <span class="identifier">parenthesized_type</span><span class="special">>::</span><span class="identifier">arg1_type</span>
|
||||
</pre><p>
|
||||
Essentially, the type is wrapped between round parenthesis <code class="computeroutput"><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span>
|
||||
<span class="keyword">char</span><span class="special">>)</span></code>
|
||||
so it can be passed as a single macro parameter even if it contains commas.
|
||||
Then the parenthesized type is transformed into the type of a function returning
|
||||
<code class="computeroutput"><span class="keyword">void</span></code> and with the specified type
|
||||
as the type of the first and only argument <code class="computeroutput"><span class="keyword">void</span>
|
||||
<span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">>)</span></code>. Finally, the type of the first argument
|
||||
<code class="computeroutput"><span class="identifier">arg1_type</span></code> is extracted at compile-time
|
||||
using the <code class="computeroutput"><span class="identifier">function_traits</span></code> meta-function
|
||||
therefore obtaining the original type from the parenthesized type (effectively
|
||||
stripping the extra parenthesis from around the specified type).
|
||||
</p></div><div class="section reference" title="Reference"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="reference"></a>Reference</h2></div></div></div><div class="section header_boost_utility_identity_type_hpp" title="Header <boost/utility/identity_type.hpp>"><div class="titlepage"><div><div><h3 class="title"><a name="header.boost.utility.identity_type_hpp"></a>Header <<a href="../../../../../boost/utility/identity_type.hpp" target="_top">boost/utility/identity_type.hpp</a>></h3></div></div></div><p>Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas. </p><pre class="synopsis">
|
||||
|
||||
<a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a>(parenthesized_type)</pre><div class="refentry" title="Macro BOOST_IDENTITY_TYPE"><a name="BOOST_IDENTITY_TYPE"></a><div class="titlepage"></div><div class="refnamediv"><h2><span class="refentrytitle">Macro BOOST_IDENTITY_TYPE</span></h2><p>BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis). </p></div><h2 class="refsynopsisdiv-title">Synopsis</h2><div class="refsynopsisdiv"><pre class="synopsis"><span class="comment">// In header: <<a class="link" href="#header.boost.utility.identity_type_hpp" title="Header <boost/utility/identity_type.hpp>">boost/utility/identity_type.hpp</a>>
|
||||
|
||||
</span>BOOST_IDENTITY_TYPE(parenthesized_type)</pre></div><div class="refsect1" title="Description"><a name="id554262"></a><h2>Description</h2><p><span class="bold"><strong>Parameters:</strong></span> </p><div class="informaltable"><table class="table"><colgroup><col><col></colgroup><tbody><tr><td><span class="bold"><strong><code class="computeroutput">parenthesized_type</code></strong></span></td><td>The type expression to be passed as macro parameter wrapped by a single set of round parenthesis <code class="computeroutput">(...)</code>. This type expression can contain an arbitrary number of commas. </td></tr></tbody></table></div><p>
|
||||
</p><p>This macro works on any C++03 compiler (it does not use variadic macros).</p><p>This macro must be prefixed by <code class="computeroutput">typename</code> when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).</p><p>On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type. </p></div></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.solution.f0" href="#boost_utility_identitytype.solution.f0" class="para">1</a>] </sup>
|
||||
Using variadic macros, it would be possible to require a single set of extra
|
||||
parenthesis <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">)</span></code> instead of two <code class="computeroutput"><span class="identifier">BOOST_IDENTITY_TYPE</span><span class="special">((</span></code><code class="literal"><span class="emphasis"><em>type</em></span></code><code class="computeroutput"><span class="special">))</span></code> but variadic macros are not part of C++03
|
||||
(even if nowadays they are supported by most modern compilers and they are
|
||||
also part of C++11).
|
||||
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.templates.f0" href="#boost_utility_identitytype.templates.f0" class="para">2</a>] </sup>
|
||||
This is because the implementation of <code class="computeroutput"><a class="link" href="#BOOST_IDENTITY_TYPE" title="Macro BOOST_IDENTITY_TYPE">BOOST_IDENTITY_TYPE</a></code>
|
||||
wraps the specified type within a meta-function.
|
||||
</p></div><div class="footnote"><p><sup>[<a id="ftn.boost_utility_identitytype.annex__implementation.f0" href="#boost_utility_identitytype.annex__implementation.f0" class="para">3</a>] </sup>
|
||||
There is absolutely no guarantee that the macro is actually implemented using
|
||||
the code listed in this documentation. The listed code is for explanatory
|
||||
purposes only.
|
||||
</p></div></div></div></body></html>
|
165
identity_type/doc/identity_type.qbk
Normal file
165
identity_type/doc/identity_type.qbk
Normal file
@ -0,0 +1,165 @@
|
||||
|
||||
[/ Copyright (C) 2009-2012 Lorenzo Caminiti ]
|
||||
[/ Distributed under the Boost Software License, Version 1.0 ]
|
||||
[/ (see accompanying file LICENSE_1_0.txt or a copy at ]
|
||||
[/ http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
[/ Home at http://www.boost.org/libs/utility/identity_type ]
|
||||
|
||||
[library Boost.Utility/IdentityType
|
||||
[quickbook 1.5]
|
||||
[version 1.0.0]
|
||||
[copyright 2009-2012 Lorenzo Caminiti]
|
||||
[purpose wraps types with round parenthesis]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0
|
||||
(see accompanying file LICENSE_1_0.txt or a copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
[authors [Caminiti <email>lorcaminiti@gmail.com</email>, Lorenzo]]
|
||||
[category Utilities]
|
||||
]
|
||||
|
||||
This library allows to wrap types within round parenthesis so they can always be passed as macro parameters.
|
||||
|
||||
[import ../test/var_error.cpp]
|
||||
[import ../test/var.cpp]
|
||||
[import ../test/template.cpp]
|
||||
[import ../test/abstract.cpp]
|
||||
[import ../test/paren.cpp]
|
||||
|
||||
[section Motivation]
|
||||
|
||||
Consider the following macro which declares a variable named `var`[^['n]] with the specified [^['type]] (see also [@../../test/var_error.cpp =var_error.cpp=]):
|
||||
|
||||
[var_error]
|
||||
|
||||
The first macro invocation works correctly declaring a variable named `var1` of type `int`.
|
||||
However, the second macro invocation fails generating a preprocessor error similar to the following:
|
||||
|
||||
[pre
|
||||
error: macro "VAR" passed 3 arguments, but takes just 2
|
||||
]
|
||||
|
||||
That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`.
|
||||
The preprocessor interprets that unwrapped comma as a separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order:
|
||||
|
||||
# `std::map<int`
|
||||
# `char>`
|
||||
# `2`
|
||||
|
||||
Note that, differently from the compiler, the preprocessor only recognizes round parenthesis `()`.
|
||||
Angular `<>` and squared `[]` parenthesis are not recognized by the preprocessor when parsing macro parameters.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Solution]
|
||||
|
||||
In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together.
|
||||
For example, in the case above a `typedef` could have been used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]):
|
||||
|
||||
[var_typedef]
|
||||
|
||||
When this is neither possible nor desired (e.g., see the function template `f` in the section below), this library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]).
|
||||
|
||||
[var_ok]
|
||||
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro expands to an expression that evaluates (at compile-time) to the specified type.
|
||||
The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`.
|
||||
In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`.
|
||||
|
||||
This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (and it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]).
|
||||
[footnote
|
||||
Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11).
|
||||
]
|
||||
The authors originally developed and tested this library using GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7.
|
||||
See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for more information on supported compilers and platforms.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Templates]
|
||||
|
||||
This macro must be prefixed by `typename` when used within templates.
|
||||
For example, let's program a macro that declares a function parameter named `arg`[^['n]] with the specified [^['type]] (see also [@../../test/template.cpp =template.cpp=]):
|
||||
|
||||
[template_f_decl]
|
||||
[template_f_call]
|
||||
|
||||
However, note that the template parameter `char` must be manually specified when invoking the function as in `f<char>(a)`.
|
||||
In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as `f(a)` would have done.
|
||||
[footnote
|
||||
This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function.
|
||||
]
|
||||
(This limitation does not apply to class templates because class template parameters must always be explicitly specified.)
|
||||
In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to automatically deduce the function template parameter as shown below:
|
||||
|
||||
[template_g_decl]
|
||||
[template_g_call]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Abstract Types]
|
||||
|
||||
On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error.
|
||||
This can be avoided by manipulating the type adding and removing a reference to it.
|
||||
|
||||
Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]).
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters).
|
||||
In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/abstract.cpp =abstract.cpp=]):
|
||||
|
||||
[abstract]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Annex: Usage]
|
||||
|
||||
The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally when implementing a user-defined macro (as shown below).
|
||||
When [macroref BOOST_IDENTITY_TYPE] is used in the implementation of the user-defined macro, the caller of the user macro will have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]):
|
||||
|
||||
[paren]
|
||||
|
||||
However, note that the caller will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma:
|
||||
|
||||
[paren_always]
|
||||
|
||||
In some cases, using [macroref BOOST_IDENTITY_TYPE] in the implementation of the user-defined macro might provide the best syntax for the caller.
|
||||
For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]:
|
||||
|
||||
BOOST_MPL_ASSERT(( // Natural syntax.
|
||||
boost::mpl::and_<
|
||||
boost::is_const<T>
|
||||
, boost::is_reference<T>
|
||||
>
|
||||
));
|
||||
|
||||
However, in other situations it might be preferable to not require the extra parenthesis in the common cases and handle commas as special cases using [macroref BOOST_IDENTITY_TYPE].
|
||||
For example, this is the case for [@http://www.boost.org/libs/local_function `BOOST_LOCAL_FUNCTION`] for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function signature:
|
||||
|
||||
int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
|
||||
return x + y;
|
||||
} BOOST_LOCAL_FUNCTION_NAME(add)
|
||||
|
||||
Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma (while still allowing to specify parameter types with commas as special cases using `BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map<int, char>))& x, int& y)`).
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Annex: Implementation]
|
||||
|
||||
The implementation of this library macro is equivalent to the following:
|
||||
[footnote
|
||||
There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation.
|
||||
The listed code is for explanatory purposes only.
|
||||
]
|
||||
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
|
||||
boost::function_traits<void parenthesized_type>::arg1_type
|
||||
|
||||
Essentially, the type is wrapped between round parenthesis `(std::map<int, char>)` so it can be passed as a single macro parameter even if it contains commas.
|
||||
Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map<int, char>)`.
|
||||
Finally, the type of the first argument `arg1_type` is extracted at compile-time using the `function_traits` meta-function therefore obtaining the original type from the parenthesized type (effectively stripping the extra parenthesis from around the specified type).
|
||||
|
||||
[endsect]
|
||||
|
||||
[xinclude reference.xml]
|
||||
|
15
identity_type/index.html
Normal file
15
identity_type/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, click this
|
||||
<a href="doc/html/index.html">link</a> <hr>
|
||||
<p><EFBFBD> Copyright Lorenzo Caminiti, 2009-2012</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0 (see
|
||||
accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or a copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
16
identity_type/test/Jamfile.v2
Normal file
16
identity_type/test/Jamfile.v2
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
# Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
# Distributed under the Boost Software License, Version 1.0
|
||||
# (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
import testing ;
|
||||
|
||||
compile-fail var_error.cpp ;
|
||||
run var.cpp ;
|
||||
run template.cpp ;
|
||||
run abstract.cpp ;
|
||||
run noncopyable.cpp ;
|
||||
run paren.cpp ;
|
||||
|
35
identity_type/test/abstract.cpp
Normal file
35
identity_type/test/abstract.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
//[abstract
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
template<typename T, bool b>
|
||||
struct abstract {
|
||||
static const bool value = b;
|
||||
virtual void f(T const& x) = 0; // Pure virtual function.
|
||||
};
|
||||
|
||||
TMP_ASSERT(
|
||||
boost::remove_reference< // Add and remove
|
||||
BOOST_IDENTITY_TYPE(( // reference for
|
||||
boost::add_reference< // abstract type.
|
||||
abstract<int, true>
|
||||
>::type
|
||||
))
|
||||
>::type
|
||||
);
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
25
identity_type/test/noncopyable.cpp
Normal file
25
identity_type/test/noncopyable.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
//[noncopyable
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
template<typename T, T init>
|
||||
struct noncopyable : boost::noncopyable {
|
||||
static const T value = init;
|
||||
};
|
||||
|
||||
TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable<bool, true>)));
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
35
identity_type/test/paren.cpp
Normal file
35
identity_type/test/paren.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <map>
|
||||
|
||||
//[paren
|
||||
#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
|
||||
/* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
|
||||
BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
|
||||
|
||||
#define TMP_ASSERT(metafunction) \
|
||||
BOOST_STATIC_ASSERT(metafunction::value)
|
||||
|
||||
// Specify only extra parenthesis `((...))`.
|
||||
TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
|
||||
|
||||
// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
|
||||
TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
|
||||
//]
|
||||
|
||||
//[paren_always
|
||||
TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
|
||||
|
||||
TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
48
identity_type/test/template.cpp
Normal file
48
identity_type/test/template.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
//[template_f_decl
|
||||
#define ARG(type, n) type arg ## n
|
||||
|
||||
template<typename T>
|
||||
void f( // Prefix macro with `typename` in templates.
|
||||
ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1)
|
||||
) {
|
||||
std::cout << arg1[0] << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
//[template_g_decl
|
||||
template<typename T>
|
||||
void g(
|
||||
std::map<int, T> arg1
|
||||
) {
|
||||
std::cout << arg1[0] << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
int main() {
|
||||
//[template_f_call
|
||||
std::map<int, char> a;
|
||||
a[0] = 'a';
|
||||
|
||||
f<char>(a); // OK...
|
||||
// f(a); // ... but error.
|
||||
//]
|
||||
|
||||
//[template_g_call
|
||||
g<char>(a); // OK...
|
||||
g(a); // ... and also OK.
|
||||
//]
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
26
identity_type/test/var.cpp
Normal file
26
identity_type/test/var.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <map>
|
||||
|
||||
#define VAR(type, n) type var ## n
|
||||
|
||||
VAR(int, 1); // OK.
|
||||
|
||||
//[var_typedef
|
||||
typedef std::map<int, char> map_type;
|
||||
VAR(map_type, 3); // OK.
|
||||
//]
|
||||
|
||||
//[var_ok
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
|
||||
VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
18
identity_type/test/var_error.cpp
Normal file
18
identity_type/test/var_error.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
#include <map>
|
||||
|
||||
//[var_error
|
||||
#define VAR(type, n) type var ## n
|
||||
|
||||
VAR(int, 1); // OK.
|
||||
VAR(std::map<int, char>, 2); // Error.
|
||||
//]
|
||||
|
||||
int main() { return 0; }
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_enum.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
@ -43,20 +44,26 @@ struct ct_imp2<T, true>
|
||||
typedef const T param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp, bool b1>
|
||||
template <typename T, bool isp, bool b1, bool b2>
|
||||
struct ct_imp
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp>
|
||||
struct ct_imp<T, isp, true>
|
||||
template <typename T, bool isp, bool b2>
|
||||
struct ct_imp<T, isp, true, b2>
|
||||
{
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool b1>
|
||||
struct ct_imp<T, true, b1>
|
||||
template <typename T, bool isp, bool b1>
|
||||
struct ct_imp<T, isp, b1, true>
|
||||
{
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool b1, bool b2>
|
||||
struct ct_imp<T, true, b1, b2>
|
||||
{
|
||||
typedef const T param_type;
|
||||
};
|
||||
@ -79,7 +86,8 @@ public:
|
||||
typedef typename boost::detail::ct_imp<
|
||||
T,
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value
|
||||
::boost::is_arithmetic<T>::value,
|
||||
::boost::is_enum<T>::value
|
||||
>::param_type param_type;
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <boost/utility/binary.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility/identity_type.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
@ -13,6 +13,7 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#include <boost/type_traits/add_rvalue_reference.hpp>
|
||||
//#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
@ -36,9 +37,13 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
//#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
template <typename T>
|
||||
typename add_rvalue_reference<T>::type declval(); //noexcept; // as unevaluated operand
|
||||
|
||||
typename add_rvalue_reference<T>::type declval() BOOST_NOEXCEPT; // as unevaluated operand
|
||||
//#else
|
||||
// template <typename T>
|
||||
// typename add_lvalue_reference<T>::type declval() BOOST_NOEXCEPT; // as unevaluated operand
|
||||
//#endif
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_TYPE_TRAITS_EXT_DECLVAL__HPP
|
||||
|
@ -5,6 +5,11 @@
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or
|
||||
// copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
# error Boost result_of - do not include this file!
|
||||
@ -18,34 +23,29 @@
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: mpl::if_<
|
||||
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::has_result_type<F>::value)>
|
||||
, boost::detail::tr1_result_of_impl<
|
||||
F,
|
||||
F(BOOST_RESULT_OF_ARGS),
|
||||
F(BOOST_RESULT_OF_ARGS),
|
||||
(boost::detail::has_result_type<F>::value)> >::type { };
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
// As of N2588, C++0x result_of only supports function call
|
||||
// expressions of the form f(x). This precludes support for member
|
||||
// function pointers, which are invoked with expressions of the form
|
||||
// o->*f(x). This implementation supports both.
|
||||
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
// Uses declval following N3225 20.7.7.6 when F is not a pointer.
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||
: mpl::if_<
|
||||
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
|
||||
is_member_function_pointer<F>
|
||||
, detail::tr1_result_of_impl<
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type,
|
||||
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
|
||||
>
|
||||
, detail::cpp0x_result_of_impl<
|
||||
@ -56,56 +56,119 @@ struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||
|
||||
namespace detail {
|
||||
|
||||
# define BOOST_RESULT_OF_STATIC_MEMBERS(z, n, _) \
|
||||
static T ## n t ## n; \
|
||||
/**/
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
class cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||
{
|
||||
static F f;
|
||||
BOOST_PP_REPEAT(BOOST_PP_ITERATION(), BOOST_RESULT_OF_STATIC_MEMBERS, _)
|
||||
public:
|
||||
typedef decltype(f(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),t))) type;
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION());
|
||||
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
|
||||
R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION());
|
||||
|
||||
#else // defined(BOOST_NO_DECLTYPE)
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F *>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F &>
|
||||
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
|
||||
{};
|
||||
|
||||
template<typename F>
|
||||
struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
|
||||
: mpl::eval_if<
|
||||
is_class<typename remove_reference<F>::type>,
|
||||
result_of_wrap_callable_class<F>,
|
||||
mpl::identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
|
||||
struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
|
||||
typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
|
||||
static const bool value = (
|
||||
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
|
||||
(boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), result_of_weird_type())
|
||||
))
|
||||
);
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
|
||||
: lazy_enable_if<
|
||||
BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
|
||||
, cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||
{
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
typename result_of_always_void<decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
)>::type> {
|
||||
typedef decltype(
|
||||
boost::declval<F>()(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
|
||||
)
|
||||
) type;
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct result_of<F(BOOST_RESULT_OF_ARGS)>
|
||||
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
|
||||
#endif
|
||||
|
||||
#endif // defined(BOOST_NO_DECLTYPE)
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
#undef BOOST_RESULT_OF_ARGS
|
||||
|
||||
#if BOOST_PP_ITERATION() >= 1
|
||||
#if BOOST_PP_ITERATION() >= 1
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
|
||||
FArgs, false>
|
||||
@ -113,8 +176,7 @@ struct tr1_result_of_impl<R (T0::*)
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
const,
|
||||
@ -123,8 +185,7 @@ struct tr1_result_of_impl<R (T0::*)
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
volatile,
|
||||
@ -133,8 +194,7 @@ struct tr1_result_of_impl<R (T0::*)
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||
struct tr1_result_of_impl<R (T0::*)
|
||||
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
|
||||
const volatile,
|
||||
|
46
include/boost/utility/identity_type.hpp
Normal file
46
include/boost/utility/identity_type.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
// Copyright (C) 2009-2012 Lorenzo Caminiti
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (see accompanying file LICENSE_1_0.txt or a copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Home at http://www.boost.org/libs/utility/identity_type
|
||||
|
||||
/** @file
|
||||
Wrap type expressions with round parenthesis so they can be passed to macros
|
||||
even if they contain commas.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_IDENTITY_TYPE_HPP_
|
||||
#define BOOST_IDENTITY_TYPE_HPP_
|
||||
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
/**
|
||||
@brief This macro allows to wrap the specified type expression within extra
|
||||
round parenthesis so the type can be passed as a single macro parameter even if
|
||||
it contains commas (not already wrapped within round parenthesis).
|
||||
|
||||
@Params
|
||||
@Param{parenthesized_type,
|
||||
The type expression to be passed as macro parameter wrapped by a single set
|
||||
of round parenthesis <c>(...)</c>.
|
||||
This type expression can contain an arbitrary number of commas.
|
||||
}
|
||||
@EndParams
|
||||
|
||||
This macro works on any C++03 compiler (it does not use variadic macros).
|
||||
|
||||
This macro must be prefixed by <c>typename</c> when used within templates.
|
||||
Note that the compiler will not be able to automatically determine function
|
||||
template parameters when they are wrapped with this macro (these parameters
|
||||
need to be explicitly specified when calling the function template).
|
||||
|
||||
On some compilers (like GCC), using this macro on abstract types requires to
|
||||
add and remove a reference to the specified type.
|
||||
*/
|
||||
#define BOOST_IDENTITY_TYPE(parenthesized_type) \
|
||||
/* must NOT prefix this with `::` to work with parenthesized syntax */ \
|
||||
boost::function_traits< void parenthesized_type >::arg1_type
|
||||
|
||||
#endif // #include guard
|
||||
|
@ -10,21 +10,48 @@
|
||||
#define BOOST_RESULT_OF_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
|
||||
#include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/declval.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#ifndef BOOST_RESULT_OF_NUM_ARGS
|
||||
# define BOOST_RESULT_OF_NUM_ARGS 10
|
||||
# define BOOST_RESULT_OF_NUM_ARGS 16
|
||||
#endif
|
||||
|
||||
// Use the decltype-based version of result_of by default if the compiler
|
||||
// supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
|
||||
// The user can force the choice by defining either BOOST_RESULT_OF_USE_DECLTYPE or
|
||||
// BOOST_RESULT_OF_USE_TR1, but not both!
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)
|
||||
# error Both BOOST_RESULT_OF_USE_DECLTYPE and BOOST_RESULT_OF_USE_TR1 cannot be defined at the same time.
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_RESULT_OF_USE_TR1
|
||||
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_DECLTYPE)
|
||||
# define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
# else
|
||||
# define BOOST_RESULT_OF_USE_TR1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
@ -38,7 +65,67 @@ namespace detail {
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
||||
|
||||
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
|
||||
template<typename F> struct cpp0x_result_of_impl;
|
||||
|
||||
#ifdef BOOST_NO_SFINAE_EXPR
|
||||
|
||||
struct result_of_private_type {};
|
||||
|
||||
struct result_of_weird_type {
|
||||
friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
|
||||
};
|
||||
|
||||
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
|
||||
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
|
||||
|
||||
template<typename T>
|
||||
result_of_no_type result_of_is_private_type(T const &);
|
||||
result_of_yes_type result_of_is_private_type(result_of_private_type);
|
||||
|
||||
template<typename C>
|
||||
struct result_of_callable_class : C {
|
||||
result_of_callable_class();
|
||||
typedef result_of_private_type const &(*pfn_t)(...);
|
||||
operator pfn_t() const volatile;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class {
|
||||
typedef result_of_callable_class<C> type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C const> {
|
||||
typedef result_of_callable_class<C> const type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C volatile> {
|
||||
typedef result_of_callable_class<C> volatile type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C const volatile> {
|
||||
typedef result_of_callable_class<C> const volatile type;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct result_of_wrap_callable_class<C &> {
|
||||
typedef typename result_of_wrap_callable_class<C>::type &type;
|
||||
};
|
||||
|
||||
template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
|
||||
|
||||
#else // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename T>
|
||||
struct result_of_always_void
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
|
||||
|
||||
#endif // BOOST_NO_SFINAE_EXPR
|
||||
|
||||
template<typename F>
|
||||
struct result_of_void_impl
|
||||
|
0
test/next_prior_test.cpp
Executable file → Normal file
0
test/next_prior_test.cpp
Executable file → Normal file
@ -5,7 +5,7 @@
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// For more information, see http://www.boost.org/libs/utility
|
||||
#include <boost/utility/result_of.hpp>
|
||||
@ -62,6 +62,9 @@ struct int_result_type_and_float_result_of_and_char_return_template
|
||||
char operator()(char);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct cv_overload_check {};
|
||||
|
||||
struct result_of_member_function_template
|
||||
{
|
||||
template<typename F> struct result;
|
||||
@ -69,13 +72,13 @@ struct result_of_member_function_template
|
||||
template<typename This, typename That> struct result<This(That)> { typedef That type; };
|
||||
template<class T> typename result<result_of_member_function_template(T)>::type operator()(T);
|
||||
|
||||
template<typename This, typename That> struct result<const This(That)> { typedef const That type; };
|
||||
template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; };
|
||||
template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const;
|
||||
|
||||
template<typename This, typename That> struct result<volatile This(That)> { typedef volatile That type; };
|
||||
template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; };
|
||||
template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile;
|
||||
|
||||
template<typename This, typename That> struct result<const volatile This(That)> { typedef const volatile That type; };
|
||||
template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; };
|
||||
template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile;
|
||||
|
||||
template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; };
|
||||
@ -91,25 +94,62 @@ struct result_of_member_function_template
|
||||
template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T);
|
||||
};
|
||||
|
||||
struct no_result_type_or_result_of
|
||||
struct no_result_type_or_result
|
||||
{
|
||||
int operator()(double);
|
||||
short operator()(double) const;
|
||||
unsigned int operator()();
|
||||
unsigned short operator()() volatile;
|
||||
const unsigned short operator()() const volatile;
|
||||
short operator()(double);
|
||||
cv_overload_check<const short> operator()(double) const;
|
||||
cv_overload_check<volatile short> operator()(double) volatile;
|
||||
cv_overload_check<const volatile short> operator()(double) const volatile;
|
||||
int operator()();
|
||||
cv_overload_check<const int> operator()() const;
|
||||
cv_overload_check<volatile int> operator()() volatile;
|
||||
cv_overload_check<const volatile int> operator()() const volatile;
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
short operator()(int&&);
|
||||
int operator()(int&);
|
||||
long operator()(int const&);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct no_result_type_or_result_of_template
|
||||
struct no_result_type_or_result_template
|
||||
{
|
||||
int operator()(double);
|
||||
short operator()(double) const;
|
||||
unsigned int operator()();
|
||||
unsigned short operator()() volatile;
|
||||
const unsigned short operator()() const volatile;
|
||||
short operator()(double);
|
||||
cv_overload_check<const short> operator()(double) const;
|
||||
cv_overload_check<volatile short> operator()(double) volatile;
|
||||
cv_overload_check<const volatile short> operator()(double) const volatile;
|
||||
int operator()();
|
||||
cv_overload_check<const int> operator()() const;
|
||||
cv_overload_check<volatile int> operator()() volatile;
|
||||
cv_overload_check<const volatile int> operator()() const volatile;
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
short operator()(int&&);
|
||||
int operator()(int&);
|
||||
long operator()(int const&);
|
||||
#endif
|
||||
};
|
||||
|
||||
// sfinae_tests are derived from example code from Joel de Guzman,
|
||||
// which demonstrated the interaction between result_of and SFINAE.
|
||||
template <typename F, typename Arg>
|
||||
typename boost::result_of<F(Arg const&)>::type
|
||||
sfinae_test(F f, Arg const& arg)
|
||||
{
|
||||
return f(arg);
|
||||
}
|
||||
|
||||
template <typename F, typename Arg>
|
||||
typename boost::result_of<F(Arg&)>::type
|
||||
sfinae_test(F f, Arg& arg)
|
||||
{
|
||||
return f(arg);
|
||||
}
|
||||
|
||||
int sfinae_test_f(int& i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
struct X {};
|
||||
|
||||
int main()
|
||||
@ -120,6 +160,10 @@ int main()
|
||||
typedef int (&func_ref)(float, double);
|
||||
typedef int (*func_ptr_0)();
|
||||
typedef int (&func_ref_0)();
|
||||
typedef void (*func_ptr_void)(float, double);
|
||||
typedef void (&func_ref_void)(float, double);
|
||||
typedef void (*func_ptr_void_0)();
|
||||
typedef void (&func_ref_void_0)();
|
||||
typedef int (X::*mem_func_ptr)(float);
|
||||
typedef int (X::*mem_func_ptr_c)(float) const;
|
||||
typedef int (X::*mem_func_ptr_v)(float) volatile;
|
||||
@ -147,7 +191,7 @@ int main()
|
||||
|
||||
// Prior to decltype, result_of could not deduce the return type
|
||||
// nullary function objects unless they exposed a result_type.
|
||||
#if !defined(BOOST_NO_DECLTYPE)
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value));
|
||||
@ -159,14 +203,11 @@ int main()
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
|
||||
#endif
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
|
||||
|
||||
// Prior to decltype, result_of ignored a nested result<> if
|
||||
// result_type was defined. After decltype, result_of deduces the
|
||||
// actual return type of the function object, ignoring both
|
||||
// result<> and result_type.
|
||||
#if !defined(BOOST_NO_DECLTYPE)
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value));
|
||||
#else
|
||||
@ -174,41 +215,52 @@ int main()
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
|
||||
#endif
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(void)>::type, int>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(void)>::type, int>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, const double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, const double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
|
||||
@ -221,18 +273,38 @@ int main()
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t(int)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t const(int)>::type,int>::value));
|
||||
|
||||
#if !defined(BOOST_NO_DECLTYPE)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(double)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(void)>::type, unsigned int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of(void)>::type, unsigned short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of(void)>::type, const unsigned short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(double)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(void)>::type, unsigned int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of_template<void>(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of_template<void>(void)>::type, unsigned short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of_template<void>(void)>::type, const unsigned short>::value));
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const volatile short> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value));
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value));
|
||||
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
int i = 123;
|
||||
sfinae_test(sfinae_test_f, i);
|
||||
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
378
utility.htm
378
utility.htm
@ -143,7 +143,7 @@ void f() {
|
||||
<h2><a name="result_of">Class template
|
||||
result_of</a></h2> <p>The class template
|
||||
<code>result_of</code> helps determine the type of a
|
||||
call expression. Given an lvalue <code>f</code> of
|
||||
call expression. For example, given an lvalue <code>f</code> of
|
||||
type <code>F</code> and lvalues <code>t1</code>,
|
||||
<code>t2</code>, ..., <code>t<em>N</em></code> of
|
||||
types <code>T1</code>, <code>T2</code>, ...,
|
||||
@ -155,22 +155,24 @@ void f() {
|
||||
the type <code>F</code> to be a function pointer,
|
||||
function reference, member function pointer, or class
|
||||
type. By default, <em>N</em> may be any value between 0 and
|
||||
10. To change the upper limit, define the macro
|
||||
16. To change the upper limit, define the macro
|
||||
<code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum
|
||||
value for <em>N</em>. Class template <code>result_of</code>
|
||||
resides in the header <code><<a
|
||||
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.</p>
|
||||
|
||||
<p>If your compiler supports <code>decltype</code>,
|
||||
then you can enable automatic result type deduction by
|
||||
defining the macro <code>BOOST_RESULT_OF_USE_DECLTYPE</code>,
|
||||
as in the following example.</p>
|
||||
<p>If your compiler's support for <code>decltype</code> is
|
||||
adequate, <code>result_of</code> automatically uses it to
|
||||
deduce the type of the call expression, in which case
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)>::type</code> names the type
|
||||
<code>decltype(boost::declval<F>()(boost::declval<T1>(),
|
||||
boost::declval<T2>(), ...,
|
||||
boost::declval<T<em>N</em>>()))</code>, as in the
|
||||
following example.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#include <boost/utility/result_of.hpp>
|
||||
|
||||
struct functor {
|
||||
<pre>struct functor {
|
||||
template<class T>
|
||||
T operator()(T x)
|
||||
{
|
||||
@ -180,21 +182,29 @@ struct functor {
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(int)
|
||||
>::type type;</pre>
|
||||
>::type type; // type is int</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>If <code>decltype</code> is not enabled,
|
||||
<p>You can test whether <code>result_of</code> is using
|
||||
<code>decltype</code> by checking if the macro
|
||||
<code>BOOST_RESULT_OF_USE_DECLTYPE</code> is defined after
|
||||
including <code>result_of.hpp</code>. You can also force
|
||||
<code>result_of</code> to use <code>decltype</code> by
|
||||
defining <code>BOOST_RESULT_OF_USE_DECLTYPE</code> prior
|
||||
to including <code>result_of.hpp</code>.</p>
|
||||
|
||||
<p>If <code>decltype</code> is not used,
|
||||
then automatic result type deduction of function
|
||||
objects is not possible. Instead, <code>result_of</code>
|
||||
uses the following protocol to allow the programmer to
|
||||
specify a type. When <code>F</code> is a class type with a
|
||||
member type <code>result_type</code>,
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)></code> is
|
||||
T<em>N</em>)>::type</code> is
|
||||
<code>F::result_type</code>. When <code>F</code> does
|
||||
not contain <code>result_type</code>,
|
||||
<code>result_of<F(T1, T2, ...,
|
||||
T<em>N</em>)></code> is <code>F::result<F(T1,
|
||||
T<em>N</em>)>::type</code> is <code>F::result<F(T1,
|
||||
T2, ..., T<em>N</em>)>::type</code> when
|
||||
<code><em>N</em> > 0</code> or <code>void</code>
|
||||
when <code><em>N</em> = 0</code>. Note that it is the
|
||||
@ -221,9 +231,30 @@ typedef boost::result_of<
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(int)
|
||||
>::type type;</pre>
|
||||
>::type type; // type is int</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Since <code>decltype</code> is a new language
|
||||
feature recently standardized in C++11,
|
||||
if you are writing a function object
|
||||
to be used with <code>result_of</code>, for
|
||||
maximum portability, you might consider following
|
||||
the above protocol even if your compiler has
|
||||
proper <code>decltype</code> support. If you wish to continue to
|
||||
use the protocol on compilers that
|
||||
support <code>decltype</code>, there are two options:
|
||||
You can use <code>boost::tr1_result_of</code>, which is also
|
||||
defined in <code><<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.
|
||||
Alternatively, you can define the macro
|
||||
<code>BOOST_RESULT_OF_USE_TR1</code>, which causes
|
||||
<code>result_of</code> to use the protocol described
|
||||
above instead of <code>decltype</code>. If you choose to
|
||||
follow the protocol, take care to ensure that the
|
||||
<code>result_type</code> and
|
||||
<code>result<></code> members accurately
|
||||
represent the return type of
|
||||
<code>operator()</code> given a call expression.</p>
|
||||
|
||||
<a name="BOOST_NO_RESULT_OF"></a>
|
||||
<p>This implementation of <code>result_of</code>
|
||||
requires class template partial specialization, the
|
||||
@ -239,7 +270,322 @@ typedef boost::result_of<
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
|
||||
or, for motivation and design rationale,
|
||||
the <code>result_of</code> <a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p>
|
||||
Contributed by Doug Gregor.</p>
|
||||
|
||||
<a name="result_of_guidelines">
|
||||
<h3>Usage guidelines for boost::result_of</h3>
|
||||
</a>
|
||||
|
||||
<p>The following are general suggestions about when
|
||||
and how to use <code>boost::result_of</code>.</p>
|
||||
|
||||
<ol>
|
||||
<li> If you are targeting C++11 and are not concerned
|
||||
about portability to non-compliant compilers or
|
||||
previous versions of the standard, then use
|
||||
<code>std::result_of</code>. If <code>std::result_of</code>
|
||||
meets your needs, then there's no reason to stop using
|
||||
it.</li>
|
||||
|
||||
<li> If you are targeting C++11 but may port your code
|
||||
to legacy compilers at some time in the future, then
|
||||
use <code>boost::result_of</code> with
|
||||
<code>decltype</code>. When <code>decltype</code> is
|
||||
used <code>boost::result_of</code>
|
||||
and <code>std::result_of</code> are usually
|
||||
interchangeable. See the documentation on
|
||||
known <a href="#result_of_cxx11_diff">differences</a>
|
||||
between boost::result_of and C++11 result_of.</li>
|
||||
|
||||
<li> If compiler portability is required,
|
||||
use <code>boost::result_of</code> with the TR1 protocol.</li>
|
||||
</ol>
|
||||
|
||||
<p>Regardless of how you
|
||||
configure <code>boost::result_of</code>, it is
|
||||
important to bear in mind that the return type of a
|
||||
function may change depending on its arguments, and
|
||||
additionally, the return type of a member function may
|
||||
change depending on the cv-qualification of the
|
||||
object. <code>boost::result_of</code> must be passed
|
||||
the appropriately cv-qualified types in order to
|
||||
deduce the corresponding return type. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
int& operator()(int);
|
||||
int const& operator()(int) const;
|
||||
|
||||
float& operator()(float&);
|
||||
float const& operator()(float const&);
|
||||
};
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(int)
|
||||
>::type type1; // type1 is int &
|
||||
|
||||
typedef boost::result_of<
|
||||
const functor(int)
|
||||
>::type type2; // type2 is int const &
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(float&)
|
||||
>::type type3; // type3 is float &
|
||||
|
||||
typedef boost::result_of<
|
||||
functor(float const&)
|
||||
>::type type4; // type4 is float const &</pre>
|
||||
</blockquote>
|
||||
|
||||
<a name="result_of_tr1_protocol_guidelines">
|
||||
<h3>Usage guidelines for the TR1 result_of protocol</h3>
|
||||
</a>
|
||||
|
||||
<p>On compliant C++11
|
||||
compilers, <code>boost::result_of</code> can
|
||||
use <code>decltype</code> to deduce the type of any
|
||||
call expression, including calls to function
|
||||
objects. However, on pre-C++11 compilers or on
|
||||
compilers without adequate decltype support,
|
||||
additional scaffolding is needed from function
|
||||
objects as described above. The following are
|
||||
suggestions about how to use the TR1 protocol.</p>
|
||||
|
||||
<ul>
|
||||
<li>When the return type does not depend on the
|
||||
argument types or the cv-qualification of the
|
||||
function object, simply
|
||||
define <code>result_type</code>. There is no need
|
||||
to use the <code>result</code> template unless the
|
||||
return type varies.</li>
|
||||
|
||||
<li>Use the protocol specified type when defining
|
||||
function prototypes. This can help ensure the
|
||||
actual return type does not get out of sync with
|
||||
the protocol specification. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
typedef int result_type;
|
||||
result_type operator()(int);
|
||||
};</pre>
|
||||
</blockquote> </li>
|
||||
|
||||
<li>Always specify the <code>result</code>
|
||||
specialization near the corresponding
|
||||
<code>operator()</code> overload. This can make it
|
||||
easier to keep the specializations in sync with the
|
||||
overloads. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F>
|
||||
struct result<F(int)> {
|
||||
typedef int& type;
|
||||
};
|
||||
result<functor(int)>::type operator()(int);
|
||||
|
||||
template<class F>
|
||||
struct result<const F(int)> {
|
||||
typedef int const& type;
|
||||
};
|
||||
result<const functor(int)>::type operator()(int) const;
|
||||
};</pre>
|
||||
</blockquote> </li>
|
||||
|
||||
<li>Use type transformations to simplify
|
||||
the <code>result</code> template specialization. For
|
||||
example, the following uses
|
||||
<a href="../type_traits/doc/html/index.html">Boost.TypeTraits</a>
|
||||
to specialize the <code>result</code> template for
|
||||
a single <code>operator()</code> that can be called on
|
||||
both a const and non-const function object with
|
||||
either an lvalue or rvalue argument.
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result;
|
||||
|
||||
template<class F, class T>
|
||||
struct result<F(T)>
|
||||
: boost::remove_cv<
|
||||
typename boost::remove_reference<T>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
T operator()(T const& x) const;
|
||||
};</pre>
|
||||
</blockquote></li>
|
||||
</ul>
|
||||
|
||||
<a name="result_of_tr1_diff">
|
||||
<h3>Known differences between boost::result_of and TR1 result_of</h3>
|
||||
</a>
|
||||
|
||||
When using <code>decltype</code>, <code>boost::result_of</code>
|
||||
ignores the TR1 protocol and instead deduces the
|
||||
return type of function objects directly
|
||||
via <code>decltype</code>. In most situations, users
|
||||
will not notice a difference, so long as they use the
|
||||
protocol correctly. The following are situations in
|
||||
which the type deduced
|
||||
by <code>boost::result_of</code> is known to differ depending on
|
||||
whether <code>decltype</code> or the TR1 protocol is
|
||||
used.
|
||||
|
||||
<ul>
|
||||
<li> TR1 protocol misusage
|
||||
|
||||
<p>When using the TR1
|
||||
protocol, <code>boost::result_of</code> cannot
|
||||
detect whether the actual type of a call to a
|
||||
function object is the same as the type specified
|
||||
by the protocol, which allows for the possibility
|
||||
of inadvertent mismatches between the specified
|
||||
type and the actual type. When
|
||||
using <code>decltype</code>, these subtle bugs
|
||||
may result in compilation errors. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
typedef short result_type;
|
||||
int operator()(short);
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor(short)>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor(short)>::type, short>::value
|
||||
));
|
||||
|
||||
#endif</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Note that the user can
|
||||
force <code>boost::result_of</code> to use the TR1
|
||||
protocol even on platforms that
|
||||
support <code>decltype</code> by
|
||||
defining <code>BOOST_RESULT_OF_USE_TR1</code>.</p></li>
|
||||
|
||||
<li> Nullary function objects
|
||||
|
||||
<p>When using the TR1 protocol, <code>boost::result_of</code>
|
||||
cannot always deduce the type of calls to
|
||||
nullary function objects, in which case the
|
||||
type defaults to void. When using <code>decltype</code>,
|
||||
<code>boost::result_of</code> always gives the actual type of the
|
||||
call expression. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result {
|
||||
typedef int type;
|
||||
};
|
||||
int operator()();
|
||||
};
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor()>::type, int>::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<boost::result_of<functor()>::type, void>::value
|
||||
));
|
||||
|
||||
#endif</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Note that there are some workarounds for the
|
||||
nullary function problem. So long as the return
|
||||
type does not vary,
|
||||
<code>result_type</code> can always be used to
|
||||
specify the return type regardless of arity. If the
|
||||
return type does vary, then the user can
|
||||
specialize <code>boost::result_of</code> itself for
|
||||
nullary calls.</p></li>
|
||||
|
||||
<li> Non-class prvalues and cv-qualification
|
||||
|
||||
<p>When using the TR1
|
||||
protocol, <code>boost::result_of</code> will
|
||||
report the cv-qualified type specified
|
||||
by <code>result_type</code> or
|
||||
the <code>result</code> template regardless of
|
||||
the actual cv-qualification of the call
|
||||
expression. When using
|
||||
<code>decltype</code>, <code>boost::result_of</code>
|
||||
will report the actual type of the call expression,
|
||||
which is not cv-qualified when the expression is a
|
||||
non-class prvalue. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>struct functor {
|
||||
template<class> struct result;
|
||||
template<class F, class T> struct result<F(const T)> {
|
||||
typedef const T type;
|
||||
};
|
||||
|
||||
const short operator()(const short);
|
||||
int const & operator()(int const &);
|
||||
};
|
||||
|
||||
// Non-prvalue call expressions work the same with or without decltype.
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
boost::result_of<functor(int const &)>::type,
|
||||
int const &
|
||||
::value
|
||||
));
|
||||
|
||||
// Non-class prvalue call expressions are not actually cv-qualified,
|
||||
// but only the decltype-based result_of reports this accurately.
|
||||
|
||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
boost::result_of<functor(const short)>::type,
|
||||
short
|
||||
::value
|
||||
));
|
||||
|
||||
#else
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
boost::result_of<functor(const short)>::type,
|
||||
const short
|
||||
::value
|
||||
));
|
||||
|
||||
#endif</pre>
|
||||
</blockquote></li>
|
||||
</ul>
|
||||
|
||||
<a name="result_of_cxx11_diff">
|
||||
<h3>Known differences between boost::result_of and C++11 result_of</h3>
|
||||
</a>
|
||||
|
||||
<p>When using <code>decltype</code>, <code>boost::result_of</code>
|
||||
implements most of the C++11 result_of
|
||||
specification. One known exception is that
|
||||
<code>boost::result_of</code> does not implement the
|
||||
requirements regarding pointers to member data.</p>
|
||||
|
||||
<p>Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others</p>
|
||||
|
||||
<h2>Class templates for the Base-from-Member Idiom</h2>
|
||||
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
|
||||
|
Reference in New Issue
Block a user