Compare commits

...

21 Commits

Author SHA1 Message Date
Douglas Gregor
6d50998347 Fix eol-style and mime-types
[SVN r7564]
2007-07-27 00:28:00 +00:00
Douglas Gregor
2bc5f0cb06 Remove the broken reference_wrapper
[SVN r2754]
2005-11-20 18:07:53 +00:00
Douglas Gregor
0e3d2ccb2c tribool has been in Boost proper for ages
[SVN r2753]
2005-11-20 14:37:12 +00:00
Larry Joe Evans
21bc200ca0 *** empty log message ***
[SVN r2655]
2005-06-27 11:41:45 +00:00
Larry Joe Evans
103b0a719f *** empty log message ***
[SVN r2654]
2005-06-27 11:26:57 +00:00
Larry Joe Evans
85a6825e74 Added file needed by utility/build/Jamfile.v2
[SVN r2631]
2005-06-14 13:41:43 +00:00
Larry Joe Evans
c346d99b84 Adding Jamfile.v2 needed by libs/policy_ptr/test/Jamfile.v2
[SVN r2630]
2005-06-14 13:31:37 +00:00
Larry Joe Evans
72088f2b04 *** empty log message ***
[SVN r2628]
2005-06-13 21:12:57 +00:00
Dave Abrahams
43b68a7b11 Continuesd cleanups and clarification
[SVN r2556]
2005-03-28 04:35:50 +00:00
Dave Abrahams
2c3c79aec5 Cleanups and clarification
[SVN r2555]
2005-03-28 03:11:26 +00:00
Daniel Wallin
c5826cb47b NamedParams renaming
[SVN r2547]
2005-03-26 08:44:37 +00:00
Daniel Wallin
f7631d89a7 reference docs for named_params, incomplete
[SVN r2337]
2004-11-08 13:28:17 +00:00
Douglas Gregor
e595c9b77b Add the include for static asserts
[SVN r2333]
2004-11-05 14:09:28 +00:00
Daniel Wallin
e219b65cf3 *** empty log message ***
[SVN r2312]
2004-09-13 10:21:22 +00:00
Larry Joe Evans
018bb60d47 *** empty log message ***
[SVN r2266]
2004-07-28 03:12:26 +00:00
Douglas Gregor
532c8aa06d boost/result_of.hpp, boost/detail/result_of_iterate.hpp:
- Deal with function references
  - Deal with cv-qualified member pointers

libs/utility/result_of_test.cpp:
  - Test all of those things above


[SVN r2157]
2004-05-02 14:49:44 +00:00
Dave Abrahams
824e94e2f6 Clean up Jamfile; fix for no koenig lookup.
[SVN r2154]
2004-04-20 16:18:49 +00:00
Daniel Wallin
e4b9ac6a30 operator, on named args produce a list automatically
[SVN r2142]
2004-04-17 11:08:24 +00:00
Daniel Wallin
2bc1676024 fixed code example errors in docs
[SVN r2141]
2004-04-17 10:51:12 +00:00
Daniel Wallin
9c3296ef74 *** empty log message ***
[SVN r2140]
2004-04-17 10:46:07 +00:00
Dave Abrahams
4f9b64125a Try latin-1 encoding.
[SVN r2135]
2004-04-14 14:41:29 +00:00
20 changed files with 662 additions and 524 deletions

13
build/Jamfile.v2 Normal file
View File

@@ -0,0 +1,13 @@
project
:
: default-build debug
;
lib debug
: #sources
../src/obj_id.cpp
../src/object_tracked.cpp
../src/trace_scope_stk.cpp
;

View File

@@ -1,6 +0,0 @@
project boost-sandbox/utility/doc ;
import boostbook ;
import doxygen ;
doxygen reference : ../../../boost/tribool.hpp : <prefix>boost ;
boostbook tribool : tribool.boostbook ;

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="Latin-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=Latin-1" />
<meta name="generator" content="Docutils 0.3.1: http://docutils.sourceforge.net/" />
<title>The Boost.NamedParams Library Boost</title>
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
@@ -21,7 +21,7 @@
</tr>
<tr class="field"><th class="field-name">organizations:</th><td class="field-body"><a class="reference" href="http://www.boost-consulting.com">Boost Consulting</a>,</td>
</tr>
<tr class="field"><th class="field-name">date:</th><td class="field-body">$Date$</td>
<tr class="field"><th class="field-name">date:</th><td class="field-body">$Date: 2004-04-17 05:51:12 -0500 (Sat, 17 Apr 2004) $</td>
</tr>
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams, Daniel Wallin 2003.</td>
</tr>
@@ -35,22 +35,22 @@ file LICENSE_1_0.txt or copy at
<div class="contents topic" id="outline">
<p class="topic-title"><a name="outline">Outline</a></p>
<ul class="auto-toc simple">
<li><a class="reference" href="#introduction" id="id7" name="id7">1   Introduction</a></li>
<li><a class="reference" href="#tutorial" id="id8" name="id8">2   Tutorial</a><ul class="auto-toc">
<li><a class="reference" href="#defining-the-keywords" id="id9" name="id9">2.1   Defining the keywords</a></li>
<li><a class="reference" href="#defining-the-forwarding-functions" id="id10" name="id10">2.2   Defining the forwarding functions</a></li>
<li><a class="reference" href="#defining-the-implementation-function" id="id11" name="id11">2.3   Defining the implementation function</a></li>
<li><a class="reference" href="#introduction" id="id7" name="id7">1<EFBFBD><EFBFBD><EFBFBD>Introduction</a></li>
<li><a class="reference" href="#tutorial" id="id8" name="id8">2<EFBFBD><EFBFBD><EFBFBD>Tutorial</a><ul class="auto-toc">
<li><a class="reference" href="#defining-the-keywords" id="id9" name="id9">2.1<EFBFBD><EFBFBD><EFBFBD>Defining the keywords</a></li>
<li><a class="reference" href="#defining-the-forwarding-functions" id="id10" name="id10">2.2<EFBFBD><EFBFBD><EFBFBD>Defining the forwarding functions</a></li>
<li><a class="reference" href="#defining-the-implementation-function" id="id11" name="id11">2.3<EFBFBD><EFBFBD><EFBFBD>Defining the implementation function</a></li>
</ul>
</li>
<li><a class="reference" href="#limitations-of-the-approach" id="id12" name="id12">3   Limitations of the Approach</a></li>
<li><a class="reference" href="#controlling-overload-resolution" id="id13" name="id13">4   Controlling Overload Resolution</a></li>
<li><a class="reference" href="#lazy-evaluation-of-defaults" id="id14" name="id14">5   Lazy Evaluation of Defaults</a></li>
<li><a class="reference" href="#automatic-overload-generation" id="id15" name="id15">6   Automatic Overload Generation</a></li>
<li><a class="reference" href="#portability" id="id16" name="id16">7   Portability</a></li>
<li><a class="reference" href="#limitations-of-the-approach" id="id12" name="id12">3<EFBFBD><EFBFBD><EFBFBD>Limitations of the Approach</a></li>
<li><a class="reference" href="#controlling-overload-resolution" id="id13" name="id13">4<EFBFBD><EFBFBD><EFBFBD>Controlling Overload Resolution</a></li>
<li><a class="reference" href="#lazy-evaluation-of-defaults" id="id14" name="id14">5<EFBFBD><EFBFBD><EFBFBD>Lazy Evaluation of Defaults</a></li>
<li><a class="reference" href="#automatic-overload-generation" id="id15" name="id15">6<EFBFBD><EFBFBD><EFBFBD>Automatic Overload Generation</a></li>
<li><a class="reference" href="#portability" id="id16" name="id16">7<EFBFBD><EFBFBD><EFBFBD>Portability</a></li>
</ul>
</div>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id7" name="introduction">1   Introduction</a></h1>
<h1><a class="toc-backref" href="#id7" name="introduction">1<EFBFBD><EFBFBD><EFBFBD>Introduction</a></h1>
<p>In C++ function arguments are given meaning by their position in
the parameter list. This protocol is fine when there are few
parameters with default values, but as the number of parameters
@@ -114,7 +114,7 @@ The tutorial has to come before all the nasty details below.
I'm going to comment on that and leave the next stuff alone -->
</div>
<div class="section" id="tutorial">
<h1><a class="toc-backref" href="#id8" name="tutorial">2   Tutorial</a></h1>
<h1><a class="toc-backref" href="#id8" name="tutorial">2<EFBFBD><EFBFBD><EFBFBD>Tutorial</a></h1>
<!-- DWA you need some set-up here describing the problem you're
going to solve. -->
<p>This example shows how to wrap a function:</p>
@@ -123,7 +123,7 @@ void foo(char const* name, float value);
</pre>
<p>to give both parameters names and default values.</p>
<div class="section" id="defining-the-keywords">
<h2><a class="toc-backref" href="#id9" name="defining-the-keywords">2.1   Defining the keywords</a></h2>
<h2><a class="toc-backref" href="#id9" name="defining-the-keywords">2.1<EFBFBD><EFBFBD><EFBFBD>Defining the keywords</a></h2>
<p>First we define the named parameter keywords. This is done by creating
&quot;tag&quot; types for each keyword, and declaring <tt class="literal"><span class="pre">keyword&lt;</span></tt><em>tag</em><tt class="literal"><span class="pre">&gt;</span></tt> objects:</p>
<pre class="literal-block">
@@ -154,31 +154,31 @@ struct foo_keywords
</pre>
</div>
<div class="section" id="defining-the-forwarding-functions">
<h2><a class="toc-backref" href="#id10" name="defining-the-forwarding-functions">2.2   Defining the forwarding functions</a></h2>
<h2><a class="toc-backref" href="#id10" name="defining-the-forwarding-functions">2.2<EFBFBD><EFBFBD><EFBFBD>Defining the forwarding functions</a></h2>
<pre class="literal-block">
template&lt;class Params&gt;
void foo_impl(const Params&amp;);
void foo()
{
foo_impl(foo_keywords());
foo_impl(foo_keywords()());
}
template&lt;class A0&gt;
void foo(const A0&amp; a0)
{
foo_impl(foo_keywords(a0));
foo_impl(foo_keywords()(a0));
}
template&lt;class A0, class A1&gt;
void foo(const A0&amp; a0, const A1&amp; a1)
{
foo_impl(foo_keywords(a0, a1));
foo_impl(foo_keywords()(a0, a1));
}
</pre>
</div>
<div class="section" id="defining-the-implementation-function">
<h2><a class="toc-backref" href="#id11" name="defining-the-implementation-function">2.3   Defining the implementation function</a></h2>
<h2><a class="toc-backref" href="#id11" name="defining-the-implementation-function">2.3<EFBFBD><EFBFBD><EFBFBD>Defining the implementation function</a></h2>
<pre class="literal-block">
template&lt;class Params&gt;
void foo_impl(const Params&amp; params)
@@ -232,7 +232,7 @@ unnamed = 3
</div>
</div>
<div class="section" id="limitations-of-the-approach">
<h1><a class="toc-backref" href="#id12" name="limitations-of-the-approach">3   Limitations of the Approach</a></h1>
<h1><a class="toc-backref" href="#id12" name="limitations-of-the-approach">3<EFBFBD><EFBFBD><EFBFBD>Limitations of the Approach</a></h1>
<p>Because the keywords' <tt class="literal"><span class="pre">operator=</span></tt> returns a temporary, and
temporaries cannot be bound to non-<tt class="literal"><span class="pre">const</span></tt> reference parameters,
our forwarding functions need to take their arguments by <tt class="literal"><span class="pre">const</span></tt>
@@ -253,7 +253,7 @@ foo(boost::ref(x)); // held type is float&amp;
<tt class="literal"><span class="pre">boost::ref</span></tt> will be unwrapped automatically by the library.</p>
</div>
<div class="section" id="controlling-overload-resolution">
<h1><a class="toc-backref" href="#id13" name="controlling-overload-resolution">4   Controlling Overload Resolution</a></h1>
<h1><a class="toc-backref" href="#id13" name="controlling-overload-resolution">4<EFBFBD><EFBFBD><EFBFBD>Controlling Overload Resolution</a></h1>
<p>The parameters of our templated forwarding functions are completely
general; in fact, they're a perfect match for any argument type
whatsoever. The problems with exposing such general function
@@ -330,7 +330,7 @@ by callers; they merely trigger SFINAE by becoming illegal types
when the <tt class="literal"><span class="pre">name</span></tt> argument is not convertible to <tt class="literal"><span class="pre">const</span> <span class="pre">char*</span></tt>.</p>
</div>
<div class="section" id="lazy-evaluation-of-defaults">
<h1><a class="toc-backref" href="#id14" name="lazy-evaluation-of-defaults">5   Lazy Evaluation of Defaults</a></h1>
<h1><a class="toc-backref" href="#id14" name="lazy-evaluation-of-defaults">5<EFBFBD><EFBFBD><EFBFBD>Lazy Evaluation of Defaults</a></h1>
<p>If computing an argument's default value is expensive, it's best
avoided when the argument is supplied by the user. In that case,
the default value can be lazily evaluated using the following
@@ -359,7 +359,7 @@ void bar_impl(Params const&amp; params)
</pre>
</div>
<div class="section" id="automatic-overload-generation">
<h1><a class="toc-backref" href="#id15" name="automatic-overload-generation">6   Automatic Overload Generation</a></h1>
<h1><a class="toc-backref" href="#id15" name="automatic-overload-generation">6<EFBFBD><EFBFBD><EFBFBD>Automatic Overload Generation</a></h1>
<p>To reduce the work needed to write functions with named parameters,
we supply a macro that generates the boilerplate code.</p>
<p>Synopsis:</p>
@@ -382,7 +382,7 @@ BOOST_NAMED_PARAMS_FUN(void, foo, 0, 2, foo_keywords)
</pre>
</div>
<div class="section" id="portability">
<h1><a class="toc-backref" href="#id16" name="portability">7   Portability</a></h1>
<h1><a class="toc-backref" href="#id16" name="portability">7<EFBFBD><EFBFBD><EFBFBD>Portability</a></h1>
<p>Boost.NamedParams has been confirmed to work on the following compilers:</p>
<blockquote>
<ul class="simple">
@@ -437,7 +437,7 @@ of lack of SFINAE support.</td></tr>
<hr class="footer" />
<div class="footer">
<a class="reference" href="named_params.rst">View document source</a>.
Generated on: 2004-03-04 10:40 UTC.
Generated on: 2004-04-17 10:54 UTC.
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
</div>
</body>

View File

@@ -14,7 +14,7 @@ __ ../../../index.htm
:Authors: David Abrahams, Daniel Wallin
:Contact: dave@boost-consulting.com, dalwan01@student.umu.se
:organizations: `Boost Consulting`_,
:date: $Date$
:date: $Date: 2005-03-27 23:35:50 -0500 (Sun, 27 Mar 2005) $
:copyright: Copyright David Abrahams, Daniel Wallin 2003.
:license: Use, modification and distribution is subject to the
Boost Software License, Version 1.0. (See accompanying
@@ -124,8 +124,8 @@ function. These keywords should be declared in the same order as
their corresponding parameters appear in the function's parameter
list::
struct foo_keywords
: boost::keywords<
struct foo_parameters
: boost::parameters<
name_t
, value_t
>
@@ -141,19 +141,19 @@ Defining the forwarding functions
void foo()
{
foo_impl(foo_keywords());
foo_impl(foo_parameters()());
}
template<class A0>
void foo(const A0& a0)
{
foo_impl(foo_keywords(a0));
foo_impl(foo_parameters()(a0));
}
template<class A0, class A1>
void foo(const A0& a0, const A1& a1)
{
foo_impl(foo_keywords(a0, a1));
foo_impl(foo_parameters()(a0, a1));
}
Defining the implementation function
@@ -293,8 +293,8 @@ of ``boost::named_param``:
.. parsed-literal::
struct foo_keywords
: boost::keywords<
struct foo_parameters
: boost::parameters<
**boost::named_param<
name_t
, mpl::false\_
@@ -312,7 +312,7 @@ Now we can add an additional optional argument to each of our
template<class A0>
void foo(
const A0& a0
, **foo_keywords::restrict<A0>::type x = foo_keywords()**
, **foo_parameters::restrict<A0>::type x = foo_parameters()**
)
{
foo_impl(x(a0));
@@ -321,7 +321,7 @@ Now we can add an additional optional argument to each of our
template<class A0, class A1>
void foo(
const A0& a0, const A1& a1
, **foo_keywords::restrict<A0,A1>::type x = foo_keywords()**
, **foo_parameters::restrict<A0,A1>::type x = foo_parameters()**
)
{
foo_impl(x(a0, a1));
@@ -372,14 +372,14 @@ Synopsis::
BOOST_NAMED_PARAMS_FUN(
return_type, function_name
, min_arity, max_arity, keywords_type
, min_arity, max_arity, parameters_type
);
To generate all the forwarding functions and the implementation
function for our example, we need only apply
``BOOST_NAMED_PARAMS_FUN`` this way::
BOOST_NAMED_PARAMS_FUN(void, foo, 0, 2, foo_keywords)
BOOST_NAMED_PARAMS_FUN(void, foo, 0, 2, foo_parameters)
{
std::cout
<< p[name | "unnamed"] << " = "

192
doc/named_params_ref.rst Executable file
View File

@@ -0,0 +1,192 @@
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The Boost.NamedParams Library Reference |(logo)|__ INCOMPLETE
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.. |(logo)| image:: ../../../c++boost.gif
:alt: Boost
:class: boost-logo
__ ../../../index.htm
-------------------------------------
:Authors: David Abrahams, Daniel Wallin
:Contact: dave@boost-consulting.com, dalwan01@student.umu.se
:organizations: `Boost Consulting`_,
:date: $Date: 2005-03-27 23:35:50 -0500 (Sun, 27 Mar 2005) $
:copyright: Copyright David Abrahams, Daniel Wallin 2003.
:license: 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)
.. _`Boost Consulting`: http://www.boost-consulting.com
.. contents::
concept ``keyword-expression``
------------------------------
.. parsed-literal::
template<class Tag>
*bound-argument* operator[](*keyword-expression*, keyword<Tag>)
**Requires**
An argument tagged with ``Tag`` must be bound in the object.
**Returns**
A reference to the bound argument tagged with ``Tag``.
**Throws**
Nothrow.
**Complexity**
O(1) runtime. O(1) compile time on good compilers. O(N), where N is
the number of bound arguments, on old compilers such as VC6.
.. parsed-literal::
*bound-argument* operator[](*keyword-expression*, *named-default-expression*)
**Requires**
Nothing.
**Returns**
A reference to the bound argument tagged with
*named-default-expression*::key_type. If no such argument is bound, the
default value as given by the *named-default-expression* instance is
returned.
**Throws**
Nothrow.
**Complexity**
O(1) runtime. O(1) compile time on good compilers. O(N), where N is
the number of bound arguments, on old compilers such as VC6.
concept ``named-default-expression``
------------------------------------
...
concept ``lazy-default-expression``
-----------------------------------
...
class template ``keyword``
--------------------------
.. parsed-literal::
template<class Tag>
struct keyword
{
template<class T>
*keyword-expression* operator=(T&) const;
template<class T>
*keyword-expression* operator=(T const&) const;
template<class Default>
*named-default-expression* operator|(Default&) const;
template<class Default>
*named-default-expression* operator|(Default const&) const;
template<class LazyDefault>
*unspecified* operator||(LazyDefault const&) const;
};
Denotes a argument keyword. ``Tag`` is a tag class, typically an incomplete type.
::
template<class T> operator=(T&)
template<class T> operator=(T const&)
**Requires**
Nothing.
**Returns**
An object that holds a cv reference to ``x``, tagged with the keyword
``Tag`` type. If ``T`` is an instance of ``boost::reference_wrapper<U cv>``
the tagged result will hold a reference to ``U cv``.
**Complexity**
O(1) compile time and run time.
**Throws**
Nothrow.
.. parsed-literal::
template<class Default>
*named-default-expression* operator|(Default&) const
template<class Default>
*named-default-expression* operator|(Default const&) const
**Requires**
Nothing.
**Returns**
An object holding a reference to the given default value, tagged
with ``Tag``.
.. parsed-literal::
template<class LazyDefault>
*lazy-default-expression* operator||(LazyDefault const& x) const;
**Requires**
``LazyDefault`` is a nullary function object, with the following
properties:
======================== =======================================
Expression Result
======================== =======================================
LazyDefault::result_type Must to Copyable
x() Convertible to LazyDefault::result_type
======================== =======================================
**Returns**
...
.. parsed-literal::
template<
class Tag
, class HasDefault = mpl::true\_
, class Predicate = mpl::always<mpl::true\_>
>
struct named_param
{
typedef Tag key_type;
typedef HasDefault has_default;
typedef Predicate predicate;
};
template<class K0, class K1, ..., class KN>
struct parameters
{
template<class T0, class T1, ..., class TN>
*keyword-expression* operator()(T0 const&, T1 const&, ..., TN const&) const;
};
* <K0, ..., KN> is either a tag type, as specified in ``keyword``, or an instantiation of
``named_param``.
::
template<class T0, class T1, ..., class TN> operator()(T0 const&, T1 const&, ..., TN const&) const;
Composes all parameters, named and positional, into an object that can be used to query
for specific keywords.

View File

@@ -1,167 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library name="Tribool" dirname="utility/tribool" id="tribool"
last-revision="$Date$" xmlns:xi="http://www.w3.org/2001/XInclude">
<libraryinfo>
<author>
<firstname>Douglas</firstname>
<surname>Gregor</surname>
<email>gregod@cs.rpi.edu</email>
</author>
<copyright>
<year>2002</year>
<year>2003</year>
<holder>Douglas Gregor</holder>
</copyright>
<legalnotice>
<para>Permission to copy, use, sell and distribute this software
is granted provided this copyright notice appears in all copies.
Permission to modify the code and to distribute modified code is
granted provided this copyright notice appears in all copies, and
a notice that the code was modified is included with the copyright
notice. </para>
<para> This software is provided "as is" without express or
implied warranty, and with no claim as to its suitability for any
purpose. </para>
</legalnotice>
<librarypurpose>Three-state boolean type</librarypurpose>
<librarycategory name="category:misc"/>
</libraryinfo>
<section id="tribool.introduction">
<title>Introduction</title>
<para>The 3-state boolean library contains a single class,
<code><classname>boost::tribool</classname></code>, along with
support functions and operator overloads that implement 3-state
boolean logic. </para>
</section>
<section id="tribool.tutorial">
<title>Tutorial</title>
<using-namespace name="boost"/>
<para> The <code><classname>tribool</classname></code> class acts
like the built-in <code>bool</code> type, but for 3-state boolean
logic. The three states are <code>true</code>, <code>false</code>,
and <code><functionname>indeterminate</functionname></code>, where
the first two states are equivalent to those of the C++
<code>bool</code> type and the last state represents an unknown
boolean value (that may be <code>true</code> or
<code>false</code>, we don't know).</para>
<para> The <code><classname>tribool</classname></code> class
supports conversion from <code>bool</code> values and literals
along with its own
<code><functionname>indeterminate</functionname></code>
keyword:</para>
<programlisting><classname>tribool</classname> b(true);
b = false;
b = <functionname>indeterminate</functionname>;
<classname>tribool</classname> b2(b);</programlisting>
<para> <code><classname>tribool</classname></code> supports
conversions to <code>bool</code> for use in conditional
statements. The conversion to <code>bool</code> will be
<code>true</code> when the value of the
<code><classname>tribool</classname></code> is always true, and
<code>false</code> otherwise.</para>
<programlisting><classname>tribool</classname> b = some_operation();
if (b) {
// b is true
}
else if (!b) {
// b is false
}
else {
// b is indeterminate
}</programlisting>
<para> <code><classname>tribool</classname></code> supports the
3-state logic operators <code>!</code> (negation),
<code>&amp;&amp;</code> (AND), and <code>||</code> (OR), with
<code>bool</code> and <code><classname>tribool</classname></code>
values. For instance:</para>
<programlisting><classname>tribool</classname> x = some_op();
<classname>tribool</classname> y = some_other_op();
if (x &amp;&amp; y) {
// both x and y are true
}
else if (!(x &amp;&amp; y)) {
// either x or y is false
}
else {
// neither x nor y is false, but we don't know that both are true
if (x || y) {
// either x or y is true, or both
}
}</programlisting>
<para> Similarly, <code><classname>tribool</classname></code>
supports 3-state equality comparisons via the operators
<code>==</code> and <code>!=</code>. These operators differ from
"normal" equality operators in C++ because they return a
<code><classname>tribool</classname></code>, because potentially we
might not know the result of a comparison (try to compare
<code>true</code> and
<code><functionname>indeterminate</functionname></code>). For
example:</para>
<programlisting><classname>tribool</classname> x(true);
<classname>tribool</classname> y(<functionname>indeterminate</functionname>);
assert(x == x); // okay, x == x returns true
assert(!(y == y)); // okay, because y == y is <functionname>indeterminate</functionname>
assert(x == true); // okay, can compare <classname>tribool</classname>s and bools</programlisting>
<para> The <code><functionname>indeterminate</functionname></code> keyword (representing the
<functionname>indeterminate</functionname>&nbsp;<code><classname>tribool</classname></code> value)
doubles as a function to check if the value of a
<code><classname>tribool</classname></code> is indeterminate,
e.g.,</para>
<programlisting><classname>tribool</classname> x = try_to_do_something_tricky();
if (<functionname>indeterminate</functionname>(x)) {
// value of x is indeterminate
}
else {
// report success or failure of x
}</programlisting>
<para> Users may introduce additional keywords for the indeterminate
value in addition to the implementation-supplied
<code><functionname>indeterminate</functionname></code> using the
<code><macroname>BOOST_TRIBOOL_THIRD_STATE</macroname></code>
macro. For instance, the following macro instantiation (at the
global scope) will introduce the keyword <code>maybe</code> as a
synonym for <code><functionname>indeterminate</functionname></code>
(also residing in the <code>boost</code> namespace):</para>
<programlisting><macroname>BOOST_TRIBOOL_THIRD_STATE</macroname>(maybe)</programlisting>
</section>
<xi:include href="reference.boostbook"/>
<testsuite>
<run-test filename="tribool_test.cpp">
<purpose><para>Test all features of the
<code><classname>boost::tribool</classname></code>
class.</para></purpose>
</run-test>
<run-test filename="tribool_rename_test.cpp">
<purpose><para>Test the use of the
<code><macroname>BOOST_TRIBOOL_THIRD_STATE</macroname></code>
macro.</para></purpose>
</run-test>
</testsuite>
</library>

View File

@@ -1,249 +0,0 @@
#ifndef BOOST_REF_HPP_INCLUDED
# define BOOST_REF_HPP_INCLUDED
# if _MSC_VER+0 >= 1020
# pragma once
# endif
# include <boost/config.hpp>
# include <boost/utility/addressof.hpp>
# include <boost/type_traits/ice.hpp>
# include <boost/type.hpp>
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
# include <boost/result_of.hpp>
# endif
# include <boost/preprocessor/iterate.hpp>
# include <boost/pending/ct_if.hpp>
//
// ref.hpp - ref/cref, useful helper functions
//
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001, 2002 Peter Dimov
// Copyright (C) 2002 David Abrahams
// Copyright (C) 2003 Doug Gregor
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/bind/ref.html for documentation.
//
# ifndef BOOST_REF_NUM_ARGS
# define BOOST_REF_NUM_ARGS 10
# endif
namespace boost
{
namespace detail { namespace ref {
template<typename T>
class reference_wrapper_without_result_type
{
public:
template<typename F>
struct result_of
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
: boost::result_of<F>
# endif
{
};
operator T& () const { return *(this->t_); }
T& get() const { return *(this->t_); }
T* get_pointer() const { return this->t_; }
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
&& !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_REF_NUM_ARGS,<boost/detail/ref_iterate.hpp>))
# include BOOST_PP_ITERATE()
# endif
protected:
# if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
explicit reference_wrapper_without_result_type(T& t) : t_(&t) {}
# else
explicit reference_wrapper_without_result_type(T& t) : t_(addressof(t)) {}
# endif
private:
T* t_;
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
class reference_wrapper_with_result_type
{
public:
typedef typename T::result_type result_type;
operator T& () const { return *(this->t_); }
T& get() const { return *(this->t_); }
T* get_pointer() const { return this->t_; }
result_type operator()() const { return get()(); }
# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_REF_NUM_ARGS,<boost/detail/ref_iterate.hpp>))
# include BOOST_PP_ITERATE()
# endif
protected:
# if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
explicit reference_wrapper_with_result_type(T& t) : t_(&t) {}
# else
explicit reference_wrapper_with_result_type(T& t) : t_(addressof(t)) {}
# endif
private:
T* t_;
};
template<typename T>
class reference_wrapper_impl :
public ct_if<(has_result_type<T>::value),
reference_wrapper_with_result_type<T>,
reference_wrapper_without_result_type<T> >::type
{
typedef typename ct_if<(has_result_type<T>::value),
reference_wrapper_with_result_type<T>,
reference_wrapper_without_result_type<T> >::type
inherited;
protected:
reference_wrapper_impl(T& t) : inherited(t) {}
};
# else
template<typename T>
class reference_wrapper_impl : public reference_wrapper_without_result_type<T>
{
typedef reference_wrapper_without_result_type<T> inherited;
protected:
reference_wrapper_impl(T& t) : inherited(t) {}
};
# endif
} } // end namespace detail::ref
template<class T>
class reference_wrapper : public detail::ref::reference_wrapper_impl<T>
{
typedef detail::ref::reference_wrapper_impl<T> inherited;
public:
typedef T type;
explicit reference_wrapper(T& t) : inherited(t) {}
};
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
# define BOOST_REF_CONST
# else
# define BOOST_REF_CONST const
# endif
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
{
return reference_wrapper<T>(t);
}
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
{
return reference_wrapper<T const>(t);
}
# undef BOOST_REF_CONST
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
class is_reference_wrapper
{
public:
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
class is_reference_wrapper<reference_wrapper<T> >
{
public:
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<typename T>
class unwrap_reference
{
public:
typedef T type;
};
template<typename T>
class unwrap_reference<reference_wrapper<T> >
{
public:
typedef T type;
};
# else // no partial specialization
} // namespace boost
namespace boost
{
namespace detail
{
typedef char (&yes_reference_wrapper_t)[1];
typedef char (&no_reference_wrapper_t)[2];
no_reference_wrapper_t is_reference_wrapper_test(...);
template<typename T>
yes_reference_wrapper_t
is_reference_wrapper_test(type< reference_wrapper<T> >);
template<bool wrapped>
struct reference_unwrapper
{
template <class T>
struct apply
{
typedef T type;
};
};
template<>
struct reference_unwrapper<true>
{
template <class T>
struct apply
{
typedef typename T::type type;
};
};
}
template<typename T>
class is_reference_wrapper
{
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(detail::is_reference_wrapper_test(type<T>()))
== sizeof(detail::yes_reference_wrapper_t)));
};
template <typename T>
class unwrap_reference
: public detail::reference_unwrapper<
is_reference_wrapper<T>::value
>::template apply<T>
{};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace boost
#endif // #ifndef BOOST_REF_HPP_INCLUDED

View File

@@ -0,0 +1,17 @@
//object_tracked with DTOR check for double destruction (death)
#ifndef BOOST_DEBUG_UTILITY_CHK_DBL_DELETE_HPP_LJE20040129
#define BOOST_UTILITY_CHK_DBL_DELETE_HPP_LJE20040129
#include "boost/utility/object_tracked.hpp"
#include <boost/test/test_tools.hpp>
namespace utility
{
struct chk_dbl_die
: public object_tracked
{
~chk_dbl_die(void)
{
BOOST_CHECK(am_i_live());
}
};
}//exit utility namespace
#endif

View File

@@ -0,0 +1,49 @@
#ifndef UTILITY_OBJ_ID_HPP
#define UTILITY_OBJ_ID_HPP
namespace utility
{
struct obj_id
/**@class obj_id
* @brief Provide unique id for objects
*/
{
typedef
unsigned
id_type
;
~obj_id(void)
{}
obj_id(void)
:m_id(the_last_id()++)
{}
obj_id(obj_id const&)
:m_id(the_last_id()++)
{}
void
operator=(obj_id const&)
{}
id_type
id_get(void)const
{ return m_id
;}
static
id_type&
the_last_id(void)
//reference to count if id's created
;
private:
id_type
m_id
;
};//end obj_id struct
}//exit utility namespace
//----------------------------
//ChangeLog:
// 2005-06-17: Larry Evans
// WHAT:
// rm'ed virtual DTOR
// WHY:
// comment that had accompanied it and justified use of
// virtual DTOR is no longer relevant.
#endif

View File

@@ -0,0 +1,118 @@
//Simple class which keeps track of members
#ifndef UTILITY_OBJECT_TRACKED_HPP_LJE20040112
#define UTILITY_OBJECT_TRACKED_HPP_LJE20040112
//#define UTILITY_OBJECT_TRACKED_SET_OF_OBJECTS_TRACE_MODE
//#define UTILITY_OBJECT_TRACKED_TRACE_MODE
#include <set>
#include "boost/utility/obj_id.hpp"
#if defined(UTILITY_OBJECT_TRACKED_SET_OF_OBJECTS_TRACE_MODE)\
|| defined(UTILITY_OBJECT_TRACKED_TRACE_MODE)
#include "boost/io/filters/mout.hpp"
#endif
namespace utility
{
class object_tracked
: public obj_id
{
private:
struct
set_of_objects_tracked
: public std::set<object_tracked const*>
{
typedef
std::set<object_tracked const*>
super_type
;
~set_of_objects_tracked(void)
{
#ifdef UTILITY_OBJECT_TRACKED_SET_OF_OBJECTS_TRACE_MODE
mout()<<"set_of_objects_tracked-\n";
#endif
}
set_of_objects_tracked(void)
{
#ifdef UTILITY_OBJECT_TRACKED_SET_OF_OBJECTS_TRACE_MODE
mout()<<"set_of_objects_tracked+\n";
#endif
}
void
reset(void)
{
super_type::clear();
obj_id::the_last_id() = 0;
}
bool
contains(object_tracked const*& a_obj)const
{
return find(a_obj) != end();
}
};
static
set_of_objects_tracked
our_members
;
public:
static
void
reset(void)
{
our_members.reset();
}
static
unsigned
members_size(void)
{
return our_members.size();
}
object_tracked(void)
{
our_members.insert(this);
#ifdef UTILITY_OBJECT_TRACKED_TRACE_MODE
mout()<<"object_tracked+:id="<<id_get()<<":default\n";
#endif
}
object_tracked(object_tracked const& a_obj)
{
our_members.insert(this);
#ifdef UTILITY_OBJECT_TRACKED_TRACE_MODE
mout()<<"object_tracked+:id="<<id_get()<<":copy\n";
#endif
}
virtual
~object_tracked(void)
{
#ifdef UTILITY_OBJECT_TRACKED_TRACE_MODE
mout()<<"object_tracked-:id="<<id_get()<<":am_i_live="<<am_i_live()<<"\n";
#endif
utility::object_tracked const*me=this;
our_members.erase(me);
}
bool
am_i_live(void)const
//Purpose:
// Used to check for multiple destructor calls. Should always return true
// if only place where our_members.erase is called is in
// ~object_tracked.
{
utility::object_tracked const*me=this;
bool result=utility::object_tracked::our_members.contains(me);
return result;
}
static
bool
is_live(utility::object_tracked const*a_ot)
{
bool result=utility::object_tracked::our_members.contains(a_ot);
return result;
}
};
}//exit utility namespace
#endif

View File

@@ -0,0 +1,40 @@
#ifndef UTILITY_TRACE_SCOPE_HPP
#define UTILITY_TRACE_SCOPE_HPP
#include "boost/io/filters/mout.hpp"
#include <string>
namespace utility
{
class
trace_scope
//Purpose:
// Indicate on cout when a scope entered and exited.
{
public:
trace_scope(char const* a_scopeName)
: m_scopeName(a_scopeName)
{ init()
;}
trace_scope(std::string const& a_scopeName)
: m_scopeName(a_scopeName)
{ init()
;}
~trace_scope(void)
{
; --mout()
; std::string l_context("===>Exit:")
; mout()<<l_context<<m_scopeName<<std::endl
;}
private:
void
init(void)
{
; std::string l_context("===>Enter:")
; mout()<<l_context<<m_scopeName<<std::endl
; ++mout()
;}
std::string
m_scopeName
;
};//end trace_scope class
}//exit utility namespace
#endif

View File

@@ -0,0 +1,46 @@
#ifndef UTILITY_TRACE_SCOPE_STK_HPP
#define UTILITY_TRACE_SCOPE_STK_HPP
#include <vector>
#include "boost/utility/trace_scope.hpp"
namespace utility
{
struct trace_scope_stk
: public trace_scope
//Purpose:
// Simply keeps a stack variables of
// type trace_scope_stk
{
public:
static
std::string const&
top_name(void)
{ return c_scope_names.back()
;}
static
std::string const
top_result(bool result_bool)
{ std::string result_string(c_scope_names.back())
; result_string += std::string(":result=")
; result_string += c_test_results[result_bool]
; return result_string
;}
trace_scope_stk(std::string const& a_name)
: trace_scope(a_name)
{ c_scope_names.push_back(a_name)
;}
~trace_scope_stk(void)
{ c_scope_names.pop_back()
;}
private:
static
std::vector<std::string>
c_scope_names
;
static
std::string const
c_test_results[2]
;
};
}//exit utility namespace
#endif

View File

@@ -3,14 +3,14 @@
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
class int_result_type { typedef int result_type; };
struct int_result_type { typedef int result_type; };
class int_result_of
struct int_result_of
{
template<typename F> struct result { typedef int type; };
};
class int_result_type_and_float_result_of
struct int_result_type_and_float_result_of
{
typedef int result_type;
template<typename F> struct result { typedef float type; };
@@ -23,13 +23,23 @@ int main()
using namespace boost;
typedef int (*func_ptr)(float, double);
typedef int (&func_ref)(float, double);
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;
typedef int (X::*mem_func_ptr_cv)(float) const volatile;
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type(float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of(double)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of(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<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));
return 0;
}

10
src/obj_id.cpp Normal file
View File

@@ -0,0 +1,10 @@
#include "boost/utility/obj_id.hpp"
using namespace utility;
// static
obj_id::
id_type&
obj_id::
the_last_id(void)
{ static id_type last_id=0
; return last_id
;}

6
src/object_tracked.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "boost/utility/object_tracked.hpp"
using namespace utility;
utility::object_tracked::set_of_objects_tracked
utility::object_tracked::our_members
;

12
src/trace_scope_stk.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include "boost/utility/trace_scope_stk.hpp"
// static
std::vector<std::string>
utility::trace_scope_stk::
c_scope_names
;
// static
std::string const
utility::trace_scope_stk::
c_test_results[2]
= {"failed", "passed"}
;

View File

@@ -6,18 +6,17 @@ subproject libs/utility/test ;
import testing ;
{
test-suite "utility"
test-suite "lexicographic"
: [ run lexicographic_test.cpp ]
[ run lex_performance_test.cpp ]
[ run named_params_test.cpp ]
;
test-suite "named_params"
: [ run named_params_test.cpp ]
[ run named_params_sfinae.cpp ]
[ run enable_if_constructors.cpp ]
[ run enable_if_member_templates.cpp ]
[ run enable_if_dummy_arg_disambiguation.cpp ]
[ run enable_if_namespace_disambiguation.cpp ]
[ run enable_if_lazy.cpp ]
[ run enable_if_no_disambiguation.cpp ]
[ run enable_if_lazy_test.cpp ]
[ run enable_if_partial_specializations.cpp ]
;
test-suite "result_check"
: [ compile result_check_test.cpp ]
;
}

View File

@@ -11,55 +11,54 @@
namespace test
{
using boost::keyword;
using boost::keywords;
using boost::named_param;
using namespace boost::named_params;
struct name_t; keyword<name_t> name;
struct value_t; keyword<value_t> value;
keyword<struct name_> name;
keyword<struct value_> value;
struct f_keywords
: keywords<
named_param<
name_t
, boost::mpl::true_
, boost::is_convertible<boost::mpl::_, std::string>
>
, named_param<
value_t
, boost::mpl::true_
, boost::is_convertible<boost::mpl::_, float>
>
struct f_parameters
: parameters<
optional<
name_
, boost::is_convertible<boost::mpl::_, std::string>
>
, optional<
value_
, boost::is_convertible<boost::mpl::_, float>
>
>
{};
template <class T> struct not_implemented;
template<class P>
void f_impl(P const& p)
{
std::string s = p[name | "bar"];
float v = p[value | 3.f];
std::cout << "s is " << s << std::endl;
assert(s == "foo");
assert(v == 3.f);
}
void f()
void f(...)
{
f_impl(f_keywords()());
f_impl(f_parameters()());
}
template<class A0>
void f(A0 const& a0
, typename f_keywords::restrict<A0>::type = f_keywords())
, typename f_parameters::restrict<A0>::type = f_parameters())
{
f_impl(f_keywords()(a0));
f_impl(f_parameters()(a0));
}
template<class A0, class A1>
void f(A0 const& a0, A1 const& a1
, typename f_keywords::restrict<A0, A1>::type = f_keywords())
, typename f_parameters::restrict<A0, A1>::type = f_parameters())
{
f_impl(f_keywords()(a0, a1));
f_impl(f_parameters()(a0, a1));
}
} // namespace test

View File

@@ -8,32 +8,23 @@
#include <string.h>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <boost/static_assert.hpp>
namespace test
{
using namespace boost::named_params;
using boost::keyword;
using boost::keywords;
using boost::named_param;
keyword<struct name_> name;
keyword<struct value_> value;
keyword<struct index_> index;
keyword<struct tester_> tester;
struct name_t;
keyword<name_t> name;
struct value_t;
keyword <value_t> value;
struct index_t;
keyword<index_t> index;
struct tester_t;
keyword<tester_t> tester;
struct f_keywords // vc6 is happier with inheritance than with a typedef
: keywords<
tester_t
, name_t
, value_t
, index_t
struct f_parameters // vc6 is happier with inheritance than with a typedef
: parameters<
tester_
, name_
, value_
, index_
>
{};
@@ -48,7 +39,8 @@ namespace test
p[tester](
p[name]
, p[value || boost::bind(&value_default) ]
, p[index | 999]
// , p[value | 666.222 ]
, p[index | 999 ]
);
return 1;
}
@@ -57,19 +49,25 @@ namespace test
int f(Tester const& t, const Name& name_,
const Value& value_, const Index& index_)
{
return f_impl(f_keywords()(t, name_, value_, index_));
return f_impl(f_parameters()(t, name_, value_, index_));
}
template<class Tester, class Name, class Value>
int f(Tester const& t, const Name& name_, const Value& value_)
{
return f_impl(f_keywords()(t, name_, value_));
return f_impl(f_parameters()(t, name_, value_));
}
template<class Tester, class Name>
int f(Tester const& t, const Name& name_)
{
return f_impl(f_keywords()(t, name_));
return f_impl(f_parameters()(t, name_));
}
template<class Params>
int f_list(Params const& params)
{
return f_impl(params);
}
template <class T>
@@ -121,6 +119,26 @@ namespace test
{
return values_t<Name,Value,Index>(n,v,i);
}
typedef f_parameters g_parameters;
template<class Args>
int g_impl(Args const& args)
{
return f(args);
}
template<class A0>
int g(A0 const& a0)
{
return g_impl(g_parameters(a0));
}
template<class A0, class A1>
int g(A0 const& a0, A1 const& a1)
{
return g_impl(g_parameters(a0, a1));
}
}
// GCC2 has a problem with char (&)[] deduction, so we'll cast string
@@ -135,6 +153,7 @@ namespace test
int main()
{
using test::f;
using test::f_list;
using test::name;
using test::value;
using test::index;
@@ -151,6 +170,12 @@ int main()
, index = boost::ref(x), name = "foo"
);
f_list((
tester = test::values("foo", 666.222, 56)
, index = boost::ref(x)
, name = "foo"
));
//f(index = 56, name = 55); // won't compile
return 0;
}

24
test/result_check_test.cpp Executable file
View File

@@ -0,0 +1,24 @@
// Copyright Daniel Wallin 2004. 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)
#include <boost/result_check.hpp>
#include <boost/type_traits/is_same.hpp>
BOOST_RESULT_CHECK(2, add, operator+, _1 + _2)
struct X
{
};
X operator+(X const&, X const&);
X& operator+(X&, X&);
int main()
{
using namespace boost;
BOOST_MPL_ASSERT((check_add<X const&, X const&, is_same<mpl::_, X> >));
BOOST_MPL_ASSERT((check_add<X&, X&, is_same<mpl::_, X&> >));
}