This commit was manufactured by cvs2svn to create branch 'expaler'.

[SVN r2110]
This commit is contained in:
nobody
2004-04-08 01:30:33 +00:00
parent 9ee97bf9a0
commit 0b5a383cb2
32 changed files with 0 additions and 4903 deletions

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,417 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>enable_if</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.06">
</HEAD>
<BODY >
<!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
<!--CUT DEF section 1 -->
<BR>
<BR>
<h1>
<img border="0" src="c++boost.gif" align="center" width="277" height="86">enable_if</h1>
<BR>
<BR>
Copyright 2003 Jaakko J&auml;rvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
<BR>
<!--TOC section Introduction-->
<H2><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
<A NAME="introduction"></A>
The <TT>enable_if</TT> family of templates is a set of tools to allow a function template or a class template specialization
to include or exclude itself from a set of matching functions or specializations
based on properties of its template arguments.
For example, one can define function templates that
are only enabled for, and thus only match, an arbitrary set of types
defined by a traits class. The <TT>enable_if</TT> templates can also be
applied to enable class template specializations. Applications of
<TT>enable_if</TT> are discussed in length
in&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and&nbsp;[<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR>
<BR>
<!--TOC subsection Synopsis-->
<H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;Synopsis</H3><!--SEC END -->
<A NAME="sec:synopsis"></A>
<PRE>
namespace boost {
template &lt;class Cond, class T = void&gt; struct enable_if;
template &lt;class Cond, class T = void&gt; struct disable_if;
template &lt;class Cond, class T&gt; struct lazy_enable_if;
template &lt;class Cond, class T&gt; struct lazy_disable_if;
template &lt;bool B, class T = void&gt; struct enable_if_c;
template &lt;bool B, class T = void&gt; struct disable_if_c;
template &lt;bool B, class T&gt; struct lazy_enable_if_c;
template &lt;bool B, class T&gt; struct lazy_disable_if_c;
}
</PRE>
<!--TOC subsection Background-->
<H3><A NAME="htoc3">1.2</A>&nbsp;&nbsp;Background</H3><!--SEC END -->
<A NAME="sec:background"></A>
Sensible operation of template function overloading in C++ relies
on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error)
principle&nbsp;[<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: if an invalid argument
or return type is formed during the instantiation of a function
template, the instantiation is removed from the overload resolution
set instead of causing a compilation error. The following example,
taken from&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>],
demonstrates why this is important:
<PRE>
int negate(int i) { return -i; }
template &lt;class F&gt;
typename F::result_type negate(const F&amp; f) { return -f(); }
</PRE>
Suppose the compiler encounters the call <TT>negate(1)</TT>. The first
definition is obviously a better match, but the compiler must
nevertheless consider (and instantiate the prototypes) of both
definitions to find this out. Instantiating the latter definition with
<TT>F</TT> as <TT>int</TT> would result in:
<PRE>
int::result_type negate(const int&amp;);
</PRE>
where the return type is invalid. If this was an error, adding an unrelated function template
(that was never called) could break otherwise valid code.
Due to the SFINAE principle the above example is not, however, erroneous.
The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR>
<BR>
The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE
conditions.<BR>
<BR>
<!--TOC section The <TT>enable_if</TT> templates-->
<H2><A NAME="htoc4">2</A>&nbsp;&nbsp;The <TT>enable_if</TT> templates</H2><!--SEC END -->
<A NAME="enable_if"></A>
The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,
either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag.
All eight combinations of these parts are supported.
The meaning of the <TT>lazy_</TT> tag is described in Section&nbsp;<A HREF="#sec:enable_if_lazy">3.3</A>.
The second part of the name indicates whether a true condition argument should
enable or disable the current overload.
The third part of the name indicates whether the condition argument is a <TT>bool</TT> value
(<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix).
The latter version interoperates with Boost.MPL. <BR>
<BR>
The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates
unqualified but they are in the <TT>boost</TT> namespace).
<PRE>
template &lt;bool B, class T = void&gt;
struct enable_if_c {
typedef T type;
};
template &lt;class T&gt;
struct enable_if_c&lt;false, T&gt; {};
template &lt;class Cond, class T = void&gt;
struct enable_if : public enable_if_c&lt;Cond::value, T&gt; {};
</PRE>
An instantiation of the <TT>enable_if_c</TT> template with the parameter
<TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined
to be <TT>T</TT>. If <TT>B</TT> is
<TT>false</TT>, no such member is defined. Thus
<TT>enable_if_c&lt;B, T&gt;::type</TT> is either a valid or an invalid type
expression, depending on the value of <TT>B</TT>.
When valid, <TT>enable_if_c&lt;B, T&gt;::type</TT> equals <TT>T</TT>.
The <TT>enable_if_c</TT> template can thus be used for controlling when functions are considered for
overload resolution and when they are not.
For example, the following function is defined for all arithmetic types (according to the
classification of the <A HREF="http://www.boost.org/libs/type_traits">Boost type_traits library</A>):
<PRE>
template &lt;class T&gt;
typename enable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
foo(T t) { return t; }
</PRE>
The <TT>disable_if_c</TT> template is provided as well, and has the
same functionality as <TT>enable_if_c</TT> except for the negated condition. The following
function is enabled for all non-arithmetic types.
<PRE>
template &lt;class T&gt;
typename disable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
bar(T t) { return t; }
</PRE>
For easier syntax in some cases and interoperation with Boost.MPL we provide versions of
the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named
<TT>value</TT> as the condition argument.
The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> templates are likely to be
useful for creating such types. Also, the traits classes in the Boost.Type_traits library
follow this convention.
For example, the above example function <TT>foo</TT> can be alternatively written as:
<PRE>
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t) { return t; }
</PRE>
<!--TOC section Using <TT>enable_if</TT>-->
<H2><A NAME="htoc5">3</A>&nbsp;&nbsp;Using <TT>enable_if</TT></H2><!--SEC END -->
<A NAME="sec:using_enable_if"></A>
The <TT>enable_if</TT> templates are defined in
<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
<BR>
The <TT>enable_if</TT> template can be used either as the return type, or as an
extra argument. For example, the <TT>foo</TT> function in the previous section could also be written
as:
<PRE>
template &lt;class T&gt;
T foo(T t, typename enable_if&lt;boost::is_arithmetic&lt;T&gt; &gt;::type* dummy = 0);
</PRE>Hence, an extra parameter of type <TT>void*</TT> is added, but it is given
a default value to keep the parameter hidden from client code.
Note that the second template argument was not given to <TT>enable_if</TT>, as the default
<TT>void</TT> gives the desired behavior.<BR>
<BR>
Whether to write the enabler as an argument or within the return type is
largely a matter of taste, but for certain functions, only one
alternative is possible:
<UL><LI>
Operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used in the return type.
<LI>Constructors and destructors do not have a return type; an extra argument is the only option.
<LI>There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors,
however, can have enablers as extra default arguments.
</UL>
<!--TOC subsection Enabling template class specializations-->
<H3><A NAME="htoc6">3.1</A>&nbsp;&nbsp;Enabling template class specializations</H3><!--SEC END -->
<A NAME="sec:enable_if_classes"></A>
Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
One extra template parameter needs to be added for the enabler expressions.
This parameter has the default value <TT>void</TT>.
For example:
<PRE>
template &lt;class T, class Enable = void&gt;
class A { ... };
template &lt;class T&gt;
class A&lt;T, typename enable_if&lt;is_integral&lt;T&gt; &gt;::type&gt; { ... };
template &lt;class T&gt;
class A&lt;T, typename enable_if&lt;is_float&lt;T&gt; &gt;::type&gt; { ... };
</PRE>Instantiating <TT>A</TT> with any integral type matches the first specialization,
whereas any floating point type matches the second one. All other types
match the primary template.
The condition can be any compile-time boolean expression that depends on the
template arguments of the class.
Note that again, the second argument to <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)
is the correct value.<BR>
<BR>
<!--TOC subsection Overlapping enabler conditions-->
<H3><A NAME="htoc7">3.2</A>&nbsp;&nbsp;Overlapping enabler conditions</H3><!--SEC END -->
<A NAME="sec:overlapping_conditions"></A>
Once the compiler has examined the enabling conditions and included the
function into the overload resolution set, normal C++ overload resolution
rules are used to select the best matching function.
In particular, there is no ordering between enabling conditions.
Function templates with enabling conditions that are not mutually exclusive can
lead to ambiguities. For example:
<PRE>
template &lt;class T&gt;
typename enable_if&lt;boost::is_integral&lt;T&gt;, void&gt;::type
foo(T t) {}
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, void&gt;::type
foo(T t) {}
</PRE>
All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>,
both conditions are true and both functions are thus in the overload resolution set.
They are both equally good matches and thus ambiguous.
Of course, more than one enabling condition can be simultaneously true as long as
other arguments disambiguate the functions.<BR>
<BR>
The above discussion applies to using <TT>enable_if</TT> in class template
partial specializations as well.<BR>
<BR>
<!--TOC subsection Lazy <TT>enable_if</TT>-->
<H3><A NAME="htoc8">3.3</A>&nbsp;&nbsp;Lazy <TT>enable_if</TT></H3><!--SEC END -->
<A NAME="sec:enable_if_lazy"></A>
In some cases it is necessary to avoid instantiating part of a
function signature unless an enabling condition is true. For example:
<PRE>
template &lt;class T, class U&gt; class mult_traits;
template &lt;class T, class U&gt;
typename enable_if&lt;is_multipliable&lt;T, U&gt;, typename mult_traits&lt;T, U&gt;::type&gt;::type
operator*(const T&amp; t, const U&amp; u) { ... }
</PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining
the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits
class specifies for which types to enable the operator. Whenever
<TT>is_multipliable&lt;A, B&gt;::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>,
then <TT>mult_traits&lt;A, B&gt;::type</TT> is defined.<BR>
<BR>
Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT>
for which <TT>is_multipliable&lt;C, D&gt;::value</TT> is <TT>false</TT>
and <TT>mult_traits&lt;C, D&gt;::type</TT> is not defined is an error on some compilers.
The SFINAE principle is not applied because
the invalid type occurs as an argument to another template. The <TT>lazy_enable_if</TT>
and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such
situations:
<PRE>
template&lt;class T, class U&gt;
typename lazy_enable_if&lt;is_multipliable&lt;T, U&gt;, mult_traits&lt;T, U&gt; &gt;::type
operator*(const T&amp; t, const U&amp; u) { ... }
</PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type
that defines a nested type named <TT>type</TT> whenever the first
parameter (the condition) is true.<BR>
<BR>
<!--TOC paragraph Note-->
<H5>Note</H5><!--SEC END -->
Referring to one member type or static constant in a traits class
causes all of the members (type and static constant) of that
specialization to be instantiated. Therefore, if your traits classes
can sometimes contain invalid types, you should use two distinct
templates for describing the conditions and the type mappings. In the
above example, <TT>is_multipliable&lt;T, U&gt;::value</TT> defines when
<TT>mult_traits&lt;T, U&gt;::type</TT> is valid.<BR>
<BR>
<!--TOC subsection Compiler workarounds-->
<H3><A NAME="htoc9">3.4</A>&nbsp;&nbsp;Compiler workarounds</H3><!--SEC END -->
<A NAME="sec:workarounds"></A>
Some compilers flag functions as ambiguous if the only distinguishing factor is a different
condition in an enabler (even though the functions could never be ambiguous). For example,
some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous:
<PRE>
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
</PRE>Two workarounds can be applied:
<UL><LI>
Use an extra dummy parameter which disambiguates the functions. Use a default value for
it to hide the parameter from the caller. For example:
<PRE>
template &lt;class T&gt; struct dummy { dummy(int) {} };
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t, dummy&lt;0&gt; = 0);
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t, dummy&lt;1&gt; = 0);
</PRE><BR>
<BR>
<LI>Define the functions in different namespaces and bring them into a common
namespace with <TT>using</TT> declarations:
<PRE>
namespace A {
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
}
namespace B {
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
}
using A::foo;
using B::foo;
</PRE>
Note that the second workaround above cannot be used for member
templates. On the other hand, operators do not accept extra arguments,
which makes the first workaround unusable. As the net effect,
neither of the workarounds are of assistance for templated operators that
need to be defined as member functions (assignment and
subscript operators).
</UL>
<!--TOC section Acknowledgements-->
<H2><A NAME="htoc10">4</A>&nbsp;&nbsp;Acknowledgements</H2><!--SEC END -->
We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard
Smith whose findings have influenced the library.<BR>
<BR>
<!--TOC section References-->
<H2>References</H2><!--SEC END -->
<DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD>
Jaakko J&auml;rvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine.
Function overloading based on arbitrary properties of types.
<EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR>
<BR>
<DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD>
Jaakko J&auml;rvi, Jeremiah Willcock, and Andrew Lumsdaine.
Concept-controlled polymorphism.
In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative
Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages
228--244. Springer Verlag, September 2003.<BR>
<BR>
<DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD>
David Vandevoorde and Nicolai&nbsp;M. Josuttis.
<EM>C++ Templates: The Complete Guide</EM>.
Addison-Wesley, 2002.</DL>
<hr></hr>
<B>Contributed by:</B> <BR>
Jaakko J&auml;rvi, Jeremiah Willcock and Andrew Lumsdaine<BR>
<EM>{jajarvi|jewillco|lums}@osl.iu.edu</EM><BR>
Indiana University<BR>
Open Systems Lab
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2>
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
</EM></BLOCKQUOTE>
</BODY>
</HTML>

View File

@@ -1,302 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<!-- TODO:
- lambda interaction
-->
<title>Boost.Utility - lexicographic documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff">
<h1>
<img border="0" src="../../../c++boost.gif" align="center" alt="c++ boost">
Utility - Lexicographic
</h1>
<p>
The class <code>boost::lexicographic</code> provides an easy way
to avoid complex and errorprone if-else cascades to do lexicographic
comparisions on certain different criteria. The class is in the header
<a href="../../../boost/utility/lexicographic.hpp"
>boost/utility/lexicographic.hpp</a> and depends on no others headers.
The test code is in
<a href="../../../libs/utility/test/lexicographic_test.cpp"
>lexicographic_test.cpp</a>.
</p>
<h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#examples">Examples</a></li>
<li><a href="#synopsis">Synopsis</a></li>
<li><a href="#members">Members</a></li>
<li><a href="#free_functions">Free Functions</a></li>
<li><a href="#credits">Credits</a></li>
</ul>
<h2><a name="introduction">Introduction</a></h2>
<p>
Often one has to write comparisions which give an ordering between
various kinds of data. When they look in a certain
specified order at one relation between two data items at a time and
result in a lexicographic comparision of all these relations the
programmer often has to write long if-else cascades. These cascades
are often complex and difficult to maintain. The class
<code>boost::lexicographic</code> helps in this scenario. Its constructor
and function call operator takes two data items which need to be
compared as arguments and performs to comparision. The order in which
the function call operators are called determine the lexicographic order
of the relations. Since the result of all further comparisions might not
be needed after a certain step, they are not executed.<br>
The logic of the class assumes an ascending order as implied by the
<code>operator &lt;</code>. If a descending order needs to be obtained
one can just switch the order of the arguments. Additionally, both the
constructor and the function call operator provide also a three argument
form which takes a functor for comparisions as a third argument.
</p>
<h3>Relation to <code>std::lexicographic_compare</code></h3>
<p>
The standard C++ algorithm <code>std::lexicographic_compare</code>
does essentially the same thing but in a different situation. It compares
sequences of data items of equal type. Whereas <code>boost::lexicographic</code>
compares individual data items of different type, and every comparison
must be specified explicitly by using the function call operator of the class.
</p>
<h3>Relation to if-else-cascades</h3>
<p>
<b>Advantages</b><br>
<ul>
<li>The order of comparisons can easily be changed.
<li>Single comparisons can be added or removed in one line.
<li>Comparisons can be split up to be computed partly in one
function and partly in another by using
<code>boost::lexicographic</code> as a functor.
<li>It documents the code in a better fashion and expresses
the users intention directly.
<li>If the comparison arguments do not need computation, there is in
theory no performance overhead.
</ul>
<b>Disadvantages</b><br>
<ul>
<li>There is no short-circuiting. All arguments will be
evaluated, also if
an earlier comparison step already gave the final result. As long as the
arguments are trivial there should be no performance overhead. The only
way to avoid evaluation of arguments is to place every comparison step
in an if-statement like:
<blockquote>
<pre>boost::lexicographic cmp (complex_computation (a), complex_computation (b));
if (cmp.result () == lexicographic::equivalent)
{
cmp (complex_computation (c), complex_computation (d));
if (cmp.result () == lexicographic::equivalent)
{
cmp (complex_computation (e), complex_computation (f));
}
}
// do something with cmp
</pre>
</blockquote>
But this construct eats up many of the advantages of using
<code>boost::lexicographic</code>.
<li>
The performance of using <code>boost::lexicographic</code>, besides
the lack of short-circuiting, is not negligible.
Tests with gcc 3.2.2 showed, that the algorithmic overhead
is about 40% in comparison to according to if-else-cascades.
Additionally gcc failed to inline everything properly, so that the
resulting performance overhead was about a factor two.
</ul>
</p>
<h2><a name="examples">Examples</a></h2>
<p>
An example usage are special sorting operators, such as the lexicographic
ordering of tuples:
<blockquote>
<pre>struct position
{
double x, y, z;
};
bool operator &lt; (position const &amp;p1, position const &amp;p2)
{
return boost::lexicographic (p1.x, p2.x)
(p1.y, p2.y)
(p1.z, p2.z);
}</pre>
</blockquote>
An alternative form of writing this without <code>boost::lexicographic</code>
would be this:
<blockquote>
<pre>bool operator &lt; (position const &amp;p1, position const &amp;p2)
{
if (p1.x == p2.x)
if (p1.y == p2.y)
return p1.z &lt; p2.z;
else
return p1.y &lt; p2.y;
else
return p1.x &lt; p2.x;
}</pre>
</blockquote>
It is also easy to use different functor such as a case insensitive
comparision function object in the next example.
<blockquote>
<pre>struct person
{
std::string firstname, lastname;
};
bool operator &lt; (person const &amp;p1, person const &amp;p2)
{
return boost::lexicographic
(p1.lastname, p2.lastname, cmp_case_insensitive)
(p1.firstname, p2.firstname, cmp_case_insensitive);
}</pre>
</blockquote>
</p>
<h2><a name="synopsis">Synopsis</a></h2>
<blockquote>
<pre>namespace boost
{
class lexicographic
{
public:
enum result_type { minus = -1, equivalent, plus };
template &lt;typename T1, typename T2&gt;
lexicographic (T1 const &amp;a, T2 const &b);
template &lt;typename T1, typename T2, typename Cmp&gt;
lexicographic (T1 const &amp;a, T2 const &b, Cmp cmp);
template &lt;typename T1, typename T2&gt;
lexicographic &amp;operator () (T1 const &a, T2 const &b);
template &lt;typename T1, typename T2, typename Cmp&gt;
lexicographic &amp;operator () (T1 const &a, T2 const &b, Cmp cmp);
result_type result () const;
operator <i>unspecified_bool_type</i> () const;
};
bool operator == (lexicographic l1, lexicographic l2);
bool operator != (lexicographic l1, lexicographic l2);
}</pre>
</blockquote>
<h2><a name="members">Members</a></h2>
<h3>result_type</h3>
<code>enum result_type { minus = -1, equivalent = 0, plus = +1 };</code>
<blockquote><p>
Defines the result type of the class. It is kept as internal state
and is returned by <code>result ()</code>.
The integer representation of it is equivalent to the one
returned by <code>std::strcmp</code>.
<ul>
<li><code>minus</code> - the sequence of the first arguments
of constructor and function call operators
is lexicographically less than the according
sequence of the second arguments.
<li><code>equivalent</code> - all elements of the sequences
of the first and the second arguments are identical.
<li><code>plus</code> - the sequence of the first arguments
of constructor and function call operators
is lexicographically greater than the according
sequence of the second arguments.
</ul>
</p></blockquote>
<h3>constructors</h3>
<code>template &lt;typename T1, typename T2&gt;<br>
lexicographic (T1 const &amp;a, T2 const &b);</code>
<blockquote><p>
Constructs new object and does the first comparision
step between <code>a</code> and <code>b</code>. It uses
<code>operator &lt;</code> for comparisions.
</p></blockquote>
<code>template &lt;typename T1, typename T2, typename Cmp&gt;<br>
lexicographic (T1 const &amp;a, T2 const &b, Cmp cmp);</code>
<blockquote><p>
Constructs new object and does the first comparision
step between <code>a</code> and <code>b</code>. It uses
<code>cmp</code> for comparisions.
</p></blockquote>
<h3>function call operators</h3>
<code>template &lt;typename T1, typename T2&gt;<br>
lexicographic &amp;operator () (T1 const &a, T2 const &b);</code>
<blockquote><p>
Does next comparision step on object between <code>a</code>
and <code>b</code>. It uses <code>operator &lt;</code> for
comparisions.
</p></blockquote>
<code>template &lt;typename T1, typename T2, typename Cmp&gt;<br>
lexicographic &amp;operator () (T1 const &a, T2 const &b, Cmp cmp);</code>
<blockquote><p>
Does next comparision step on object between <code>a</code>
and <code>b</code>. It uses <code>cmp</code> for
comparisions.
</p></blockquote>
<h3>result</h3>
<code>result_type result () const;</code>
<blockquote><p>
Gives result of already done comparision steps.
</p></blockquote>
<h3>conversions</h3>
<code>operator <i>unspecified_bool_type</i> () const;</code>
<blockquote><p>
This conversion operator allows objects to be used in boolean
contexts, like <code>if (lexicographic (a, b)) {}</code>. The
actual target type is typically a pointer to a member function,
avoiding many of the implicit conversion pitfalls.<br>
It evaluates to <code>true</code> if <code>result () == minus</code>,
otherwise to <code>false</code>.
</p></blockquote>
<h2><a name="free_functions">Free Functions</a></h2>
<h3>comparision</h3>
<code>bool operator == (lexicographic l1, lexicographic l2);</code>
<blockquote><p>
Returns <code>l1.result () == l2.result ()</code>.
That means it returns <code>true</code> if both
objects are in the same state.
</p></blockquote>
<code>bool operator != (lexicographic l1, lexicographic l2);</code>
<blockquote><p>
Returns <code>l1.result () != l2.result ()</code>.
That means it returns <code>true</code> if the two
objects are in the a different state.
</p></blockquote>
<h2><a name="credits">Credits</a></h2>
<p>
The author of <code>boost::lexicographic</code> is Jan Langer (jan@langernetz.de).
Ideas and suggestions from Steve Cleary, David Abrahams, Gennaro Proata, Paul Bristow, Daniel Frey, Daryle Walker and Brian McNamara were used.
</p>
<hr>
<p>
October 5, 2003<br>
<br>
<09> Copyright Jan Langer 2003<br>
Use, modification, and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file
<a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

View File

@@ -1,444 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!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 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" />
</head>
<body>
<div class="document" id="the-boost-namedparams-library-logo">
<h1 class="title">The Boost.NamedParams Library <a class="reference" href="../../../index.htm"><img alt="Boost" class="boost-logo" src="../../../c++boost.gif" /></a></h1>
<hr />
<table class="field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Authors:</th><td class="field-body">David Abrahams, Daniel Wallin</td>
</tr>
<tr class="field"><th class="field-name">Contact:</th><td class="field-body"><a class="reference" href="mailto:dave&#64;boost-consulting.com">dave&#64;boost-consulting.com</a>, <a class="reference" href="mailto:dalwan01&#64;student.umu.se">dalwan01&#64;student.umu.se</a></td>
</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>
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams, Daniel Wallin 2003.</td>
</tr>
<tr class="field"><th class="field-name">license:</th><td class="field-body">Use, modification and distribution is subject to the
Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at
<a class="reference" href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</td>
</tr>
</tbody>
</table>
<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>
</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>
</ul>
</div>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id7" name="introduction">1   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
grows, so does the inconvenience of passing arguments in the
correct order, especially in the presence of default values:</p>
<blockquote>
<ul>
<li><p class="first">It can become difficult for readers to understand the meaning of
arguments at the call site:</p>
<pre class="literal-block">
window* w = new_window(&quot;alert&quot;, true, true, false, 77, 65);
</pre>
</li>
<li><p class="first">Since meaning is given by position, we have to choose some
(often arbitrary) order for parameters with default values,
making some combinations of defaults unusable:</p>
<pre class="literal-block">
window* new_window(
char const* name, bool border = true
, bool opaque = true, bool movable = false
, int width = 100, int height = 100);
const bool movability = true;
window* w = new_window(&quot;alert2&quot;, movability); // error!
</pre>
</li>
<li><p class="first">Default values can not depend on the values of other function
parameters:</p>
<pre class="literal-block">
window* new_window(
char const* name, bool border, ...
, int width = 100, int heigh = width); // error!
</pre>
</li>
<li><p class="first">Template types can not be deduced from the default values, so
we have to resort to overloading to provide default values for
parameters with template type:</p>
<pre class="literal-block">
template&lt;class T&gt; void f(T x = 0);
f(); // error!
</pre>
</li>
</ul>
</blockquote>
<p>This library is an attempt to address the problems outlined above
by associating each parameter with a keyword identifier. Using
this library, users can identify parameters by name instead of just
argument position:</p>
<pre class="literal-block">
window* w = new_window(&quot;alert2&quot;, movable = movability); // OK!
</pre>
<!-- DWA Daniel, we explicitly *don't* need ref() for the case
described below. It's only when we want to pass by reference
without a keyword that we need it.
You also can't start talking about forwarding functions without
introducing them first!
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>
<!-- 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>
<pre class="literal-block">
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>
<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">
#include &lt;boost/named_params.hpp&gt;
struct name_t; // tag types
struct value_t;
namespace {
boost::keyword&lt;name_t&gt; name; // keyword objects
boost::keyword&lt;value_t&gt; value;
}
</pre>
<p>Placing these keyword objects in an unnamed namespace will prevent
link errors when you declare keywords in header files [<strong>Note</strong>:
the tag types should generally <em>not</em> be declared in an unnamed
namespace]. We also need to create a keywords list for our
function. These keywords should be declared in the same order as
their corresponding parameters appear in the function's parameter
list:</p>
<pre class="literal-block">
struct foo_keywords
: boost::keywords&lt;
name_t
, value_t
&gt;
{};
</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>
<pre class="literal-block">
template&lt;class Params&gt;
void foo_impl(const Params&amp;);
void foo()
{
foo_impl(foo_keywords());
}
template&lt;class A0&gt;
void foo(const A0&amp; 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));
}
</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>
<pre class="literal-block">
template&lt;class Params&gt;
void foo_impl(const Params&amp; params)
{
std::cout &lt;&lt; params[name] &lt;&lt; &quot; = &quot; &lt;&lt; params[value] &lt;&lt; &quot;\n&quot;;
}
</pre>
<p>That's it. The user calls the <tt class="literal"><span class="pre">foo()</span></tt> forwarding functions, with
either positional or named parameters. For instance:</p>
<pre class="literal-block">
foo(&quot;bar&quot;, 3.14f);
foo(value = 6.28f, &quot;baz&quot;)
</pre>
<p>Should print:</p>
<pre class="literal-block">
bar = 3.14
baz = 6.28
</pre>
<p>But we still don't have any default values, leaving any of the
parameters out results in a compilation error:</p>
<pre class="literal-block">
foo()
foo(&quot;bar&quot;)
foo(value = 3)
</pre>
<p>All fails.</p>
<p>Fortunatly, adding default values to parameters is easy:</p>
<pre class="literal-block">
template&lt;class Params&gt;
void foo_impl(const Params&amp; params)
{
std::cout
&lt;&lt; params[name | &quot;unnamed&quot;] &lt;&lt; &quot; = &quot;
&lt;&lt; params[value | 0] &lt;&lt; &quot;\n&quot;;
}
</pre>
<p>We are using <tt class="literal"><span class="pre">operator|</span></tt> to denote the default value of a named
parameter.</p>
<p>Going back a little to the <tt class="literal"><span class="pre">foo()</span></tt> call that didn't compile:</p>
<pre class="literal-block">
foo()
foo(&quot;bar&quot;)
foo(value = 3)
</pre>
<p>Now compiles, and prints:</p>
<pre class="literal-block">
unnamed = 0
bar = 0
unnamed = 3
</pre>
</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>
<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>
reference <a class="footnote-reference" href="#forwarding" id="id2" name="id2"><sup>1</sup></a>. As a result, an argument which is bound
to a keyword with <tt class="literal"><span class="pre">operator=</span></tt> can be transparently passed by
non-const reference, but positional arguments are always passed by
<tt class="literal"><span class="pre">const</span></tt> reference unless we use the <a class="reference" href="../../bind/ref.hpp">Boost.Ref</a> library to
indicate otherwise:</p>
<pre class="literal-block">
#include &lt;boost/ref.hpp&gt;
float x;
foo(value = x); // held type is float&amp;
foo(x); // held type is float const&amp;, need help!
foo(boost::ref(x)); // held type is float&amp;
</pre>
<p>Instances of <tt class="literal"><span class="pre">boost::reference_wrapper&lt;&gt;</span></tt> generated by
<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>
<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
templates have been the subject of much discussion; especially in
the presence of <a class="reference" href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#225">unqualified calls</a>. Probably the safest thing
to do is to isolate the forwarding functions in a namespace
containing no types <a class="footnote-reference" href="#using" id="id3" name="id3"><sup>2</sup></a>, but often we'd <em>like</em> our functions
to play nicely with argument-dependent lookup and other function
overloads. In that case, it's neccessary to somehow remove the
functions from the overload set when the passed argument types
don't meet their needs.</p>
<p>This sort of overload control can be accomplished in C++ by taking
advantage of <a class="reference" href="http://www.semantics.org/once_weakly/w02_SFINAE.pdf">SFINAE</a> (Substitution Failure Is Not An Error). If
type substitution during the instantiation of a function template
results in an invalid type, no compilation error is emitted;
instead the overload is removed from the overload set. By producing
an invalid type in the function signature depending on the result
of some condition, whether or not an overload is considered during
overload resolution can be controlled. The technique is formalized
in the <tt class="literal"><span class="pre">enable_if</span></tt> utility.</p>
<p>The named parameters library provides built-in SFINAE support
through the following class template:</p>
<pre class="literal-block">
template&lt;
class KeywordTag
, class HasDefaultValue // mpl::true_ or mpl::false_
, class Predicate
&gt;
struct named_param;
</pre>
<p>The key parameter, <tt class="literal"><span class="pre">Predicate</span></tt> shall be a unary MPL lambda
expression or <a class="reference" href="../../mpl/doc/ref/Metafunction_Class.html">Metafunction Class</a> that, when applied to the
actual type the argument, indicates whether that argument type
meets the function's requirements for that parameter position.</p>
<p>For example, let's say we want to restrict our <tt class="literal"><span class="pre">foo()</span></tt> so that
the <tt class="literal"><span class="pre">name</span></tt> parameter must be convertible to <tt class="literal"><span class="pre">const</span> <span class="pre">char*</span></tt>.
We'll replace our use of the <tt class="literal"><span class="pre">name_t</span></tt> tag with a specialization
of <tt class="literal"><span class="pre">boost::named_param</span></tt>:</p>
<pre class="literal-block">
struct foo_keywords
: boost::keywords&lt;
<strong>boost::named_param&lt;
name_t
, mpl::false_
, is_convertible&lt;mpl::_, const char*&gt;
&gt;</strong>
, value_t
&gt;
{};
</pre>
<p>Now we can add an additional optional argument to each of our
<tt class="literal"><span class="pre">foo</span></tt> overloads</p>
<pre class="literal-block">
template&lt;class A0&gt;
void foo(
const A0&amp; a0
, <strong>foo_keywords::restrict&lt;A0&gt;::type x = foo_keywords()</strong>
)
{
foo_impl(x(a0));
}
template&lt;class A0, class A1&gt;
void foo(
const A0&amp; a0, const A1&amp; a1
, <strong>foo_keywords::restrict&lt;A0,A1&gt;::type x = foo_keywords()</strong>
)
{
foo_impl(x(a0, a1));
}
</pre>
<p>These additional parameters are not intended to be used directly
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>
<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
syntax:</p>
<pre class="literal-block">
params[keyword <strong>|| nullary_function</strong>];
</pre>
<p><tt class="literal"><span class="pre">nullary_function</span></tt> must be a function object that is callable
without arguments, and that indicates its return type via a nested
<tt class="literal"><span class="pre">result_type</span></tt>. Boost.Bind can be used to produce an appropriate
function object from a regular function pointer:</p>
<pre class="literal-block">
// expensive default computation function
float default_span(float x, float theta);
// implementation of bar()
template &lt;class Params&gt;
void bar_impl(Params const&amp; params)
{
// Extract arguments
float x_ = params[x];
float theta_ = params[theta | pi];
float span = params[span || boost::bind(default_span, x_, theta_)];
...
}
</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>
<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>
<pre class="literal-block">
BOOST_NAMED_PARAMS_FUN(
return_type, function_name
, min_arity, max_arity, keywords_type
);
</pre>
<p>To generate all the forwarding functions and the implementation
function for our example, we need only apply
<tt class="literal"><span class="pre">BOOST_NAMED_PARAMS_FUN</span></tt> this way:</p>
<pre class="literal-block">
BOOST_NAMED_PARAMS_FUN(void, foo, 0, 2, foo_keywords)
{
std::cout
&lt;&lt; p[name | &quot;unnamed&quot;] &lt;&lt; &quot; = &quot;
&lt;&lt; p[value | 0] &lt;&lt; &quot;\n&quot;;
}
</pre>
</div>
<div class="section" id="portability">
<h1><a class="toc-backref" href="#id16" name="portability">7   Portability</a></h1>
<p>Boost.NamedParams has been confirmed to work on the following compilers:</p>
<blockquote>
<ul class="simple">
<li>Microsoft VC6 sp5, VC7 <a class="footnote-reference" href="#norestrict" id="id5" name="id5"><sup>3</sup></a></li>
<li>Microsoft VC7.1</li>
<li>GCC3.3.1 (cygwin), GCC2.95.3 (cygwin), GCC3.2 (mingw)</li>
<li>Metrowerks Codewarrior Pro8 and Pro9 (Windows)</li>
<li>Intel C++ 5.0,6.0,7.1,8.0 (Windows)</li>
<li>Comeau 4.3.3</li>
</ul>
</blockquote>
<hr />
<table class="footnote" frame="void" id="forwarding" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2" name="forwarding">[1]</a></td><td><p>One could provide overloads for <tt class="literal"><span class="pre">const</span></tt> and
non-<tt class="literal"><span class="pre">const</span></tt> reference versions of each parameter, but that
would quickly become unmanageable. It's known as &quot;the
forwarding problem&quot; and has been described in detail in this
<a class="reference" href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">paper</a>. The combinatorial explosion is avoided for the
parameter of keywords' <tt class="literal"><span class="pre">operator=</span></tt> because they take only a
single argument.</p>
</td></tr>
</tbody>
</table>
<table class="footnote" frame="void" id="using" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3" name="using">[2]</a></td><td><p>You can always give the illusion that the function
lives in an outer namespace by applying a <em>using-declaration</em>:</p>
<pre class="literal-block">
namespace foo_overloads
{
// foo declarations here
void foo() { ... }
...
}
using foo_overloads::foo;
</pre>
</td></tr>
</tbody>
</table>
<table class="footnote" frame="void" id="norestrict" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id5" name="norestrict">[3]</a></td><td>Restrictions doesn't work on these compilers because
of lack of SFINAE support.</td></tr>
</tbody>
</table>
</div>
</div>
<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 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>
</html>

View File

@@ -1,427 +0,0 @@
++++++++++++++++++++++++++++++++++++++++++
The Boost.NamedParams Library |(logo)|__
++++++++++++++++++++++++++++++++++++++++++
.. |(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$
: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
.. _`Open Systems Lab`: http://www.osl.iu.edu
.. contents:: Outline
.. section-numbering::
Introduction
============
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
grows, so does the inconvenience of passing arguments in the
correct order, especially in the presence of default values:
* It can become difficult for readers to understand the meaning of
arguments at the call site::
window* w = new_window("alert", true, true, false, 77, 65);
* Since meaning is given by position, we have to choose some
(often arbitrary) order for parameters with default values,
making some combinations of defaults unusable::
window* new_window(
char const* name, bool border = true
, bool opaque = true, bool movable = false
, int width = 100, int height = 100);
const bool movability = true;
window* w = new_window("alert2", movability); // error!
* Default values can not depend on the values of other function
parameters::
window* new_window(
char const* name, bool border, ...
, int width = 100, int heigh = width); // error!
* Template types can not be deduced from the default values, so
we have to resort to overloading to provide default values for
parameters with template type::
template<class T> void f(T x = 0);
f(); // error!
This library is an attempt to address the problems outlined above
by associating each parameter with a keyword identifier. Using
this library, users can identify parameters by name instead of just
argument position::
window* w = new_window("alert2", movable = movability); // OK!
.. DWA Daniel, we explicitly *don't* need ref() for the case
described below. It's only when we want to pass by reference
without a keyword that we need it.
You also can't start talking about forwarding functions without
introducing them first!
The tutorial has to come before all the nasty details below.
I'm going to comment on that and leave the next stuff alone
Tutorial
========
.. DWA you need some set-up here describing the problem you're
going to solve.
This example shows how to wrap a function::
void foo(char const* name, float value);
to give both parameters names and default values.
Defining the keywords
---------------------
First we define the named parameter keywords. This is done by creating
"tag" types for each keyword, and declaring ``keyword<``\ *tag*\
``>`` objects::
#include <boost/named_params.hpp>
struct name_t; // tag types
struct value_t;
namespace {
boost::keyword<name_t> name; // keyword objects
boost::keyword<value_t> value;
}
Placing these keyword objects in an unnamed namespace will prevent
link errors when you declare keywords in header files [**Note**:
the tag types should generally *not* be declared in an unnamed
namespace]. We also need to create a keywords list for our
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<
name_t
, value_t
>
{};
Defining the forwarding functions
---------------------------------
::
template<class Params>
void foo_impl(const Params&);
void foo()
{
foo_impl(foo_keywords());
}
template<class A0>
void foo(const A0& a0)
{
foo_impl(foo_keywords(a0));
}
template<class A0, class A1>
void foo(const A0& a0, const A1& a1)
{
foo_impl(foo_keywords(a0, a1));
}
Defining the implementation function
------------------------------------
::
template<class Params>
void foo_impl(const Params& params)
{
std::cout << params[name] << " = " << params[value] << "\n";
}
That's it. The user calls the ``foo()`` forwarding functions, with
either positional or named parameters. For instance::
foo("bar", 3.14f);
foo(value = 6.28f, "baz")
Should print::
bar = 3.14
baz = 6.28
But we still don't have any default values, leaving any of the
parameters out results in a compilation error::
foo()
foo("bar")
foo(value = 3)
All fails.
Fortunatly, adding default values to parameters is easy::
template<class Params>
void foo_impl(const Params& params)
{
std::cout
<< params[name | "unnamed"] << " = "
<< params[value | 0] << "\n";
}
We are using ``operator|`` to denote the default value of a named
parameter.
Going back a little to the ``foo()`` call that didn't compile::
foo()
foo("bar")
foo(value = 3)
Now compiles, and prints::
unnamed = 0
bar = 0
unnamed = 3
Limitations of the Approach
===========================
Because the keywords' ``operator=`` returns a temporary, and
temporaries cannot be bound to non-``const`` reference parameters,
our forwarding functions need to take their arguments by ``const``
reference [#forwarding]_. As a result, an argument which is bound
to a keyword with ``operator=`` can be transparently passed by
non-const reference, but positional arguments are always passed by
``const`` reference unless we use the `Boost.Ref`_ library to
indicate otherwise::
#include <boost/ref.hpp>
float x;
foo(value = x); // held type is float&
foo(x); // held type is float const&, need help!
foo(boost::ref(x)); // held type is float&
.. _`Boost.Ref`: ../../bind/ref.hpp
Instances of ``boost::reference_wrapper<>`` generated by
``boost::ref`` will be unwrapped automatically by the library.
Controlling Overload Resolution
===============================
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
templates have been the subject of much discussion; especially in
the presence of `unqualified calls`__. Probably the safest thing
to do is to isolate the forwarding functions in a namespace
containing no types [#using]_, but often we'd *like* our functions
to play nicely with argument-dependent lookup and other function
overloads. In that case, it's neccessary to somehow remove the
functions from the overload set when the passed argument types
don't meet their needs.
__ http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#225
This sort of overload control can be accomplished in C++ by taking
advantage of SFINAE_ (Substitution Failure Is Not An Error). If
type substitution during the instantiation of a function template
results in an invalid type, no compilation error is emitted;
instead the overload is removed from the overload set. By producing
an invalid type in the function signature depending on the result
of some condition, whether or not an overload is considered during
overload resolution can be controlled. The technique is formalized
in the |enable_if| utility.
The named parameters library provides built-in SFINAE support
through the following class template::
template<
class KeywordTag
, class HasDefaultValue // mpl::true_ or mpl::false_
, class Predicate
>
struct named_param;
The key parameter, ``Predicate`` shall be a unary MPL lambda
expression or `Metafunction Class`_ that, when applied to the
actual type the argument, indicates whether that argument type
meets the function's requirements for that parameter position.
.. _`Metafunction Class`: ../../mpl/doc/ref/Metafunction_Class.html
.. _SFINAE: http://www.semantics.org/once_weakly/w02_SFINAE.pdf
.. |enable_if| replace:: ``enable_if``
.. _enable_if: ../enable_if.html
For example, let's say we want to restrict our ``foo()`` so that
the ``name`` parameter must be convertible to ``const char*``.
We'll replace our use of the ``name_t`` tag with a specialization
of ``boost::named_param``:
.. parsed-literal::
struct foo_keywords
: boost::keywords<
**boost::named_param<
name_t
, mpl::false\_
, is_convertible<mpl::\_, const char\*>
>**
, value_t
>
{};
Now we can add an additional optional argument to each of our
``foo`` overloads
.. parsed-literal::
template<class A0>
void foo(
const A0& a0
, **foo_keywords::restrict<A0>::type x = foo_keywords()**
)
{
foo_impl(x(a0));
}
template<class A0, class A1>
void foo(
const A0& a0, const A1& a1
, **foo_keywords::restrict<A0,A1>::type x = foo_keywords()**
)
{
foo_impl(x(a0, a1));
}
These additional parameters are not intended to be used directly
by callers; they merely trigger SFINAE by becoming illegal types
when the ``name`` argument is not convertible to ``const char*``.
Lazy Evaluation of Defaults
===========================
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
syntax:
.. parsed-literal::
params[keyword **|| nullary_function**];
``nullary_function`` must be a function object that is callable
without arguments, and that indicates its return type via a nested
``result_type``. Boost.Bind can be used to produce an appropriate
function object from a regular function pointer::
// expensive default computation function
float default_span(float x, float theta);
// implementation of bar()
template <class Params>
void bar_impl(Params const& params)
{
// Extract arguments
float x_ = params[x];
float theta_ = params[theta | pi];
float span = params[span || boost::bind(default_span, x_, theta_)];
...
}
Automatic Overload Generation
=============================
To reduce the work needed to write functions with named parameters,
we supply a macro that generates the boilerplate code.
Synopsis::
BOOST_NAMED_PARAMS_FUN(
return_type, function_name
, min_arity, max_arity, keywords_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)
{
std::cout
<< p[name | "unnamed"] << " = "
<< p[value | 0] << "\n";
}
Portability
===========
Boost.NamedParams has been confirmed to work on the following compilers:
- Microsoft VC6 sp5, VC7 [#norestrict]_
- Microsoft VC7.1
- GCC3.3.1 (cygwin), GCC2.95.3 (cygwin), GCC3.2 (mingw)
- Metrowerks Codewarrior Pro8 and Pro9 (Windows)
- Intel C++ 5.0,6.0,7.1,8.0 (Windows)
- Comeau 4.3.3
-----------------------------
.. [#forwarding] One could provide overloads for ``const`` and
non-``const`` reference versions of each parameter, but that
would quickly become unmanageable. It's known as "the
forwarding problem" and has been described in detail in this
paper__. The combinatorial explosion is avoided for the
parameter of keywords' ``operator=`` because they take only a
single argument.
__ http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm
.. [#using] You can always give the illusion that the function
lives in an outer namespace by applying a *using-declaration*::
namespace foo_overloads
{
// foo declarations here
void foo() { ... }
...
}
using foo_overloads::foo;
.. [#norestrict] Restrictions doesn't work on these compilers because
of lack of SFINAE support.

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

@@ -1,87 +0,0 @@
// Copyright 2003 <20> The Trustees of Indiana University.
// Boost Software License - Version 1.0 - August 17th, 2003
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef BOOST_UTILITY_ENABLE_IF_HPP
#define BOOST_UTILITY_ENABLE_IF_HPP
namespace boost
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace boost
#endif

View File

@@ -1,105 +0,0 @@
// Copyright (c) 2003 Jan Langer
// 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)
// See library home page at http://www.boost.org/libs/utility
#ifndef BOOST_UTILITY_LEXICOGRAPHIC_HPP
#define BOOST_UTILITY_LEXICOGRAPHIC_HPP
namespace boost
{
class lexicographic
{
public:
enum result_type { minus = -1, equivalent = 0, plus = +1 };
private:
typedef void (lexicographic::*unspecified_bool_type) ();
void safe_bool_conversion () {}
template <typename T1, typename T2>
result_type do_compare (T1 const &a, T2 const &b) const
{
if (a < b)
return minus;
else if (b < a)
return plus;
else
return equivalent;
}
template <typename T1, typename T2, typename Cmp>
result_type do_compare (T1 const &a, T2 const &b, Cmp cmp) const
{
if (cmp (a, b))
return minus;
else if (cmp (b, a))
return plus;
else
return equivalent;
}
public:
lexicographic () : m_value (equivalent) {}
template <typename T1, typename T2>
lexicographic (T1 const &a, T2 const &b)
: m_value (do_compare (a, b))
{}
template <typename T1, typename T2, typename Cmp>
lexicographic (T1 const &a, T2 const &b, Cmp cmp)
: m_value (do_compare (a, b, cmp))
{}
template <typename T1, typename T2>
lexicographic &operator () (T1 const &a, T2 const &b)
{
if (m_value == equivalent)
m_value = do_compare (a, b);
return *this;
}
template <typename T1, typename T2, typename Cmp>
lexicographic &operator () (T1 const &a, T2 const &b, Cmp cmp)
{
if (m_value == equivalent)
m_value = do_compare (a, b, cmp);
return *this;
}
result_type result () const
{
return m_value;
}
operator unspecified_bool_type () const
{
return (m_value == minus)
? &lexicographic::safe_bool_conversion
: 0;
}
// somehow only needed old compilers
bool operator ! () const
{
return m_value != minus;
}
private:
result_type m_value;
};
bool operator == (lexicographic l1, lexicographic l2)
{
return l1.result () == l2.result ();
}
bool operator != (lexicographic l1, lexicographic l2)
{
return l1.result () != l2.result ();
}
} // namespace boost
#endif // BOOST_UTILITY_LEXICOGRAPHIC_HPP

View File

@@ -1,175 +0,0 @@
// (C) Copyright Jonathan Turkanis 2004.
// 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.
//
// Intended as an alternative to type_traits::yes_type and type_traits::no_type.
// Provides an arbitrary number of types (case_<0>, case_<1>, ...) for
// determining the results of overload resultion using 'sizeof', plus a uniform
// means of using the result. yes_type and no_type are typedefs for case_<1>
// and case_<0>. A single case with negative argument, case_<-1>, is also
// provided, for convenience.
//
// This header may be included any number of times, with
// BOOST_SELECT_BY_SIZE_MAX_CASE defined to be the largest N such that case_<N>
// is needed for a particular application. It defaults to 2.
//
// This header depends only on Boost.Config and Boost.Preprocessor. Dependence
// on Type Traits or MPL was intentionally avoided, to leave open the
// possibility that select_by_size could be used by these libraries.
//
// Example usage:
//
// #define BOOST_SELECT_BY_SIZE_MAX_CASE 7 // Needed for > 2 cases.
// #include <boost/utility/select_by_size.hpp>
//
// using namespace boost::utility;
//
// case_<0> helper(bool); // could use 'case_<false>' or 'no_type'.
// case_<1> helper(int); // could use 'case_<true>' or' yes_type'.
// case_<2> helper(unsigned);
// case_<3> helper(long);
// case_<4> helper(unsigned long);
// case_<5> helper(float);
// case_<6> helper(double);
// case_<7> helper(const char*);
//
// struct test {
// static const int value =
// select_by_size< sizeof(helper(9876UL)) >::value;
// BOOST_STATIC_ASSERT(value == 4);
// };
//
// For compilers with integral constant expression problems, e.g. Borland 5.x,
// one can also write
//
// struct test {
// BOOST_SELECT_BY_SIZE(int, value, helper(9876UL));
// };
//
// to define a static integral constant 'value' equal to
//
// select_by_size< sizeof(helper(9876UL)) >::value.
//
// Include guards surround all contents of this header except for explicit
// specializations of select_by_size for case_<N> with N > 2.
#ifndef BOOST_UTILITY_SELECT_BY_SIZE_HPP_INCLUDED
#define BOOST_UTILITY_SELECT_BY_SIZE_HPP_INCLUDED
// The lowest N for which select_by_size< sizeof(case_<N>) > has not been
// specialized.
#define SELECT_BY_SIZE_MAX_SPECIALIZED 2
#include <boost/config.hpp> // BOOST_STATIC_CONSTANT.
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
/* Alternative implementation using max_align.
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
namespace boost { namespace utility {
template<int N>
struct case_ { char c[(N + 1) * alignment_of<detail::max_align>::value]; };
template<unsigned Size>
struct select_by_size {
BOOST_STATIC_CONSTANT(int, value =
(Size / alignment_of<detail::max_align>::value - 1));
};
} } // End namespaces utility, boost.
*/ // End alternate implementation.
namespace boost { namespace utility {
//--------------Definition of case_-------------------------------------------//
template<int N> struct case_ { char c1; case_<N - 1> c2; };
template<> struct case_<-1> { char c; };
typedef case_<true> yes_type;
typedef case_<false> no_type;
//--------------Declaration of select_by_size---------------------------------//
template<unsigned Size> struct select_by_size;
} } // End namespaces utility, boost.
//--------------Definition of SELECT_BY_SIZE_SPEC-----------------------------//
// Sepecializes select_by_size for sizeof(case<n-1>). The decrement is used
// here because the preprocessor library doesn't handle negative integers.
#define SELECT_BY_SIZE_SPEC(n) \
namespace boost { namespace utility { \
namespace detail { \
static const int BOOST_PP_CAT(sizeof_case_, n) = sizeof(case_<n - 1>); \
} \
template<> \
struct select_by_size< detail::BOOST_PP_CAT(sizeof_case_, n) > { \
struct type { BOOST_STATIC_CONSTANT(int, value = n - 1); }; \
BOOST_STATIC_CONSTANT(int, value = type::value); \
}; \
} } \
/**/
//--------------Default specializations of select_by_size---------------------//
SELECT_BY_SIZE_SPEC(0) // select_by_size< sizeof(case<-1>) >
SELECT_BY_SIZE_SPEC(1) // select_by_size< sizeof(case<0>) >
SELECT_BY_SIZE_SPEC(2) // select_by_size< sizeof(case<1>) >
//--------------Definition of SELECT_BY_SIZE----------------------------------//
#define BOOST_SELECT_BY_SIZE(type_, name, expr) \
BOOST_STATIC_CONSTANT( \
unsigned, \
BOOST_PP_CAT(boost_select_by_size_temp_, name) = sizeof(expr) \
); \
BOOST_STATIC_CONSTANT( \
type_, \
name = \
( boost::utility::select_by_size< \
BOOST_PP_CAT(boost_select_by_size_temp_, name) \
>::value ) \
) \
/**/
#endif // #ifndef BOOST_UTILITY_SELECT_BY_SIZE_HPP_INCLUDED
//----------Specializations of SELECT_BY_SIZE (outside main inclued guards)---//
// Specialize select_by_size for sizeof(case_<N>) for each N less than
// BOOST_SELECT_BY_SIZE_CASES for which this specialization has not already been
// performed.
#if !BOOST_PP_IS_ITERATING //-------------------------------------------------//
#include <boost/preprocessor/iteration/iterate.hpp>
#if !defined(BOOST_SELECT_BY_SIZE_MAX_CASE) || \
(BOOST_SELECT_BY_SIZE_MAX_CASE < 2)
#undef BOOST_SELECT_BY_SIZE_MAX_CASE
#define BOOST_SELECT_BY_SIZE_MAX_CASE 2
#endif
#if (BOOST_SELECT_BY_SIZE_MAX_CASE > SELECT_BY_SIZE_MAX_SPECIALIZED)
#define BOOST_PP_FILENAME_1 <boost/utility/select_by_size.hpp>
#define BOOST_PP_ITERATION_LIMITS ( SELECT_BY_SIZE_MAX_SPECIALIZED, \
BOOST_SELECT_BY_SIZE_MAX_CASE )
#include BOOST_PP_ITERATE()
#undef SELECT_BY_SIZE_MAX_SPECIALIZED
#define SELECT_BY_SIZE_MAX_SPECIALIZED BOOST_SELECT_BY_SIZE_MAX_CASE
#endif // #if (BOOST_SELECT_BY_SIZE_CASES > SELECT_BY_SIZE_MAX_SPECIALIZED)
#undef BOOST_SELECT_BY_SIZE_MAX_CASE
#else // #if !BOOST_PP_IS_ITERATING //----------------------------------------//
SELECT_BY_SIZE_SPEC(BOOST_PP_INC(BOOST_PP_ITERATION()))
#endif // #if !BOOST_PP_IS_ITERATING //---------------------------------------//

View File

@@ -1,476 +0,0 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
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)
==============================================================================*/
#ifndef BOOST_TYPE_DEDUCTION_IPP
#define BOOST_TYPE_DEDUCTION_IPP
/*=============================================================================
Return Type Deduction
[JDG Sept. 15, 2003]
Before C++ adopts the typeof, there is currently no way to deduce the
result type of an expression such as x + y. This deficiency is a major
problem with template metaprogramming; for example, when writing
forwarding functions that attempt to capture the essence of an
expression inside a function. Consider the std::plus<T>:
template <typename T>
struct plus : public binary_function<T, T, T>
{
T operator()(T const& x, T const& y) const
{
return x + y;
}
};
What's wrong with this? Well, this functor does not accurately capture
the behavior of the plus operator. 1) It does not handle the case where
x and y are of different types (e.g. x is short and y is int). 2) It
assumes that the arguments and return type are the same (i.e. when
adding a short and an int, the return type ought to be an int). Due to
these shortcomings, std::plus<T>(x, y) is a poor substitute for x + y.
The case where x is short and y is int does not really expose the
problem. We can simply use std::plus<int> and be happy that the
operands x and y will simply be converted to an int. The problem
becomes evident when an operand is a user defined type such as bigint.
Here, the conversion to bigint is simply not acceptable. Even if the
unnecessary conversion is tolerable, in generic code, it is not always
possible to choose the right T type that can accomodate both x and y
operands.
To truly model the plus operator, what we need is a polymorphic functor
that can take arbitrary x and y operands. Here's a rough schematic:
struct plus
{
template <typename X, typename Y>
unspecified-type
operator()(X const& x, Y const& y) const
{
return x + y;
}
};
Now, we can handle the case where X and Y are arbitrary types. We've
solved the first problem. To solve the second problem, we need some
form of return type deduction mechanism. If we had the typeof, it would
be something like:
template <typename X, typename Y>
typeof(X() + Y())
operator()(X const& x, Y const& y) const
{
return x + y;
}
Without the typeof facility, it is only possible to wrap an expression
such as x + y in a function or functor if we are given a hint that
tells us what the actual result type of such an expression is. Such a
hint can be in the form of a metaprogram, that, given the types of the
arguments, will return the result type. Example:
template <typename X, typename Y>
struct result_of_plus
{
typedef unspecified-type type;
};
Given a result_of_plus metaprogram, we can complete our polymorphic
plus functor:
struct plus
{
template <typename X, typename Y>
typename result_of_plus<X, Y>::type
operator()(X const& x, Y const& y) const
{
return x + y;
}
};
The process is not automatic. We have to specialize the metaprogram for
specific argument types. Examples:
template <>
struct result_of_plus<short, int>
{
typedef int type;
};
template <typename T>
struct result_of_plus<std::complex<T>, std::complex<T> >
{
typedef std::complex<T> type;
};
To make it easier for the user, specializations are provided for common
types such as primitive c++ types (e.g. int, char, double, etc.), and
standard types (e.g. std::complex, iostream, std containers and
iterators).
To further improve the ease of use, for user defined classes, we can
supply a few more basic specializations through metaprogramming using
heuristics based on canonical operator rules (Such heuristics can be
found in the LL and Phoenix, for example). For example, it is rather
common that the result of x += y is X& or the result of x || y is a
bool. The client is out of luck if her classes do not follow the
canonical rules. She'll then have to supply her own specialization.
The type deduction mechanism demostrated below approaches the problem
not through specialization and heuristics, but through a limited form
of typeof mechanism. The code does not use heuristics, hence, no
guessing games. The code takes advantage of the fact that, in general,
the result type of an expression is related to one its arguments' type.
For example, x + y, where x has type int and y has type double, has the
result type double (the second operand type). Another example, x[y]
where x is a vector<T> and y is a std::size_t, has the result type
vector<T>::reference (the vector<T>'s reference type type).
The limited form of type deduction presented can detect common
relations if the result of a binary or unary operation, given arguments
x and y with types X and Y (respectively), is X, Y, X&, Y&, X*, Y*, X
const*, Y const*, bool, int, unsigned, double, container and iterator
elements (e.g the T, where X is: T[N], T*, vector<T>, map<T>,
vector<T>::iterator). More arguments/return type relationships can be
established if needed.
A set of overloaded test(T) functions capture these argument related
types. Each test(T) function returns a distinct type that can be used
to determine the exact type of an expression.
Consider:
template <typename X, typename Y>
x_value_type
test(X const&);
template <typename X, typename Y>
y_value_type
test(Y const&);
Given an expression x + y, where x is int and y is double, the call to:
test<int, double>(x + y)
will return a y_value_type.
Now, if we rig x_value_type and y_value_type such that both have unique
sizes, we can use sizeof(test<X, Y>(x + y)) to determine if the result
type is either X or Y.
For example, if:
sizeof(test<X, Y>(x + y)) == sizeof(y_value_type)
then, we know for sure that the result of x + y has type Y.
The same basic scheme can be used to detect more argument-dependent
return types where the sizeof the test(T) return type is used to index
through a boost::mpl vector which holds each of the corresponding
result types.
==============================================================================*/
#include <boost/mpl/vector/vector20.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/cat.hpp>
namespace boost {
struct error_cant_deduce_type {};
namespace type_deduction_detail
{
typedef char(&bool_value_type)[1];
typedef char(&int_value_type)[2];
typedef char(&uint_value_type)[3];
typedef char(&double_value_type)[4];
typedef char(&bool_reference_type)[5];
typedef char(&int_reference_type)[6];
typedef char(&uint_reference_type)[7];
typedef char(&double_reference_type)[8];
typedef char(&x_value_type)[9];
typedef char(&x_reference_type)[10];
typedef char(&x_const_pointer_type)[11];
typedef char(&x_pointer_type)[12];
typedef char(&y_value_type)[13];
typedef char(&y_reference_type)[14];
typedef char(&y_const_pointer_type)[15];
typedef char(&y_pointer_type)[16];
typedef char(&container_reference_type)[17];
typedef char(&container_const_reference_type)[18];
typedef char(&container_mapped_type)[19];
typedef char(&cant_deduce_type)[20];
template <typename T, typename PlainT = typename remove_cv<T>::type>
struct is_basic
: mpl::or_<
is_same<PlainT, bool>
, is_same<PlainT, int>
, is_same<PlainT, unsigned>
, is_same<PlainT, double>
> {};
template <typename C>
struct reference_type
{
typedef typename C::reference type;
};
template <typename T, std::size_t N>
struct reference_type<T[N]>
{
typedef T& type;
};
template <typename T>
struct reference_type<T*>
{
typedef T& type;
};
template <typename C>
struct const_reference_type
{
typedef typename C::const_reference type;
};
template <typename C>
struct mapped_type
{
typedef typename C::mapped_type type;
};
struct asymmetric;
template <typename X, typename Y>
cant_deduce_type
test(...); // The black hole !!!
template <typename X, typename Y>
bool_value_type
test(bool const&);
template <typename X, typename Y>
int_value_type
test(int const&);
template <typename X, typename Y>
uint_value_type
test(unsigned const&);
template <typename X, typename Y>
double_value_type
test(double const&);
template <typename X, typename Y>
bool_reference_type
test(bool&);
template <typename X, typename Y>
int_reference_type
test(int&);
template <typename X, typename Y>
uint_reference_type
test(unsigned&);
template <typename X, typename Y>
double_reference_type
test(double&);
template <typename X, typename Y>
typename disable_if<
mpl::or_<is_basic<X>, is_const<X> >
, x_value_type
>::type
test(X const&);
template <typename X, typename Y>
typename disable_if<
is_basic<X>
, x_reference_type
>::type
test(X&);
template <typename X, typename Y>
typename disable_if<
mpl::or_<
is_basic<X>
, is_const<X>
>
, x_const_pointer_type
>::type
test(X const*);
template <typename X, typename Y>
x_pointer_type
test(X*);
template <typename X, typename Y>
typename disable_if<
mpl::or_<
is_basic<Y>
, is_same<Y, asymmetric>
, is_const<Y>
, is_same<X, Y>
>
, y_value_type
>::type
test(Y const&);
template <typename X, typename Y>
typename disable_if<
mpl::or_<
is_basic<Y>
, is_same<Y, asymmetric>
, is_same<X, Y>
>
, y_reference_type
>::type
test(Y&);
template <typename X, typename Y>
typename disable_if<
mpl::or_<
is_same<Y, asymmetric>
, is_const<Y>
, is_same<X, Y>
>
, y_const_pointer_type
>::type
test(Y const*);
template <typename X, typename Y>
typename disable_if<
mpl::or_<
is_same<Y, asymmetric>
, is_same<X, Y>
>
, y_pointer_type
>::type
test(Y*);
template <typename X, typename Y>
typename disable_if<
is_basic<typename X::value_type>
, container_reference_type
>::type
test(typename X::reference);
template <typename X, typename Y, typename Z>
typename enable_if<
mpl::and_<
mpl::or_<is_array<X>, is_pointer<X> >
, mpl::not_<is_basic<Z> >
>
, container_reference_type
>::type
test(Z&);
template <typename X, typename Y>
typename disable_if<
is_basic<typename X::value_type>
, container_const_reference_type
>::type
test(typename X::const_reference);
template <typename X, typename Y>
typename disable_if<
is_basic<typename X::mapped_type>
, container_mapped_type
>::type
test(typename X::mapped_type);
template <typename X, typename Y>
struct base_result_of
{
typedef typename remove_reference<X>::type x_type;
typedef typename remove_reference<Y>::type y_type;
typedef mpl::vector20<
mpl::identity<bool>
, mpl::identity<int>
, mpl::identity<unsigned>
, mpl::identity<double>
, mpl::identity<bool&>
, mpl::identity<int&>
, mpl::identity<unsigned&>
, mpl::identity<double&>
, mpl::identity<x_type>
, mpl::identity<x_type&>
, mpl::identity<x_type const*>
, mpl::identity<x_type*>
, mpl::identity<y_type>
, mpl::identity<y_type&>
, mpl::identity<y_type const*>
, mpl::identity<y_type*>
, reference_type<x_type>
, const_reference_type<x_type>
, mapped_type<x_type>
, mpl::identity<error_cant_deduce_type>
>
types;
};
}} // namespace boost::type_deduction_detail
#define BOOST_RESULT_OF_COMMON(expr, name, Y, SYMMETRY) \
struct name \
{ \
typedef type_deduction_detail::base_result_of<X, Y> base_type; \
static typename base_type::x_type x; \
static typename base_type::y_type y; \
\
BOOST_STATIC_CONSTANT(int, \
size = sizeof( \
type_deduction_detail::test< \
typename base_type::x_type \
, SYMMETRY \
>(expr) \
)); \
\
BOOST_STATIC_CONSTANT(int, index = (size / sizeof(char)) - 1); \
\
typedef typename mpl::at_c< \
typename base_type::types, index>::type id; \
typedef typename id::type type; \
};
#define BOOST_UNARY_RESULT_OF(expr, name) \
template <typename X> \
BOOST_RESULT_OF_COMMON(expr, name, \
type_deduction_detail::asymmetric, type_deduction_detail::asymmetric)
#define BOOST_BINARY_RESULT_OF(expr, name) \
template <typename X, typename Y> \
BOOST_RESULT_OF_COMMON(expr, name, Y, typename base_type::y_type)
#define BOOST_ASYMMETRIC_BINARY_RESULT_OF(expr, name) \
template <typename X, typename Y> \
BOOST_RESULT_OF_COMMON(expr, name, Y, type_deduction_detail::asymmetric)
#endif

View File

@@ -1,158 +0,0 @@
#include <boost/ref.hpp>
#include <functional>
#include <algorithm>
#include <vector>
#include <cassert>
class generate_zero {
public:
typedef int result_type;
generate_zero() {}
int operator()() const { return 0; }
private:
generate_zero(const generate_zero&);
};
class generate_zero_no_result_type {
public:
generate_zero_no_result_type() {}
int operator()() const { return 0; }
private:
generate_zero_no_result_type(const generate_zero_no_result_type&);
};
template<typename F>
void check_generate_zero(F f)
{
assert(f() == 0);
}
class negate_with_result_type
{
public:
typedef int result_type;
negate_with_result_type() {}
int operator()(int x) const { return -x; }
private:
negate_with_result_type(const negate_with_result_type&);
};
class negate_with_result_of
{
public:
template<typename T>
struct result_of
{
typedef int type;
};
negate_with_result_of() {}
int operator()(int x) const { return -x; }
private:
negate_with_result_of(const negate_with_result_of&);
};
template<typename F>
void check_negate(F f)
{
int x = 5;
assert(f(x) == -x);
}
class add_with_result_type
{
public:
typedef int result_type;
add_with_result_type() {}
int operator()(int x, int y) const { return x + y; }
private:
add_with_result_type(const add_with_result_type&);
};
class add_with_result_of
{
public:
template<typename F> struct result_of { typedef int type; };
add_with_result_of() {}
int operator()(int x, int y) const { return x + y; }
private:
add_with_result_of(const add_with_result_of&);
};
template<typename F>
void check_sum(F f)
{
int x = 3;
int y = 5;
assert(f(x, y) == x+y);
}
struct zero_negate_add_result_type
{
public:
typedef int result_type;
zero_negate_add_result_type() {}
int operator()() const { return 0; }
int operator()(int x) const { return -x; }
int operator()(int x, int y) const { return x+y; }
private:
zero_negate_add_result_type(const zero_negate_add_result_type&);
};
struct zero_negate_add_result_of
{
public:
template<typename F> struct result_of { typedef int type; };
zero_negate_add_result_of() {}
int operator()() const { return 0; }
int operator()(int x) const { return -x; }
int operator()(int x, int y) const { return x+y; }
private:
zero_negate_add_result_of(const zero_negate_add_result_of&);
};
int main()
{
// Arity zero function objects
generate_zero gz;
generate_zero_no_result_type gznrt;
check_generate_zero(boost::ref(gz));
boost::ref(gznrt);
// Arity 1 function objects
negate_with_result_type nrt;
negate_with_result_of nro;
check_negate(boost::ref(nrt));
check_negate(boost::ref(nro));
// Arity 2 function objects
add_with_result_type art;
add_with_result_of aro;
check_sum(boost::ref(art));
check_sum(boost::ref(aro));
// Arity overloading in function objects
zero_negate_add_result_type znart;
zero_negate_add_result_type znaro;
check_generate_zero(boost::ref(znart));
check_negate(boost::ref(znart));
check_sum(boost::ref(znart));
check_generate_zero(boost::ref(znaro));
check_negate(boost::ref(znaro));
check_sum(boost::ref(znaro));
return 0;
}

View File

@@ -1,35 +0,0 @@
#include <boost/result_of.hpp>
#include <utility>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
class int_result_type { typedef int result_type; };
class int_result_of
{
template<typename F> struct result { typedef int type; };
};
class int_result_type_and_float_result_of
{
typedef int result_type;
template<typename F> struct result { typedef float type; };
};
struct X {};
int main()
{
using namespace boost;
typedef int (*func_ptr)(float, double);
typedef int (X::*mem_func_ptr)(float);
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<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<mem_func_ptr(X,char)>::type, int>::value));
return 0;
}

View File

@@ -1,232 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<STYLE>
.code { font-family:monospace; font-size: 10pt }
H1, H2, H3 { font-family:Verdana, Tahoma, sans-serif; font-weight:0 }
H1 { font-size: 20pt }
H2 { font-size: 16pt }
P { color: black }
TH { text-align:left }
A { text-decoration:none }
A:visited { color: #005E20 }
A.contact { color: black; text-decoration:none }
.code { font-family:monospace; font-size: 10pt }
.headingCode { font-family:monospace; font-size: 12pt }
.concept { font-weight: bold }
</STYLE>
</HEAD>
<BODY>
<TABLE BORDER='0' WIDTH='100%'>
<TR>
<TD WIDTH="*" STYLE='text-align:left'><H1>Select-By-Size</H1></TD>
<TD ALIGN=right>
<TABLE>
<TR>
<TD STYLE='text-align:center'><A HREF='../../index.html'><IMG BORDER=0 SRC='../../kangaroo.gif'></A></TD>
</TR>
<TR>
<TD ALIGN='center'>
<A STYLE='text-align:center;color: black;font: bold italic 12pt/17pt Verdana, sans-serif; text-decoration:none' HREF='../../index.html'>Metaprogramming<BR>Utilities</A>
</TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
<H2>Contents</H2>
<DL STYLE='margin-left:1em'>
<DT>1. <A HREF='#overview'>Overview</A>
<DT>2. <A HREF='#example'>Example</A>
<DT>3. <A HREF='#description'>Description</A>
<DT>4. <A HREF='#synopsis'>Synopsis</A>
<DT>5. <A HREF='#rationale'>Rationale</A>
<DT>6. <A HREF='#implementation'>Implementation</A>
<DT>7. <A HREF='#dependencies'>Dependencies</A>
<DT>8. <A HREF='#portability'>Portability</A>
<DT>9. <A HREF='#feedback'>Feedback</A>
</DL>
<A NAME='overview'></A>
<H2>Overview</H2>
<P>
The header <A HREF='../../boost/utility/select_by_size.hpp'><SPAN CLASS='code'>&lt;boost/utility/select_by_size.hpp&gt;</SPAN></A> provides template classes and macros for determining the results of overload resolution at compile time using <SPAN CLASS='code'>sizeof</SPAN>. It is intended as an alternative to <A HREF='http://www.boost.org/boost/type_traits/detail/yes_no_type.hpp'><SPAN CLASS='code'>type_traits::yes_type</SPAN></A> and <A HREF='http://www.boost.org/boost/type_traits/detail/yes_no_type.hpp'><SPAN CLASS='code'>type_traits::no_type</SPAN></A> from the <A HREF='http://www.boost.org/libs/type_traits/index.html'>Type Traits</A> library. It provides an arbitrary number of types, <SPAN CLASS='code'>case_&lt;0&gt;</SPAN>, <SPAN CLASS='code'>case_&lt;1&gt;</SPAN>, <SPAN CLASS='code'>case_&lt;2&gt;</SPAN>, <SPAN CLASS='code'>... </SPAN>, for use as the return types of helper functions, plus a template <SPAN CLASS='code'>select_by_size</SPAN> which provides access to the result of the overload resolution. There is also a macro <SPAN CLASS='code'>BOOST_SELECT_BY_SIZE</SPAN>, similar to <A HREF='http://www.boost.org/libs/config/config.htm'><SPAN CLASS='code'>BOOST_STATIC_CONSTANT</SPAN></A>, for use with compilers which have trouble with integral constant expressions. (<I>See</I> <A HREF='http://www.boost.org/more/int_const_guidelines.htm'>Coding Guidelines for Integral Constant Expressions</A>.)
</P>
<P>
The <SPAN CLASS='code'>typedefs</SPAN> <SPAN CLASS='code'>yes_type</SPAN> and <SPAN CLASS='code'>no_type</SPAN> are provided as shorthands for <SPAN CLASS='code'>case_&lt;1&gt;</SPAN> and <SPAN CLASS='code'>case_&lt;0&gt;</SPAN>. In some cases, <SPAN CLASS='code'>case_&lt;true&gt;</SPAN> and <SPAN CLASS='code'>case_&lt;false&gt;</SPAN> may be more suggestive. There is also a single return type representing a negative value: <SPAN CLASS='code'>case_&lt;-1&gt;</SPAN>.
</P>
<P>All types decribes in this document reside in the namespace <SPAN CLASS='code'>boost::utility</SPAN>.
<A NAME='example'></A>
<H2>Example</H2>
<PRE> #include &lt;boost/static_assert.hpp&gt;
#define BOOST_SELECT_BY_SIZE_MAX_CASE 7
#include &lt;boost/utility/select_by_size.hpp&gt;
using namespace boost::utility;
case_&lt;0&gt; helper(bool);
case_&lt;1&gt; helper(int);
case_&lt;2&gt; helper(unsigned);
case_&lt;3&gt; helper(long);
case_&lt;4&gt; helper(unsigned long);
case_&lt;5&gt; helper(float);
case_&lt;6&gt; helper(double);
case_&lt;7&gt; helper(const char*);
struct test {
static const int value =
select_by_size&lt; sizeof(helper("hello")) &gt;::value;
BOOST_STATIC_ASSERT(value == 7);
};
struct test2 {
BOOST_SELECT_BY_SIZE(int, value, helper("hello"));
BOOST_STATIC_ASSERT(value == 7);
};</PRE>
<A NAME='description'></A>
<H2>Description</H2>
<H3>The template <SPAN CLASS='headingCode'>case_</SPAN></H3>
<P>
The defining property of the class template <SPAN CLASS='code'>case_</SPAN> is that the sizes of the types
<PRE> case_&lt;-1&gt;, case_&lt;0&gt;, case_&lt;1&gt;, case_&lt;2&gt;, case_&lt;3&gt;, ...</PRE>
form a strictly increasing sequence. With well-behaved implementations, <SPAN CLASS='code'>sizeof(case_&lt;-1&gt;)</SPAN> will be small, as will be the difference in size between adjacent types in the sequence.
</P>
<H3>The template <SPAN CLASS='headingCode'>select_by_size</SPAN></H3>
<P>
The defining property of the class template <SPAN CLASS='code'>select_by_size</SPAN> is that for each integer <SPAN CLASS='code'>N</SPAN> in the range <SPAN CLASS='code'>select_by_size</SPAN> through <SPAN CLASS='code'>BOOST_SELECT_BY_SIZE_MAX_CASE</SPAN>, we have the equality
<PRE> select_by_size< sizeof(case_&lt;N&gt;) >::value == N</PRE>
</P>
<H3>The macro <SPAN CLASS='headingCode'>BOOST_SELECT_BY_SIZE</SPAN></H3>
<P>
The macro <SPAN CLASS='code'>BOOST_SELECT_BY_SIZE(type, name, expr)</SPAN> can be used similarly to <SPAN CLASS='code'>BOOST_STATIC_CONSTANT</SPAN> to define a <SPAN CLASS='code'>static const</SPAN> intergral class member <SPAN CLASS='code'>name</SPAN> of type <SPAN CLASS='code'>type</SPAN> with value equal to <SPAN CLASS='code'>select_by_size< sizeof(expr) >::value</SPAN>.
</P>
<H3>The macro <SPAN CLASS='headingCode'>BOOST_SELECT_BY_SIZE_MAX_CASE</SPAN></H3>
<P>
In order to make use of <SPAN CLASS='code'>select_by_size</SPAN> with specializations <SPAN CLASS='code'>case_&lt;N&gt;</SPAN> for <SPAN CLASS='code'>N</SPAN> other than <SPAN CLASS='code'>-1</SPAN>, <SPAN CLASS='code'>0</SPAN> and <SPAN CLASS='code'>1</SPAN>,
the symbol <SPAN CLASS='code'>BOOST_SELECT_BY_SIZE_MAX_CASE</SPAN> must be defined as an intergral value greater than or equal to <SPAN CLASS='code'>N</SPAN> before including the header <SPAN CLASS='code'>&lt;boost/utility/select_by_size.hpp&gt;</SPAN>. The header may be included multiple times with different values of <SPAN CLASS='code'>BOOST_SELECT_BY_SIZE_MAX_CASE</SPAN>.
</P>
<P>
It is possible to implement <SPAN CLASS='code'>select_by_size</SPAN> in such a way that this macro is not necessary. <I>See</I> <A HREF='#implementation'>Implementation</A>, below, for a discussion.
</P>
<A NAME='Synopsis'></A>
<H2>Synopsis</H2>
<PRE> namespace boost {
namespace utility {
template&lt;int N&gt; struct <B>case_</B> { [<I>unspecified</I>] };
template&lt;unsigned N&gt;
struct <B>select_by_size</B> {
struct type {
static const unsigned value =
[M <I>such that</I> sizeof(case_&lt;M&gt;) == N];
};
static const unsigned value = type::value;
};
#define <B>BOOST_SELECT_BY_SIZE</B>(type, name, expr) [<I>unspecified</I>]
}
}</PRE>
<A NAME='rationale'></A>
<H2>Rationale</H2>
The utility of <SPAN CLASS='code'>type_traits::yes_type</SPAN> and <SPAN CLASS='code'>type_traits::no_type</SPAN> is well-known. The advantages of using <SPAN CLASS='code'>select_by_size</SPAN> are:
<UL type='box'>
<LI STYLE='list-style-type: square'>It documents the fact that <SPAN CLASS='code'>sizeof</SPAN> is being used to determine the result of overload resolution.
<LI STYLE='list-style-type: square'>It eliminates the need to compare a given <SPAN CLASS='code'>sizeof</SPAN> expression with <SPAN CLASS='code'>sizeof(type_traits::yes_type)</SPAN>.
<LI STYLE='list-style-type: square'>It allows the use of an aribtrary number of cases.</LI>
</UL>
<P>
Until recently the author knew of only one use for <SPAN CLASS='code'>select_by_size</SPAN> with more than two cases, and so regarded it as a <I>trick</I>. He then discovered a second use, elevating it to a <I>method</I>. With the discovery of a third use, it is now a <I>programming paradigm</I>. (The three known uses are determing template arity, as in <A HREF='http://www.boost.org/boost/mpl/aux_/template_arity.hpp'><SPAN CLASS='code'>&lt;boost/mpl/aux_/template_arity.hpp&gt;</SPAN></A>, <A HREF='http://www.boost.org/people/joel_de_guzman.htm'>Joel de Guzman</A>'s type deduction system in the <A HREF='http://www.boost.org/more/mailing_lists.htm#sandbox'>Boost Sandbox</A> at <SPAN CLASS='code'>&lt;boost/utility/type_deduction.hpp&gt;</SPAN>, and Reece Dunn's type deduction system for his Output Formatters library, also in the <A HREF='http://www.boost.org/more/mailing_lists.htm#sandbox'>Boost Sandbox</A>, at <SPAN CLASS='code'>&lt;boost/outfmt/detail/type_traits.hpp&gt;</SPAN>. There are surely many more.)
</P>
<A NAME='implementation'></A>
<H2>Implementation</H2>
<P>
<SPAN CLASS='code'>select_by_size</SPAN> is implemented by explicit specialization for the values
<PRE> sizeof(case_&lt;-1&gt;), sizeof(case_&lt;0&gt;), sizeof(case_&lt;1&gt;), sizeof(case_&lt;2&gt;), ... .</PRE>
As a result, there is a limit to the number of cases which can be used by default.
</P>
<P>
There are several ways to remove this restriction. For instance:
<UL>
<LI STYLE='list-style-type: square'><SPAN CLASS='code'>select_by_size</SPAN> could be implemented to
iterate through the sequence <SPAN CLASS='code'>case_&lt;-1&gt;, case_&lt;0&gt;, case_&lt;1&gt;, ... </SPAN> until it finds
a specialization whose size is equal to its template argument, or
<LI STYLE='list-style-type: square'>The template <SPAN CLASS='code'>case_</SPAN> could be designed so
that its size is easy to compute, taking alignment issues into account.
</UL>
This first approach is computationally too expensive for a widely used utility. The second approach is feasable; a sample implementation using <A HREF='http://www.boost.org/boost/type_traits/alignment_of.hpp'><SPAN CLASS='code'>alignment_of</SPAN></A> and <A HREF='http://www.boost.org/boost/type_traits/type_with_alignment.hpp'><SPAN CLASS='code'>max_align</SPAN></A> from the <A HREF='http://www.boost.org/libs/config/config.htm'>Type Traits</A> library is given in the <A HREF='../../boost/utility/select_by_size.hpp'>source code</A>.
</P>
<P>
The present implementation was chosen to
reduce dependencies on other libraries. If defining the macro <SPAN CLASS='code'>BOOST_SELECT_BY_SIZE_MAX_CASE</SPAN> is considered too inconvenient, the default number of cases could be set to <SPAN CLASS='code'>10</SPAN> or <SPAN CLASS='code'>20</SPAN> with little noticeable overhead.
</P>
<A NAME='dependencies'></A>
<H2>Dependencies</H2>
The header <A HREF='../../boost/utility/select_by_size.hpp'><SPAN CLASS='code'>&lt;boost/utility/select_by_size.hpp&gt;</SPAN></A> depends on <A HREF='http://www.boost.org/libs/config/config.htm'>Boost.Config</A> and the <A HREF='http://www.boost.org/libs/preprocessor/doc/index.html'>Boost Preprocessor Library</A>.
<A NAME='portability'></A>
<H2>Portability</H2>
<P>
The program <A HREF='select_by_size_test.cpp'><SPAN CLASS='code'>&lt;libs/utility/select_by_size_test.cpp&gt;</SPAN></A> has been tested successfully with the following compilers:
<UL>
<LI STYLE='list-style-type: square'>Microsoft Visual C++ 6.0, SP 5</LI>
<LI STYLE='list-style-type: square'>Microsoft Visual C++ 7.1</LI>
<LI STYLE='list-style-type: square'>Metrowerks CodeWarrior 8.0</LI>
<LI STYLE='list-style-type: square'>Intel C++ Compiler for Windows 7.1 and 8.0</LI>
<LI STYLE='list-style-type: square'>GCC 2.95.3-10 (cygwin special)</LI>
<LI STYLE='list-style-type: square'>GCC 3.2 (MinGW)</LI>
<LI STYLE='list-style-type: square'>GCC 3.3.1 (cygming special)</LI>
<LI STYLE='list-style-type: square'>Comeau C/C++ 4.3.3</LI>
<LI STYLE='list-style-type: square'>Borland C++ 5.5.1 and 5.6.4</LI>
<LI STYLE='list-style-type: square'>DigitalMars 8.38n</LI>
</UL>
It should work on any recent compiler for which Boost has been configured.
</P>
<A NAME='feedback'></A>
<H2>Feedback</H2>
The author, Jonathan Turkanis, can be contacted at <A CLASS='contact' HREF='mailto:turkanis@kangaroologic.com'>turkanis@kangaroologic.com</A>
<HR STYLE='margin:20,0,0'>
<P STYLE='font-size:8pt'>
&copy; Copyright Jonathan Turkanis 2004.
Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This
document is provided "as is" without express or implied warranty, and
with no claim as to its suitability for any purpose.
</P>
</BODY>

View File

@@ -1,60 +0,0 @@
// (C) Copyright Jonathan Turkanis 2004.
// 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.
// Test program for <boost/utility/select_by_size.hpp>
#include <boost/static_assert.hpp>
#include <boost/config.hpp>
// Include "select_by_size.hpp" with BOOST_SELECT_BY_SIZE_MAX_CASE undefined.
#include <boost/utility/select_by_size.hpp>
using boost::utility::case_;
case_<false> helper(bool);
case_<true> helper(int);
struct test1 {
// Define static bool constants v0 and v1.
BOOST_SELECT_BY_SIZE(bool, v0, helper(true));
BOOST_SELECT_BY_SIZE(bool, v1, helper(0));
BOOST_STATIC_ASSERT(v0 == false);
BOOST_STATIC_ASSERT(v1 == true);
};
// Include "select_by_size.hpp" a second time, defining more cases.
#define BOOST_SELECT_BY_SIZE_MAX_CASE 7
#include <boost/utility/select_by_size.hpp>
case_<2> helper(unsigned);
case_<3> helper(long);
case_<4> helper(unsigned long);
case_<5> helper(float);
case_<6> helper(double);
case_<7> helper(const char*);
struct test2 {
// Define static int constants v0 through v7.
BOOST_SELECT_BY_SIZE(int, v0, helper(true));
BOOST_SELECT_BY_SIZE(int, v1, helper(0));
BOOST_SELECT_BY_SIZE(int, v2, helper(0U));
BOOST_SELECT_BY_SIZE(int, v3, helper(0L));
BOOST_SELECT_BY_SIZE(int, v4, helper(0UL));
BOOST_SELECT_BY_SIZE(int, v5, helper(0.0F));
BOOST_SELECT_BY_SIZE(int, v6, helper(0.0));
BOOST_SELECT_BY_SIZE(int, v7, helper("hello"));
BOOST_STATIC_ASSERT(v0 == 0);
BOOST_STATIC_ASSERT(v1 == 1);
BOOST_STATIC_ASSERT(v2 == 2);
BOOST_STATIC_ASSERT(v3 == 3);
BOOST_STATIC_ASSERT(v4 == 4);
BOOST_STATIC_ASSERT(v5 == 5);
BOOST_STATIC_ASSERT(v6 == 6);
BOOST_STATIC_ASSERT(v7 == 7);
};
int main() { return 0; }

View File

@@ -1,23 +0,0 @@
# Boost Utility Library test Jamfile
subproject libs/utility/test ;
# bring in rules for testing
import testing ;
{
test-suite "utility"
: [ run lexicographic_test.cpp ]
[ run lex_performance_test.cpp ]
[ 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 ]
;
}

View File

@@ -1,23 +0,0 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -1,60 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
struct container {
bool my_value;
template <class T>
container(const T&, const typename enable_if<is_arithmetic<T>, T>::type * = 0):
my_value(true) {}
template <class T>
container(const T&, const typename disable_if<is_arithmetic<T>, T>::type * = 0):
my_value(false) {}
};
// example from Howard Hinnant (tests enable_if template members of a templated class)
template <class charT>
struct xstring
{
template <class It>
xstring(It begin, It end, typename
disable_if<is_arithmetic<It> >::type* = 0)
: data(end-begin) {}
int data;
};
int test_main(int, char*[])
{
BOOST_CHECK(container(1).my_value);
BOOST_CHECK(container(1.0).my_value);
BOOST_CHECK(!container("1").my_value);
BOOST_CHECK(!container(static_cast<void*>(0)).my_value);
char sa[] = "123456";
BOOST_CHECK(xstring<char>(sa, sa+6).data == 6);
return 0;
}

View File

@@ -1,44 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
template <int N> struct dummy {
dummy(int) {};
};
template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t, dummy<0> = 0) { return true; }
template<class T>
typename disable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t, dummy<1> = 0) { return false; }
int test_main(int, char*[])
{
BOOST_CHECK(arithmetic_object(1));
BOOST_CHECK(arithmetic_object(1.0));
BOOST_CHECK(!arithmetic_object("1"));
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@@ -1,80 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
using boost::enable_if_c;
using boost::lazy_enable_if_c;
// This class provides a reduced example of a traits class for
// computing the result of multiplying two types. The member typedef
// 'type' in this traits class defines the return type of this
// operator. The return type member is invalid unless both arguments
// for mult_traits are values that mult_traits expects (ints in this
// case). This kind of situation may arise if a traits class only
// makes sense for some set of types, not all C++ types.
template <class T> struct is_int {
BOOST_STATIC_CONSTANT(bool, value = (boost::is_same<T, int>::value));
};
template <class T, class U>
struct mult_traits {
typedef typename T::does_not_exist type;
};
template <>
struct mult_traits<int, int> {
typedef int type;
};
// Next, a forwarding function mult() is defined. It is enabled only
// when both arguments are of type int. The first version, using
// non-lazy enable_if_c does not work.
#if 0
template <class T, class U>
typename enable_if_c<
is_int<T>::value && is_int<U>::value,
typename mult_traits<T, U>::type
>::type
mult(const T& x, const U& y) {return x * y;}
#endif
// A correct version uses lazy_enable_if_c.
// This template removes compiler errors from invalid code used as an
// argument to enable_if_c.
#if 1
template <class T, class U>
typename lazy_enable_if_c<
is_int<T>::value && is_int<U>::value,
mult_traits<T, U>
>::type
mult(const T& x, const U& y) {return x * y;}
#endif
double mult(int i, double d) { return (double)i * d; }
int test_main(int, char*[])
{
BOOST_CHECK(mult(1, 2) == 2);
BOOST_CHECK(mult(1, 3.0) == 3.0);
return 0;
}

View File

@@ -1,98 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
// Testing all variations of lazy_enable_if.
#include <boost/test/minimal.hpp>
#include <boost/mpl/not.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
using boost::lazy_enable_if;
using boost::lazy_disable_if;
using boost::lazy_enable_if_c;
using boost::lazy_disable_if_c;
template <class T>
struct is_int_or_double {
BOOST_STATIC_CONSTANT(bool,
value = (boost::is_same<T, int>::value ||
boost::is_same<T, double>::value));
};
template <class T>
struct some_traits {
typedef typename T::does_not_exist type;
};
template <>
struct some_traits<int> {
typedef bool type;
};
template <>
struct some_traits<double> {
typedef bool type;
};
template <class T>
struct make_bool {
typedef bool type;
};
template <>
struct make_bool<int> {};
template <>
struct make_bool<double> {};
namespace A {
template<class T>
typename lazy_enable_if<is_int_or_double<T>, some_traits<T> >::type
foo(T t) { return true; }
template<class T>
typename lazy_enable_if_c<is_int_or_double<T>::value, some_traits<T> >::type
foo2(T t) { return true; }
}
namespace B {
template<class T>
typename lazy_disable_if<is_int_or_double<T>, make_bool<T> >::type
foo(T t) { return false; }
template<class T>
typename lazy_disable_if_c<is_int_or_double<T>::value, make_bool<T> >::type
foo2(T t) { return false; }
}
int test_main(int, char*[])
{
using namespace A;
using namespace B;
BOOST_CHECK(foo(1));
BOOST_CHECK(foo(1.0));
BOOST_CHECK(!foo("1"));
BOOST_CHECK(!foo(static_cast<void*>(0)));
BOOST_CHECK(foo2(1));
BOOST_CHECK(foo2(1.0));
BOOST_CHECK(!foo2("1"));
BOOST_CHECK(!foo2(static_cast<void*>(0)));
return 0;
}

View File

@@ -1,41 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
struct container {
template <class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(const T&, const int* /* disambiguate */ = 0) {return true;}
template <class T>
typename disable_if<is_arithmetic<T>, bool>::type
arithmetic_object(const T&) {return false;}
};
int test_main(int, char*[])
{
BOOST_CHECK(container().arithmetic_object(1));
BOOST_CHECK(container().arithmetic_object(1.0));
BOOST_CHECK(!container().arithmetic_object("1"));
BOOST_CHECK(!container().arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@@ -1,45 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/mpl/not.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if;
using boost::mpl::not_;
using boost::is_arithmetic;
namespace A {
template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t) { return true; }
}
namespace B {
template<class T>
typename enable_if<not_<is_arithmetic<T> >, bool>::type
arithmetic_object(T t) { return false; }
}
int test_main(int, char*[])
{
using namespace A;
using namespace B;
BOOST_CHECK(arithmetic_object(1));
BOOST_CHECK(arithmetic_object(1.0));
BOOST_CHECK(!arithmetic_object("1"));
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@@ -1,41 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/mpl/not.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::mpl::not_;
using boost::enable_if;
using boost::is_arithmetic;
template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t) { return true; }
template<class T>
typename enable_if<not_<is_arithmetic<T> >, bool>::type
arithmetic_object(T t) { return false; }
int test_main(int, char*[])
{
BOOST_CHECK(arithmetic_object(1));
BOOST_CHECK(arithmetic_object(1.0));
BOOST_CHECK(!arithmetic_object("1"));
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@@ -1,65 +0,0 @@
//
// Copyright 2003 <20> The Trustees of Indiana University.
//
// See the file enable_if_LICENSE for licensing conditions.
//
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
//
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if_c;
using boost::disable_if_c;
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
template <class T, class Enable = void>
struct tester;
template <class T>
struct tester<T, typename enable_if_c<is_arithmetic<T>::value>::type> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct tester<T, typename disable_if_c<is_arithmetic<T>::value>::type> {
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T, class Enable = void>
struct tester2;
template <class T>
struct tester2<T, typename enable_if<is_arithmetic<T> >::type> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct tester2<T, typename disable_if<is_arithmetic<T> >::type> {
BOOST_STATIC_CONSTANT(bool, value = false);
};
int test_main(int, char*[])
{
BOOST_CHECK(tester<int>::value);
BOOST_CHECK(tester<double>::value);
BOOST_CHECK(!tester<char*>::value);
BOOST_CHECK(!tester<void*>::value);
BOOST_CHECK(tester2<int>::value);
BOOST_CHECK(tester2<double>::value);
BOOST_CHECK(!tester2<char*>::value);
BOOST_CHECK(!tester2<void*>::value);
return 0;
}

View File

@@ -1,135 +0,0 @@
// Copyright (c) 2003 Jan Langer
// 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)
// See library home page at http://www.boost.org/libs/utility
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <boost/utility/lexicographic.hpp>
#include <boost/timer.hpp>
bool cmp_lex (int a, int b)
{
return boost::lexicographic
(a / 1000, b / 1000)
(b / 100, a / 100)
(a / 10, b / 10)
(b, a);
}
bool cmp_lex_nl (int a, int b)
{
return boost::lexicographic
(a, b)
(b, a)
(a, b)
(b, a);
}
bool cmp_emul_nl (int a, int b)
{
typedef boost::lexicographic::result_type result_type;
result_type const equivalent = boost::lexicographic::equivalent;
result_type const minus = boost::lexicographic::minus;
result_type const plus = boost::lexicographic::plus;
// ctor
result_type m = equivalent;
if (a < b)
m = minus;
else if (b < a)
m = plus;
else
m = equivalent;
// first operator ()
if (m == equivalent)
if (b < a)
m = minus;
else if (a < b)
m = plus;
else
m = equivalent;
// second operator ()
if (m == equivalent)
if (a < b)
m = minus;
else if (b < a)
m = plus;
else
m = equivalent;
// third operator ()
if (m == equivalent)
if (b < a)
m = minus;
else if (a < b)
m = plus;
else
m = equivalent;
return m == minus;
}
bool cmp_cascade (int a, int b)
{
if (a / 1000 == b / 1000)
if (b / 100 == a / 100)
if (a / 10 == b / 10)
return b < a;
else
return a / 10 < b / 10;
else
return b / 100 < a / 100;
else
return a / 1000 < b / 1000;
}
bool cmp_cascade_nl (int a, int b)
{
if (a == b)
if (b == a)
if (a == b)
return b < a;
else
return a < b;
else
return b < a;
else
return a < b;
}
typedef std::vector <int> int_vector;
void run (int_vector values, // make copy to keep original random order
bool (*cmp) (int, int),
std::string desc)
{
boost::timer uhr;
std::sort (values.begin (), values.end (), cmp);
std::cout << desc << " - " << uhr.elapsed() << '\n';
}
int main ()
{
int_vector::size_type const n = 400000;
int_vector values;
values.reserve (n);
std::srand (std::time (0));
for (unsigned int i = 0; i < n; ++i)
values.push_back (std::rand ());
run (values, cmp_lex, "boost::lexicographic, division");
run (values, cmp_lex_nl, "boost::lexicographic, no division");
run (values, cmp_emul_nl, "boost::lexicographic emulation, no division");
run (values, cmp_cascade, "if cascade, division");
run (values, cmp_cascade_nl, "if cascade, no division");
}

View File

@@ -1,74 +0,0 @@
// Copyright (c) 2003 Jan Langer
// 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)
// See library home page at http://www.boost.org/libs/utility
#include <functional>
#include <boost/test/minimal.hpp>
#include <boost/utility/lexicographic.hpp>
int test_main (int, char *[])
{
using boost::lexicographic;
lexicographic l1; // equivalent
BOOST_CHECK (!l1);
lexicographic l2 (l1); // equivalent
BOOST_CHECK (!l2);
BOOST_CHECK (l1 == l2);
l2 = l1;
BOOST_CHECK (!l2);
BOOST_CHECK (l2 == l1);
l2 (3, 6); // less
BOOST_CHECK (l2);
BOOST_CHECK (l2.result () == lexicographic::minus);
BOOST_CHECK (lexicographic::minus == l2.result ());
BOOST_CHECK (l2.result () != lexicographic::equivalent);
BOOST_CHECK (lexicographic::equivalent != l2.result ());
BOOST_CHECK (l1 != l2);
lexicographic l3 (3.0, 1.0); // greater
BOOST_CHECK (!l3);
BOOST_CHECK (l3 != l1);
for (int i = 1; i <= 3; ++i)
for (int j = 1; j <= 3; ++j)
for (int k = 1; k <= 3; ++k)
{
lexicographic l4;
l4 (i, 2) (j, 2) (k, 2);
if (i < 2)
BOOST_CHECK (l4);
else if (i > 2)
BOOST_CHECK (!l4);
else if (j < 2)
BOOST_CHECK (l4);
else if (j > 2)
BOOST_CHECK (!l4);
else if (k < 2)
BOOST_CHECK (l4);
else
BOOST_CHECK (!l4);
}
lexicographic l5;
l5 (1, 1, std::greater <int> ()) (2, 3);
BOOST_CHECK (l5);
lexicographic l6;
l6 (1, 1, std::greater <int> ()) (2, 3, std::greater <int> ());
BOOST_CHECK (!l6);
lexicographic l7;
l7 (1, 1) (2, 3, std::greater <int> ());
BOOST_CHECK (!l7);
return 0;
}

View File

@@ -1,79 +0,0 @@
// Copyright David Abrahams, Daniel Wallin 2003. 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/named_params.hpp>
#include <cassert>
#include <string>
#include <boost/type_traits/is_convertible.hpp>
#include <iostream>
namespace test
{
using boost::keyword;
using boost::keywords;
using boost::named_param;
struct name_t; keyword<name_t> name;
struct value_t; keyword<value_t> 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>
>
>
{};
template<class P>
void f_impl(P const& p)
{
std::string s = p[name | "bar"];
float v = p[value | 3.f];
assert(s == "foo");
assert(v == 3.f);
}
void f()
{
f_impl(f_keywords()());
}
template<class A0>
void f(A0 const& a0
, typename f_keywords::restrict<A0>::type = f_keywords())
{
f_impl(f_keywords()(a0));
}
template<class A0, class A1>
void f(A0 const& a0, A1 const& a1
, typename f_keywords::restrict<A0, A1>::type = f_keywords())
{
f_impl(f_keywords()(a0, a1));
}
} // namespace test
int main()
{
using test::name;
using test::value;
using test::f;
f("foo");
f("foo", 3.f);
f(value = 3.f, name = "foo");
return 0;
}

View File

@@ -1,156 +0,0 @@
// Copyright David Abrahams, Daniel Wallin 2003. 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/named_params.hpp>
#include <cassert>
#include <string.h>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
namespace test
{
using boost::keyword;
using boost::keywords;
using boost::named_param;
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
>
{};
double value_default()
{
return 666.222;
}
template<class Params>
int f_impl(const Params& p)
{
p[tester](
p[name]
, p[value || boost::bind(&value_default) ]
, p[index | 999]
);
return 1;
}
template<class Tester, class Name, class Value, class Index>
int f(Tester const& t, const Name& name_,
const Value& value_, const Index& index_)
{
return f_impl(f_keywords()(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_));
}
template<class Tester, class Name>
int f(Tester const& t, const Name& name_)
{
return f_impl(f_keywords()(t, name_));
}
template <class T>
bool equal(T const& x, T const& y)
{
return x == y;
}
bool equal(char const* s1, char const* s2)
{
return !strcmp(s1,s2);
}
template <class Name, class Value, class Index>
struct values_t
{
values_t(Name const& n, Value const& v, Index const& i)
: n(n), v(v), i(i)
{}
template <class Name_, class Value_, class Index_>
void operator()(Name_ const& n_, Value_ const& v_, Index_ const& i_) const
{
// Only VC and its emulators fail this; they seem to have
// problems with deducing the constness of string literal
// arrays.
#if defined(_MSC_VER) \
&& (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) \
|| BOOST_WORKAROUND(BOOST_MSVC, < 1310))
# else
BOOST_STATIC_ASSERT((boost::is_same<Index,Index_>::value));
BOOST_STATIC_ASSERT((boost::is_same<Value,Value_>::value));
BOOST_STATIC_ASSERT((boost::is_same<Name,Name_>::value));
#endif
assert(equal(n, n_));
assert(equal(v, v_));
assert(equal(i, i_));
}
Name const& n;
Value const& v;
Index const& i;
};
template <class Name, class Value, class Index>
values_t<Name,Value,Index>
values(Name const& n, Value const& v, Index const& i)
{
return values_t<Name,Value,Index>(n,v,i);
}
}
// GCC2 has a problem with char (&)[] deduction, so we'll cast string
// literals there.
#undef S
#if BOOST_WORKAROUND(__GNUC__, == 2)
# define S(s) (char const*)s
#else
# define S(s) s
#endif
int main()
{
using test::f;
using test::name;
using test::value;
using test::index;
using test::tester;
f(
test::values(S("foo"), S("bar"), S("baz"))
, S("foo"), S("bar"), S("baz")
);
int x = 56;
f(
test::values("foo", 666.222, 56)
, index = boost::ref(x), name = "foo"
);
//f(index = 56, name = 55); // won't compile
return 0;
}

View File

@@ -1,129 +0,0 @@
// Copyright (C) 2002-2003 Doug Gregor (gregod@cs.rpi.edu)
//
// 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.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/tribool.hpp>
#include <cassert>
#include <iostream>
BOOST_TRIBOOL_THIRD_STATE(maybe)
int main()
{
using namespace boost;
tribool x; // false
tribool y(true); // true
tribool z(maybe); // maybe
assert(!x);
assert(x == false);
assert(false == x);
assert(x != true);
assert(true != x);
assert(maybe(x == maybe));
assert(maybe(maybe == x));
assert(maybe(x != maybe));
assert(maybe(maybe != x));
assert(x == x);
assert(!(x != x));
assert(!(x && true));
assert(!(true && x));
assert(x || true);
assert(true || x);
assert(y);
assert(y == true);
assert(true == y);
assert(y != false);
assert(false != y);
assert(maybe(y == maybe));
assert(maybe(maybe == y));
assert(maybe(y != maybe));
assert(maybe(maybe != y));
assert(y == y);
assert(!(y != y));
assert(maybe(z || !z));
assert(maybe(z == true));
assert(maybe(true == z));
assert(maybe(z == false));
assert(maybe(false == z));
assert(maybe(z == maybe));
assert(maybe(maybe == z));
assert(maybe(z != maybe));
assert(maybe(maybe != z));
assert(maybe(z == z));
assert(maybe(z != z));
assert(!(x == y));
assert(x != y);
assert(maybe(x == z));
assert(maybe(x != z));
assert(maybe(y == z));
assert(maybe(y != z));
assert(!(x && y));
assert(x || y);
assert(!(x && z));
assert(maybe(y && z));
assert(maybe(z && z));
assert(maybe(z || z));
assert(maybe(x || z));
assert(y || z);
assert(maybe(y && maybe));
assert(maybe(maybe && y));
assert(!(x && maybe));
assert(!(maybe && x));
assert(maybe || y);
assert(y || maybe);
assert(maybe(x || maybe));
assert(maybe(maybe || x));
// Test the if (z) ... else (!z) ... else ... idiom
if (z) {
assert(false);
}
else if (!z) {
assert(false);
}
else {
assert(true);
}
z = true;
if (z) {
assert(true);
}
else if (!z) {
assert(false);
}
else {
assert(false);
}
z = false;
if (z) {
assert(false);
}
else if (!z) {
assert(true);
}
else {
assert(false);
}
std::cout << "no errors detected\n";
return 0;
}

View File

@@ -1,127 +0,0 @@
// Copyright (C) 2002-2003 Doug Gregor (gregod@cs.rpi.edu)
//
// 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.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/tribool.hpp>
#include <cassert>
#include <iostream>
int main()
{
using namespace boost;
tribool x; // false
tribool y(true); // true
tribool z(indeterminate); // indeterminate
assert(!x);
assert(x == false);
assert(false == x);
assert(x != true);
assert(true != x);
assert(indeterminate(x == indeterminate));
assert(indeterminate(indeterminate == x));
assert(indeterminate(x != indeterminate));
assert(indeterminate(indeterminate != x));
assert(x == x);
assert(!(x != x));
assert(!(x && true));
assert(!(true && x));
assert(x || true);
assert(true || x);
assert(y);
assert(y == true);
assert(true == y);
assert(y != false);
assert(false != y);
assert(indeterminate(y == indeterminate));
assert(indeterminate(indeterminate == y));
assert(indeterminate(y != indeterminate));
assert(indeterminate(indeterminate != y));
assert(y == y);
assert(!(y != y));
assert(indeterminate(z || !z));
assert(indeterminate(z == true));
assert(indeterminate(true == z));
assert(indeterminate(z == false));
assert(indeterminate(false == z));
assert(indeterminate(z == indeterminate));
assert(indeterminate(indeterminate == z));
assert(indeterminate(z != indeterminate));
assert(indeterminate(indeterminate != z));
assert(indeterminate(z == z));
assert(indeterminate(z != z));
assert(!(x == y));
assert(x != y);
assert(indeterminate(x == z));
assert(indeterminate(x != z));
assert(indeterminate(y == z));
assert(indeterminate(y != z));
assert(!(x && y));
assert(x || y);
assert(!(x && z));
assert(indeterminate(y && z));
assert(indeterminate(z && z));
assert(indeterminate(z || z));
assert(indeterminate(x || z));
assert(y || z);
assert(indeterminate(y && indeterminate));
assert(indeterminate(indeterminate && y));
assert(!(x && indeterminate));
assert(!(indeterminate && x));
assert(indeterminate || y);
assert(y || indeterminate);
assert(indeterminate(x || indeterminate));
assert(indeterminate(indeterminate || x));
// Test the if (z) ... else (!z) ... else ... idiom
if (z) {
assert(false);
}
else if (!z) {
assert(false);
}
else {
assert(true);
}
z = true;
if (z) {
assert(true);
}
else if (!z) {
assert(false);
}
else {
assert(false);
}
z = false;
if (z) {
assert(false);
}
else if (!z) {
assert(true);
}
else {
assert(false);
}
std::cout << "no errors detected\n";
return 0;
}

View File

@@ -1,343 +0,0 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
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/test/minimal.hpp>
#include <boost/utility/type_deduction.hpp>
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <complex>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
BOOST_UNARY_RESULT_OF(-x, result_of_negate);
BOOST_UNARY_RESULT_OF(+x, result_of_posit);
BOOST_UNARY_RESULT_OF(!x, result_of_logical_not);
BOOST_UNARY_RESULT_OF(~x, result_of_invert);
BOOST_UNARY_RESULT_OF(&x, result_of_reference);
BOOST_UNARY_RESULT_OF(*x, result_of_dereference);
BOOST_UNARY_RESULT_OF(++x, result_of_pre_increment);
BOOST_UNARY_RESULT_OF(--x, result_of_pre_decrement);
BOOST_UNARY_RESULT_OF(x++, result_of_post_increment);
BOOST_UNARY_RESULT_OF(x--, result_of_post_decrement);
BOOST_BINARY_RESULT_OF(x = y, result_of_assign);
BOOST_ASYMMETRIC_BINARY_RESULT_OF(x[y], result_of_index);
BOOST_BINARY_RESULT_OF(x += y, result_of_plus_assign);
BOOST_BINARY_RESULT_OF(x -= y, result_of_minus_assign);
BOOST_BINARY_RESULT_OF(x *= y, result_of_multiplies_assign);
BOOST_BINARY_RESULT_OF(x /= y, result_of_divides_assign);
BOOST_BINARY_RESULT_OF(x %= y, result_of_modulus_assign);
BOOST_BINARY_RESULT_OF(x &= y, result_of_and_assign);
BOOST_BINARY_RESULT_OF(x |= y, result_of_or_assign);
BOOST_BINARY_RESULT_OF(x ^= y, result_of_xor_assign);
BOOST_BINARY_RESULT_OF(x <<= y, result_of_shift_left_assign);
BOOST_BINARY_RESULT_OF(x >>= y, result_of_shift_right_assign);
BOOST_BINARY_RESULT_OF(x + y, result_of_plus);
BOOST_BINARY_RESULT_OF(x - y, result_of_minus);
BOOST_BINARY_RESULT_OF(x * y, result_of_multiplies);
BOOST_BINARY_RESULT_OF(x / y, result_of_divides);
BOOST_BINARY_RESULT_OF(x % y, result_of_modulus);
BOOST_BINARY_RESULT_OF(x & y, result_of_and);
BOOST_BINARY_RESULT_OF(x | y, result_of_or);
BOOST_BINARY_RESULT_OF(x ^ y, result_of_xor);
BOOST_BINARY_RESULT_OF(x << y, result_of_shift_left);
BOOST_BINARY_RESULT_OF(x >> y, result_of_shift_right);
BOOST_BINARY_RESULT_OF(x == y, result_of_equal_to);
BOOST_BINARY_RESULT_OF(x != y, result_of_not_equal_to);
BOOST_BINARY_RESULT_OF(x < y, result_of_less);
BOOST_BINARY_RESULT_OF(x <= y, result_of_less_equal);
BOOST_BINARY_RESULT_OF(x > y, result_of_greater);
BOOST_BINARY_RESULT_OF(x >= y, result_of_greater_equal);
BOOST_BINARY_RESULT_OF(x && y, result_of_logical_and);
BOOST_BINARY_RESULT_OF(x || y, result_of_logical_or);
BOOST_BINARY_RESULT_OF(true ? x : y, result_of_if_else);
}
using namespace boost;
using namespace std;
struct X {};
X operator+(X, int);
struct Y {};
Y* operator+(Y, int);
struct Z {};
Z const* operator+(Z const&, int);
Z& operator+(Z&, int);
bool operator==(Z, Z);
bool operator==(Z, int);
struct W {};
Z operator+(W, int);
bool operator==(W, Z);
int
test_main(int, char*[])
{
// PLUS
{
typedef result_of_plus<int, double>::type result;
BOOST_STATIC_ASSERT((is_same<result, double>::value));
}
{
typedef result_of_plus<double, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, double>::value));
}
{
typedef result_of_plus<int, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_plus<float, short>::type result;
BOOST_STATIC_ASSERT((is_same<result, float>::value));
}
{
typedef result_of_plus<char, short>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_plus<long, short>::type result;
BOOST_STATIC_ASSERT((is_same<result, long>::value));
}
{
typedef result_of_plus<long, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, long>::value));
}
{
typedef result_of_plus<X, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, X>::value));
}
{
typedef result_of_plus<Y, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, Y*>::value));
}
{
typedef result_of_plus<Z, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, Z&>::value));
}
{
typedef result_of_plus<Z const, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, Z const*>::value));
}
{
typedef result_of_plus<complex<double>, double>::type result;
BOOST_STATIC_ASSERT((is_same<result, complex<double> >::value));
}
{
typedef result_of_plus<double, complex<double> >::type result;
BOOST_STATIC_ASSERT((is_same<result, complex<double> >::value));
}
{
typedef result_of_plus<int*, size_t>::type result;
BOOST_STATIC_ASSERT((is_same<result, int*>::value));
}
// INDEX
{
typedef result_of_index<int(&)[3], int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int&>::value));
}
{
typedef result_of_index<X(&)[3], int>::type result;
BOOST_STATIC_ASSERT((is_same<result, X&>::value));
}
{
typedef result_of_index<X const(&)[3], int>::type result;
BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
}
{
typedef result_of_index<X*, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, X&>::value));
}
{
typedef result_of_index<X const*, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
}
{
typedef result_of_index<vector<int>, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, vector<int>::reference>::value));
}
{
typedef result_of_index<vector<int> const, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_index<vector<X> const, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, vector<X>::const_reference>::value));
}
{
typedef result_of_index<vector<X>, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, vector<X>::reference>::value));
}
{
typedef result_of_index<string, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, string::reference>::value));
}
{
typedef result_of_index<vector<int>::iterator, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, vector<int>::iterator::reference>::value));
}
{
typedef result_of_index<vector<int>::const_iterator, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_index<vector<X>::const_iterator, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, vector<X>::const_iterator::reference>::value));
}
{
typedef result_of_index<map<char, X>, char>::type result;
BOOST_STATIC_ASSERT((is_same<result, map<char, X>::mapped_type>::value));
}
// PLUS ASSIGN
{
typedef result_of_plus_assign<int, char>::type result;
BOOST_STATIC_ASSERT((is_same<result, int&>::value));
}
{
typedef result_of_plus_assign<double, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, double&>::value));
}
{
typedef result_of_plus_assign<complex<double>, double>::type result;
BOOST_STATIC_ASSERT((is_same<result, complex<double>&>::value));
}
// SHIFT LEFT
{
typedef result_of_shift_left<int, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_shift_left<short, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_shift_left<ostream, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, ostream&>::value));
}
// EQUAL
{
typedef result_of_equal_to<int, double>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<double, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<int, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<float, short>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<char, short>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<Z, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<Z, Z>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
{
typedef result_of_equal_to<W, Z>::type result;
BOOST_STATIC_ASSERT((is_same<result, bool>::value));
}
// MINUS (pointers)
{
typedef result_of_minus<X*, X*>::type result;
BOOST_STATIC_ASSERT((is_same<result, std::ptrdiff_t>::value));
}
// DEREFERENCE
{
typedef result_of_dereference<X*>::type result;
BOOST_STATIC_ASSERT((is_same<result, X&>::value));
}
{
typedef result_of_dereference<vector<X>::iterator>::type result;
BOOST_STATIC_ASSERT((is_same<result, X&>::value));
}
{
typedef result_of_dereference<shared_ptr<X> >::type result;
BOOST_STATIC_ASSERT((is_same<result, X&>::value));
}
// ADDRESS OF
{
typedef result_of_reference<X>::type result;
BOOST_STATIC_ASSERT((is_same<result, X*>::value));
}
{
typedef result_of_reference<X const>::type result;
BOOST_STATIC_ASSERT((is_same<result, X const*>::value));
}
// PRE INCREMENT
{
typedef result_of_pre_increment<int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int&>::value));
}
// POST INCREMENT
{
typedef result_of_post_increment<int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
// IF-ELSE-EXPRESSION ( c ? a : b )
{
typedef result_of_if_else<int, char>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_if_else<int, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, int&>::value));
}
{
typedef result_of_if_else<int const, int const>::type result;
BOOST_STATIC_ASSERT((is_same<result, int>::value));
}
{
typedef result_of_if_else<X, X>::type result;
BOOST_STATIC_ASSERT((is_same<result, X&>::value));
}
{
typedef result_of_if_else<X const&, X const&>::type result;
BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
}
// DEDUCTION FAILURE
{
typedef result_of_plus<W, int>::type result;
BOOST_STATIC_ASSERT((is_same<result, error_cant_deduce_type>::value));
}
return 0;
}