Added new type traits files.

[SVN r9238]
This commit is contained in:
John Maddock
2001-02-17 12:25:45 +00:00
parent 6fda1821b2
commit f3976d8060
32 changed files with 6095 additions and 24 deletions

590
c++_type_traits.htm Normal file
View File

@ -0,0 +1,590 @@
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>C++ Type traits</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<h2 align="center">C++ Type traits</h2>
<p align="center"><em>by John Maddock and Steve Cleary</em></p>
<p align="center"><em>This is the draft version of an article
that appeared in the October 2000 issue of </em><a
href="http://www.ddj.com"><em>Dr Dobb's Journal</em></a></p>
<p>Generic programming (writing code which works with any data
type meeting a set of requirements) has become the method of
choice for providing reusable code. However, there are times in
generic programming when &quot;generic&quot; just isn't good
enough - sometimes the differences between types are too large
for an efficient generic implementation. This is when the traits
technique becomes important - by encapsulating those properties
that need to be considered on a type by type basis inside a
traits class, we can minimise the amount of code that has to
differ from one type to another, and maximise the amount of
generic code.</p>
<p>Consider an example: when working with character strings, one
common operation is to determine the length of a null terminated
string. Clearly it's possible to write generic code that can do
this, but it turns out that there are much more efficient methods
available: for example, the C library functions <font size="2"
face="Courier New">strlen</font> and <font size="2"
face="Courier New">wcslen</font> are usually written in assembler,
and with suitable hardware support can be considerably faster
than a generic version written in C++. The authors of the C++
standard library realised this, and abstracted the properties of <font
size="2" face="Courier New">char</font> and <font size="2"
face="Courier New">wchar_t</font> into the class <font size="2"
face="Courier New">char_traits</font>. Generic code that works
with character strings can simply use <font size="2"
face="Courier New">char_traits&lt;&gt;::length</font> to
determine the length of a null terminated string, safe in the
knowledge that specialisations of <font size="2"
face="Courier New">char_traits</font> will use the most
appropriate method available to them.</p>
<h4>Type traits</h4>
<p>Class <font size="2" face="Courier New">char_traits</font> is
a classic example of a collection of type specific properties
wrapped up in a single class - what Nathan Myers termed a <i>baggage
class</i>[1]. In the Boost type-traits library, we[2] have
written a set of very specific traits classes, each of which
encapsulate a single trait from the C++ type system; for example,
is a type a pointer or a reference type? Or does a type have a
trivial constructor, or a const-qualifier? The type-traits
classes share a unified design: each class has a single member <i>value</i>,
a compile-time constant that is true if the type has the
specified property, and false otherwise. As we will show, these
classes can be used in generic programming to determine the
properties of a given type and introduce optimisations that are
appropriate for that case.</p>
<p>The type-traits library also contains a set of classes that
perform a specific transformation on a type; for example, they
can remove a top-level const or volatile qualifier from a type.
Each class that performs a transformation defines a single
typedef-member <i>type</i> that is the result of the
transformation. All of the type-traits classes are defined inside
namespace <font size="2" face="Courier New">boost</font>; for
brevity, namespace-qualification is omitted in most of the code
samples given.</p>
<h4>Implementation</h4>
<p>There are far too many separate classes contained in the type-traits
library to give a full implementation here - see the source code
in the Boost library for the full details - however, most of the
implementation is fairly repetitive anyway, so here we will just
give you a flavour for how some of the classes are implemented.
Beginning with possibly the simplest class in the library, is_void&lt;T&gt;
has a member <i>value</i> that is true only if T is void.</p>
<pre>template &lt;typename T&gt;
struct is_void
{ static const bool value = false; };
template &lt;&gt;
struct is_void&lt;void&gt;
{ static const bool value = true; };</pre>
<p>Here we define a primary version of the template class <font
size="2" face="Courier New">is_void</font>, and provide a full-specialisation
when T is void. While full specialisation of a template class is
an important technique, sometimes we need a solution that is
halfway between a fully generic solution, and a full
specialisation. This is exactly the situation for which the
standards committee defined partial template-class specialisation.
As an example, consider the class boost::is_pointer&lt;T&gt;:
here we needed a primary version that handles all the cases where
T is not a pointer, and a partial specialisation to handle all
the cases where T is a pointer:</p>
<pre>template &lt;typename T&gt;
struct is_pointer
{ static const bool value = false; };
template &lt;typename T&gt;
struct is_pointer&lt;T*&gt;
{ static const bool value = true; };</pre>
<p>The syntax for partial specialisation is somewhat arcane and
could easily occupy an article in its own right; like full
specialisation, in order to write a partial specialisation for a
class, you must first declare the primary template. The partial
specialisation contains an extra &lt;&#133;&gt; after the class
name that contains the partial specialisation parameters; these
define the types that will bind to that partial specialisation
rather than the default template. The rules for what can appear
in a partial specialisation are somewhat convoluted, but as a
rule of thumb if you can legally write two function overloads of
the form:</p>
<pre>void foo(T);
void foo(U);</pre>
<p>Then you can also write a partial specialisation of the form:</p>
<pre>template &lt;typename T&gt;
class c{ /*details*/ };
template &lt;typename T&gt;
class c&lt;U&gt;{ /*details*/ };</pre>
<p>This rule is by no means foolproof, but it is reasonably
simple to remember and close enough to the actual rule to be
useful for everyday use.</p>
<p>As a more complex example of partial specialisation consider
the class remove_bounds&lt;T&gt;. This class defines a single
typedef-member <i>type</i> that is the same type as T but with
any top-level array bounds removed; this is an example of a
traits class that performs a transformation on a type:</p>
<pre>template &lt;typename T&gt;
struct remove_bounds
{ typedef T type; };
template &lt;typename T, std::size_t N&gt;
struct remove_bounds&lt;T[N]&gt;
{ typedef T type; };</pre>
<p>The aim of remove_bounds is this: imagine a generic algorithm
that is passed an array type as a template parameter, <font
size="2" face="Courier New">remove_bounds</font> provides a means
of determining the underlying type of the array. For example <code>remove_bounds&lt;int[4][5]&gt;::type</code>
would evaluate to the type <code>int[5]</code>. This example also
shows that the number of template parameters in a partial
specialisation does not have to match the number in the default
template. However, the number of parameters that appear after the
class name do have to match the number and type of the parameters
in the default template.</p>
<h4>Optimised copy</h4>
<p>As an example of how the type traits classes can be used,
consider the standard library algorithm copy:</p>
<pre>template&lt;typename Iter1, typename Iter2&gt;
Iter2 copy(Iter1 first, Iter1 last, Iter2 out);</pre>
<p>Obviously, there's no problem writing a generic version of
copy that works for all iterator types Iter1 and Iter2; however,
there are some circumstances when the copy operation can best be
performed by a call to <font size="2" face="Courier New">memcpy</font>.
In order to implement copy in terms of <font size="2"
face="Courier New">memcpy</font> all of the following conditions
need to be met:</p>
<ul>
<li>Both of the iterator types Iter1 and Iter2 must be
pointers.</li>
<li>Both Iter1 and Iter2 must point to the same type -
excluding <font size="2" face="Courier New">const</font>
and <font size="2" face="Courier New">volatile</font>-qualifiers.</li>
<li>The type pointed to by Iter1 must have a trivial
assignment operator.</li>
</ul>
<p>By trivial assignment operator we mean that the type is either
a scalar type[3] or:</p>
<ul>
<li>The type has no user defined assignment operator.</li>
<li>The type does not have any data members that are
references.</li>
<li>All base classes, and all data member objects must have
trivial assignment operators.</li>
</ul>
<p>If all these conditions are met then a type can be copied
using <font size="2" face="Courier New">memcpy</font> rather than
using a compiler generated assignment operator. The type-traits
library provides a class <i>has_trivial_assign</i>, such that <code>has_trivial_assign&lt;T&gt;::value</code>
is true only if T has a trivial assignment operator. This class
&quot;just works&quot; for scalar types, but has to be explicitly
specialised for class/struct types that also happen to have a
trivial assignment operator. In other words if <i>has_trivial_assign</i>
gives the wrong answer, it will give the &quot;safe&quot; wrong
answer - that trivial assignment is not allowable.</p>
<p>The code for an optimised version of copy that uses <font
size="2" face="Courier New">memcpy</font> where appropriate is
given in listing 1. The code begins by defining a template class <i>copier</i>,
that takes a single Boolean template parameter, and has a static
template member function <font size="2" face="Courier New">do_copy</font>
which performs the generic version of <font size="2">copy</font>
(in other words the &quot;slow but safe version&quot;). Following
that there is a specialisation for <i>copier&lt;true&gt;</i>:
again this defines a static template member function <font
size="2" face="Courier New">do_copy</font>, but this version uses
memcpy to perform an &quot;optimised&quot; copy.</p>
<p>In order to complete the implementation, what we need now is a
version of copy, that calls <code>copier&lt;true&gt;::do_copy</code>
if it is safe to use <font size="2" face="Courier New">memcpy</font>,
and otherwise calls <code>copier&lt;false&gt;::do_copy</code> to
do a &quot;generic&quot; copy. This is what the version in
listing 1 does. To understand how the code works look at the code
for <font size="2" face="Courier New">copy</font> and consider
first the two typedefs <i>v1_t</i> and <i>v2_t</i>. These use <code>std::iterator_traits&lt;Iter1&gt;::value_type</code>
to determine what type the two iterators point to, and then feed
the result into another type-traits class <i>remove_cv</i> that
removes the top-level const-volatile-qualifiers: this will allow
copy to compare the two types without regard to const- or
volatile-qualifiers. Next, <font size="2" face="Courier New">copy</font>
declares an enumerated value <i>can_opt</i> that will become the
template parameter to copier - declaring this here as a constant
is really just a convenience - the value could be passed directly
to class <font size="2" face="Courier New">copier</font>. The
value of <i>can_opt</i> is computed by verifying that all of the
following are true:</p>
<ul>
<li>first that the two iterators point to the same type by
using a type-traits class <i>is_same</i>.</li>
<li>Then that both iterators are real pointers - using the
class <i>is_pointer</i> described above.</li>
<li>Finally that the pointed-to types have a trivial
assignment operator using <i>has_trivial_assign</i>.</li>
</ul>
<p>Finally we can use the value of <i>can_opt</i> as the template
argument to copier - this version of copy will now adapt to
whatever parameters are passed to it, if its possible to use <font
size="2" face="Courier New">memcpy</font>, then it will do so,
otherwise it will use a generic copy.</p>
<h4>Was it worth it?</h4>
<p>It has often been repeated in these columns that &quot;premature
optimisation is the root of all evil&quot; [4]. So the question
must be asked: was our optimisation premature? To put this in
perspective the timings for our version of copy compared a
conventional generic copy[5] are shown in table 1.</p>
<p>Clearly the optimisation makes a difference in this case; but,
to be fair, the timings are loaded to exclude cache miss effects
- without this accurate comparison between algorithms becomes
difficult. However, perhaps we can add a couple of caveats to the
premature optimisation rule:</p>
<ul>
<li>If you use the right algorithm for the job in the first
place then optimisation will not be required; in some
cases, <font size="2" face="Courier New">memcpy</font> is
the right algorithm.</li>
<li>If a component is going to be reused in many places by
many people then optimisations may well be worthwhile
where they would not be so for a single case - in other
words, the likelihood that the optimisation will be
absolutely necessary somewhere, sometime is that much
higher. Just as importantly the perceived value of the
stock implementation will be higher: there is no point
standardising an algorithm if users reject it on the
grounds that there are better, more heavily optimised
versions available.</li>
</ul>
<h4>Table 1: Time taken to copy 1000 elements using copy&lt;const
T*, T*&gt; (times in micro-seconds)</h4>
<table border="1" cellpadding="7" cellspacing="1" width="529">
<tr>
<td valign="top" width="33%"><p align="center">Version</p>
</td>
<td valign="top" width="33%"><p align="center">T</p>
</td>
<td valign="top" width="33%"><p align="center">Time</p>
</td>
</tr>
<tr>
<td valign="top" width="33%">&quot;Optimised&quot; copy</td>
<td valign="top" width="33%">char</td>
<td valign="top" width="33%">0.99</td>
</tr>
<tr>
<td valign="top" width="33%">Conventional copy</td>
<td valign="top" width="33%">char</td>
<td valign="top" width="33%">8.07</td>
</tr>
<tr>
<td valign="top" width="33%">&quot;Optimised&quot; copy</td>
<td valign="top" width="33%">int</td>
<td valign="top" width="33%">2.52</td>
</tr>
<tr>
<td valign="top" width="33%">Conventional copy</td>
<td valign="top" width="33%">int</td>
<td valign="top" width="33%">8.02</td>
</tr>
</table>
<p>&nbsp;</p>
<h4>Pair of References</h4>
<p>The optimised copy example shows how type traits may be used
to perform optimisation decisions at compile-time. Another
important usage of type traits is to allow code to compile that
otherwise would not do so unless excessive partial specialization
is used. This is possible by delegating partial specialization to
the type traits classes. Our example for this form of usage is a
pair that can hold references [6].</p>
<p>First, let us examine the definition of &quot;std::pair&quot;,
omitting the comparision operators, default constructor, and
template copy constructor for simplicity:</p>
<pre>template &lt;typename T1, typename T2&gt;
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(const T1 &amp; nfirst, const T2 &amp; nsecond)
:first(nfirst), second(nsecond) { }
};</pre>
<p>Now, this &quot;pair&quot; cannot hold references as it
currently stands, because the constructor would require taking a
reference to a reference, which is currently illegal [7]. Let us
consider what the constructor's parameters would have to be in
order to allow &quot;pair&quot; to hold non-reference types,
references, and constant references:</p>
<table border="1" cellpadding="7" cellspacing="1" width="638">
<tr>
<td valign="top" width="50%">Type of &quot;T1&quot;</td>
<td valign="top" width="50%">Type of parameter to
initializing constructor</td>
</tr>
<tr>
<td valign="top" width="50%"><pre>T</pre>
</td>
<td valign="top" width="50%"><pre>const T &amp;</pre>
</td>
</tr>
<tr>
<td valign="top" width="50%"><pre>T &amp;</pre>
</td>
<td valign="top" width="50%"><pre>T &amp;</pre>
</td>
</tr>
<tr>
<td valign="top" width="50%"><pre>const T &amp;</pre>
</td>
<td valign="top" width="50%"><pre>const T &amp;</pre>
</td>
</tr>
</table>
<p>A little familiarity with the type traits classes allows us to
construct a single mapping that allows us to determine the type
of parameter from the type of the contained class. The type
traits classes provide a transformation &quot;add_reference&quot;,
which adds a reference to its type, unless it is already a
reference.</p>
<table border="1" cellpadding="7" cellspacing="1" width="580">
<tr>
<td valign="top" width="21%">Type of &quot;T1&quot;</td>
<td valign="top" width="27%">Type of &quot;const T1&quot;</td>
<td valign="top" width="53%">Type of &quot;add_reference&lt;const
T1&gt;::type&quot;</td>
</tr>
<tr>
<td valign="top" width="21%"><pre>T</pre>
</td>
<td valign="top" width="27%"><pre>const T</pre>
</td>
<td valign="top" width="53%"><pre>const T &amp;</pre>
</td>
</tr>
<tr>
<td valign="top" width="21%"><pre>T &amp;</pre>
</td>
<td valign="top" width="27%"><pre>T &amp; [8]</pre>
</td>
<td valign="top" width="53%"><pre>T &amp;</pre>
</td>
</tr>
<tr>
<td valign="top" width="21%"><pre>const T &amp;</pre>
</td>
<td valign="top" width="27%"><pre>const T &amp;</pre>
</td>
<td valign="top" width="53%"><pre>const T &amp;</pre>
</td>
</tr>
</table>
<p>This allows us to build a primary template definition for
&quot;pair&quot; that can contain non-reference types, reference
types, and constant reference types:</p>
<pre>template &lt;typename T1, typename T2&gt;
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(boost::add_reference&lt;const T1&gt;::type nfirst,
boost::add_reference&lt;const T2&gt;::type nsecond)
:first(nfirst), second(nsecond) { }
};</pre>
<p>Add back in the standard comparision operators, default
constructor, and template copy constructor (which are all the
same), and you have a std::pair that can hold reference types!</p>
<p>This same extension <i>could</i> have been done using partial
template specialization of &quot;pair&quot;, but to specialize
&quot;pair&quot; in this way would require three partial
specializations, plus the primary template. Type traits allows us
to define a single primary template that adjusts itself auto-magically
to any of these partial specializations, instead of a brute-force
partial specialization approach. Using type traits in this
fashion allows programmers to delegate partial specialization to
the type traits classes, resulting in code that is easier to
maintain and easier to understand.</p>
<h4>Conclusion</h4>
<p>We hope that in this article we have been able to give you
some idea of what type-traits are all about. A more complete
listing of the available classes are in the boost documentation,
along with further examples using type traits. Templates have
enabled C++ uses to take the advantage of the code reuse that
generic programming brings; hopefully this article has shown that
generic programming does not have to sink to the lowest common
denominator, and that templates can be optimal as well as generic.</p>
<h4>Acknowledgements</h4>
<p>The authors would like to thank Beman Dawes and Howard Hinnant
for their helpful comments when preparing this article.</p>
<h4>References</h4>
<ol>
<li>Nathan C. Myers, C++ Report, June 1995.</li>
<li>The type traits library is based upon contributions by
Steve Cleary, Beman Dawes, Howard Hinnant and John
Maddock: it can be found at www.boost.org.</li>
<li>A scalar type is an arithmetic type (i.e. a built-in
integer or floating point type), an enumeration type, a
pointer, a pointer to member, or a const- or volatile-qualified
version of one of these types.</li>
<li>This quote is from Donald Knuth, ACM Computing Surveys,
December 1974, pg 268.</li>
<li>The test code is available as part of the boost utility
library (see algo_opt_examples.cpp), the code was
compiled with gcc 2.95 with all optimisations turned on,
tests were conducted on a 400MHz Pentium II machine
running Microsoft Windows 98.</li>
<li>John Maddock and Howard Hinnant have submitted a &quot;compressed_pair&quot;
library to Boost, which uses a technique similar to the
one described here to hold references. Their pair also
uses type traits to determine if any of the types are
empty, and will derive instead of contain to conserve
space -- hence the name &quot;compressed&quot;.</li>
<li>This is actually an issue with the C++ Core Language
Working Group (issue #106), submitted by Bjarne
Stroustrup. The tentative resolution is to allow a &quot;reference
to a reference to T&quot; to mean the same thing as a
&quot;reference to T&quot;, but only in template
instantiation, in a method similar to multiple cv-qualifiers.</li>
<li>For those of you who are wondering why this shouldn't be
const-qualified, remember that references are always
implicitly constant (for example, you can't re-assign a
reference). Remember also that &quot;const T &amp;&quot;
is something completely different. For this reason, cv-qualifiers
on template type arguments that are references are
ignored.</li>
</ol>
<h2>Listing 1</h2>
<pre>namespace detail{
template &lt;bool b&gt;
struct copier
{
template&lt;typename I1, typename I2&gt;
static I2 do_copy(I1 first,
I1 last, I2 out);
};
template &lt;bool b&gt;
template&lt;typename I1, typename I2&gt;
I2 copier&lt;b&gt;::do_copy(I1 first,
I1 last,
I2 out)
{
while(first != last)
{
*out = *first;
++out;
++first;
}
return out;
}
template &lt;&gt;
struct copier&lt;true&gt;
{
template&lt;typename I1, typename I2&gt;
static I2* do_copy(I1* first, I1* last, I2* out)
{
memcpy(out, first, (last-first)*sizeof(I2));
return out+(last-first);
}
};
}
template&lt;typename I1, typename I2&gt;
inline I2 copy(I1 first, I1 last, I2 out)
{
typedef typename
boost::remove_cv&lt;
typename std::iterator_traits&lt;I1&gt;
::value_type&gt;::type v1_t;
typedef typename
boost::remove_cv&lt;
typename std::iterator_traits&lt;I2&gt;
::value_type&gt;::type v2_t;
enum{ can_opt =
boost::is_same&lt;v1_t, v2_t&gt;::value
&amp;&amp; boost::is_pointer&lt;I1&gt;::value
&amp;&amp; boost::is_pointer&lt;I2&gt;::value
&amp;&amp; boost::
has_trivial_assign&lt;v1_t&gt;::value
};
return detail::copier&lt;can_opt&gt;::
do_copy(first, last, out);
}</pre>
<hr>
<p><EFBFBD> Copyright John Maddock and Steve Cleary, 2000</p>
</body>
</html>

View File

@ -1,5 +1,5 @@
// (C) Copyright John Maddock 2000.
// (C) Copyright John Maddock and Steve Cleary 2000.
// 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
@ -73,3 +73,4 @@ struct ice_and<true, true, true, true, true, true, true>

View File

@ -1,4 +1,4 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// (C) Copyright Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000.
// 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
@ -87,3 +87,4 @@ public:
#endif // SAME_TRAITS_HPP

View File

@ -175,6 +175,8 @@ public:
// include a bunch of full specialisations as a workaround:
//
#include <boost/type_traits/transform_traits_spec.hpp>
#else
#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(x)
#endif
#endif // TRANSFORM_TRAITS_HPP
@ -182,3 +184,4 @@ public:

View File

@ -5,6 +5,9 @@
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
#ifndef BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP
#define BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP
#ifndef TRANSFORM_TRAITS_HPP
#include <boost/type_traits/transform_traits.hpp>
#endif
@ -67,9 +70,5 @@ BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(float)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(double)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(long double)
#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_CONST_VOLATILE_RANK1
#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1
#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_2
#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1
#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2
#endif // BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP

View File

@ -5,7 +5,7 @@
content="text/html; charset=iso-8859-1">
<meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>Type Traits</title>
</head>
@ -471,8 +471,8 @@ relationship between two types:</p>
<p align="center">8.5</p>
</td>
<td valign="top" width="25%" bgcolor="#C0C0C0">Note that
this template is currently broken with Borland's compiler,
for constructor-based conversions.</td>
this template is currently broken with Borland's
compiler, for constructor-based conversions.</td>
<td valign="top" width="5%">&nbsp;</td>
</tr>
</table>
@ -595,7 +595,64 @@ transformation to the template argument T:</p>
</tr>
</table>
<p>&nbsp;</p>
<p>As the table above indicates, support for partial
specialization of class templates is required to correctly
implement the type transformation templates. On the other hand,
practice shows that many of the templates from this category are
very useful, and often essential for implementing some generic
libraries. Lack of these templates is often one of the major
limiting factors in porting those libraries to compilers that do
not yet support this language feature. As some of these compilers
are going to be around for a while, and at least one of them is
very wide-spread, it was decided that the library should provide
workarounds where possible. The basic idea behind the workaround
is</p>
<ol>
<li>To manually define full specializations of all type
transformation templates for all fundamental types, and
all their 1st and 2nd rank cv-[un]qualified derivative
pointer types, and to</li>
<li>Provide a user-level macro that will define such explicit
specializations for any user-defined type T.</li>
</ol>
<p>The first part guarantees the successful compilation of
something like this:</p>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char, remove_reference&lt;char&amp;&gt;::type&gt;::value));</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char const, remove_reference&lt;char const&amp;&gt;::type&gt;::value));</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char volatile, remove_reference&lt;char volatile&amp;&gt;::type&gt;::value));</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char const volatile, remove_reference&lt;char const volatile&amp;&gt;::type&gt;::value));</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char*, remove_reference&lt;char*&amp;&gt;::type&gt;::value));</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char const*, remove_reference&lt;char const*&amp;&gt;::type&gt;::value));</pre>
<pre>...</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;char const volatile* const volatile* const volatile, remove_reference&lt;char const volatile* const volatile* const volatile&amp;&gt;::type&gt;::value));</pre>
<p>and the second part provides library's users with a mechanism
to make the above code work not only for 'char', 'int' or other
built-in type, but for they own types too:</p>
<pre>struct my {};</pre>
<pre>BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(my)</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;my, remove_reference&lt;my&amp;&gt;::type&gt;::value));</pre>
<pre>BOOST_STATIC_ASSERT((is_same&lt;my, remove_const&lt;my const&gt;::type&gt;::value));</pre>
<pre>// etc.</pre>
<p>Note that the maco
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates to
nothing on those compilers that do support partial specialisation.</p>
<h2><a name="compiler"></a>Compiler Support Information</h2>
@ -637,11 +694,11 @@ happen if: T is a union or T is a compiler-supplied scalar type
that is not specialised for in these type traits.</p>
<p><i>If there is no compiler support</i>, to ensure that these
traits <i>always</i> return the correct values, specialise 'is_union'
for each user-defined union type, 'is_empty' for each user-defined
empty composite type, and 'is_POD' for each user-defined POD type.
The 'has_*' traits should also be specialized if the user-defined
type has those traits and is <i>not</i> a POD.</p>
traits <i>always</i> return the correct values, specialise
'is_union' for each user-defined union type, 'is_empty' for each
user-defined empty composite type, and 'is_POD' for each user-defined
POD type. The 'has_*' traits should also be specialized if the
user-defined type has those traits and is <i>not</i> a POD.</p>
<p>The following rules are automatically enforced:</p>

240
examples/copy_example.cpp Normal file
View File

@ -0,0 +1,240 @@
/*
*
* Copyright (c) 1999
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* This file provides some example of type_traits usage -
* by "optimising" various algorithms:
*
* opt::copy - optimised for trivial copy (cf std::copy)
*
*/
#include <iostream>
#include <typeinfo>
#include <algorithm>
#include <iterator>
#include <memory>
#include <boost/timer.hpp>
#include <boost/type_traits.hpp>
using std::cout;
using std::endl;
using std::cin;
namespace opt{
//
// opt::copy
// same semantics as std::copy
// calls memcpy where appropiate.
//
namespace detail{
template<typename I1, typename I2>
I2 copy_imp(I1 first, I1 last, I2 out)
{
while(first != last)
{
*out = *first;
++out;
++first;
}
return out;
}
template <bool b>
struct copier
{
template<typename I1, typename I2>
static I2 do_copy(I1 first, I1 last, I2 out)
{ return copy_imp(first, last, out); }
};
template <>
struct copier<true>
{
template<typename I1, typename I2>
static I2* do_copy(I1* first, I1* last, I2* out)
{
memcpy(out, first, (last-first)*sizeof(I2));
return out+(last-first);
}
};
}
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
template<typename I1, typename I2>
inline I2 copy(I1 first, I1 last, I2 out)
{
typedef typename boost::remove_cv<typename std::iterator_traits<I1>::value_type>::type v1_t;
typedef typename boost::remove_cv<typename std::iterator_traits<I2>::value_type>::type v2_t;
return detail::copier<
::boost::type_traits::ice_and<
::boost::is_same<v1_t, v2_t>::value,
::boost::is_pointer<I1>::value,
::boost::is_pointer<I2>::value,
::boost::has_trivial_assign<v1_t>::value
>::value>::do_copy(first, last, out);
}
#else // BOOST_NO_STD_ITERATOR_TRAITS
//
// If there is no standard iterator_traits then we have to
// use overloading rather than iterator_traits to detect
// when we have T*'s to copy. Note that we cannot overload
// copy directly as that will cause some standard conforming
// code to fail to build:
namespace detail{
template<typename I1, typename I2>
inline I2 copy_(const I1& first, const I1& last, const I2& out)
{
return detail::copier<false>::do_copy(first, last, out);
}
template<typename T>
inline T* copy_(const T* first, const T* last, T* out)
{
return detail::copier<
::boost::has_trivial_assign<T>::value
>::do_copy(first, last, out);
}
} // namespace detail
template<typename I1, typename I2>
inline I2 copy(I1 first, I1 last, I2 out)
{
return detail::copy_(first, last, out);
}
#endif // BOOST_NO_STD_ITERATOR_TRAITS
}; // namespace opt
//
// define some global data:
//
const int array_size = 1000;
int i_array_[array_size] = {0,};
const int ci_array_[array_size] = {0,};
char c_array_[array_size] = {0,};
const char cc_array_[array_size] = { 0,};
//
// since arrays aren't iterators we define a set of pointer
// aliases into the arrays (otherwise the compiler is entitled
// to deduce the type passed to the template functions as
// T (&)[N] rather than T*).
int* i_array = i_array_;
const int* ci_array = ci_array_;
char* c_array = c_array_;
const char* cc_array = cc_array_;
const int iter_count = 1000000;
int main()
{
boost::timer t;
double result;
int i;
cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
cout << "testing copy...\n"
"[Some standard library versions may already perform this optimisation.]" << endl;
// cache load:
opt::copy(ci_array, ci_array + array_size, i_array);
// time optimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::copy(ci_array, ci_array + array_size, i_array);
}
result = t.elapsed();
cout << "opt::copy<const int*, int*>: " << result << endl;
// cache load:
std::copy(ci_array, ci_array + array_size, i_array);
// time standard version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::copy(ci_array, ci_array + array_size, i_array);
}
result = t.elapsed();
cout << "std::copy<const int*, int*>: " << result << endl;
// cache load:
opt::detail::copier<false>::do_copy(ci_array, ci_array + array_size, i_array);
// time unoptimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::detail::copier<false>::do_copy(ci_array, ci_array + array_size, i_array);
}
result = t.elapsed();
cout << "standard \"unoptimised\" copy: " << result << endl << endl;
// cache load:
opt::copy(cc_array, cc_array + array_size, c_array);
// time optimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::copy(cc_array, cc_array + array_size, c_array);
}
result = t.elapsed();
cout << "opt::copy<const char*, char*>: " << result << endl;
// cache load:
std::copy(cc_array, cc_array + array_size, c_array);
// time standard version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::copy(cc_array, cc_array + array_size, c_array);
}
result = t.elapsed();
cout << "std::copy<const char*, char*>: " << result << endl;
// cache load:
opt::detail::copier<false>::do_copy(cc_array, cc_array + array_size, c_array);
// time unoptimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::detail::copier<false>::do_copy(cc_array, cc_array + array_size, c_array);
}
result = t.elapsed();
cout << "standard \"unoptimised\" copy: " << result << endl << endl;
return 0;
}

191
examples/fill_example.cpp Normal file
View File

@ -0,0 +1,191 @@
/*
*
* Copyright (c) 1999
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* This file provides some example of type_traits usage -
* by "optimising" various algorithms:
*
* opt::fill - optimised for trivial copy/small types (cf std::fill)
*
*/
#include <iostream>
#include <typeinfo>
#include <algorithm>
#include <iterator>
#include <memory>
#include <boost/timer.hpp>
#include <boost/type_traits.hpp>
#include <boost/call_traits.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE) || (defined(std) && defined(__SGI_STL_PORT))
namespace std{ using :: memset; }
#endif
using std::cout;
using std::endl;
using std::cin;
namespace opt{
//
// fill
// same as std::fill, uses memset where appropriate, along with call_traits
// to "optimise" parameter passing.
//
namespace detail{
template <typename I, typename T>
void do_fill_(I first, I last, typename boost::call_traits<T>::param_type val)
{
while(first != last)
{
*first = val;
++first;
}
}
template <bool opt>
struct filler
{
template <typename I, typename T>
struct rebind
{
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
{ do_fill_<I,T>(first, last, val); }
};
};
template <>
struct filler<true>
{
template <typename I, typename T>
struct rebind
{
static void do_fill(I first, I last, T val)
{
std::memset(first, val, last-first);
}
};
};
}
template <class I, class T>
inline void fill(I first, I last, const T& val)
{
typedef detail::filler<
::boost::type_traits::ice_and<
::boost::is_pointer<I>::value,
::boost::is_arithmetic<T>::value,
(sizeof(T) == 1)
>::value> filler_t;
typedef typename filler_t:: template rebind<I,T> binder;
binder::do_fill(first, last, val);
}
}; // namespace opt
//
// define some global data:
//
const int array_size = 1000;
int i_array_[array_size] = {0,};
const int ci_array_[array_size] = {0,};
char c_array_[array_size] = {0,};
const char cc_array_[array_size] = { 0,};
//
// since arrays aren't iterators we define a set of pointer
// aliases into the arrays (otherwise the compiler is entitled
// to deduce the type passed to the template functions as
// T (&)[N] rather than T*).
int* i_array = i_array_;
const int* ci_array = ci_array_;
char* c_array = c_array_;
const char* cc_array = cc_array_;
const int iter_count = 1000000;
int main()
{
boost::timer t;
double result;
int i;
//
// test destroy_array,
// compare destruction time of an array of ints
// with unoptimised form.
//
cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
cout << "testing fill(char)...\n"
"[Some standard library versions may already perform this optimisation.]" << endl;
// cache load:
opt::fill(c_array, c_array + array_size, (char)3);
// time optimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::fill(c_array, c_array + array_size, (char)3);
}
result = t.elapsed();
cout << "opt::fill<char*, char>: " << result << endl;
// cache load:
std::fill(c_array, c_array + array_size, (char)3);
// time standard version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::fill(c_array, c_array + array_size, (char)3);
}
result = t.elapsed();
cout << "std::fill<char*, char>: " << result << endl << endl;
cout << "testing fill(int)...\n"
"[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl;
// cache load:
opt::fill(i_array, i_array + array_size, 3);
// timer optimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::fill(i_array, i_array + array_size, 3);
}
result = t.elapsed();
cout << "opt::fill<int*, int>: " << result << endl;
// cache load:
std::fill(i_array, i_array + array_size, 3);
// time standard version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::fill(i_array, i_array + array_size, 3);
}
result = t.elapsed();
cout << "std::fill<int*, int>: " << result << endl << endl;
return 0;
}

View File

@ -0,0 +1,110 @@
/*
*
* Copyright (c) 1999
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* This file provides some example of type_traits usage -
* by "optimising" various algorithms:
*
* opt::iter_swap - uses type_traits to determine whether the iterator is a proxy
* in which case it uses a "safe" approach, otherwise calls swap
* on the assumption that swap may be specialised for the pointed-to type.
*
*/
#include <iostream>
#include <typeinfo>
#include <algorithm>
#include <iterator>
#include <vector>
#include <memory>
#include <boost/type_traits.hpp>
using std::cout;
using std::endl;
using std::cin;
namespace opt{
//
// iter_swap:
// tests whether iterator is a proxying iterator or not, and
// uses optimal form accordingly:
//
namespace detail{
template <bool b>
struct swapper
{
template <typename I>
static void do_swap(I one, I two)
{
typedef typename std::iterator_traits<I>::value_type v_t;
v_t v = *one;
*one = *two;
*two = v;
}
};
#ifdef __GNUC__
using std::swap;
#endif
template <>
struct swapper<true>
{
template <typename I>
static void do_swap(I one, I two)
{
using std::swap;
swap(*one, *two);
}
};
}
template <typename I1, typename I2>
inline void iter_swap(I1 one, I2 two)
{
typedef typename std::iterator_traits<I1>::reference r1_t;
typedef typename std::iterator_traits<I2>::reference r2_t;
detail::swapper<
::boost::type_traits::ice_and<
::boost::is_reference<r1_t>::value,
::boost::is_reference<r2_t>::value,
::boost::is_same<r1_t, r2_t>::value
>::value>::do_swap(one, two);
}
}; // namespace opt
int main()
{
//
// testing iter_swap
// really just a check that it does in fact compile...
std::vector<int> v1;
v1.push_back(0);
v1.push_back(1);
std::vector<bool> v2;
v2.push_back(0);
v2.push_back(1);
opt::iter_swap(v1.begin(), v1.begin()+1);
opt::iter_swap(v2.begin(), v2.begin()+1);
cout << "Press any key to exit...";
cin.get();
}

View File

@ -0,0 +1,166 @@
/*
*
* Copyright (c) 1999
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* This file provides some example of type_traits usage -
* by "optimising" various algorithms:
*
* opt::destroy_array - an example of optimisation based upon omitted destructor calls
*
*/
#include <iostream>
#include <boost/timer.hpp>
#include <boost/type_traits.hpp>
using std::cout;
using std::endl;
using std::cin;
namespace opt{
//
// algorithm destroy_array:
// The reverse of std::unitialized_copy, takes a block of
// initialized memory and calls destructors on all objects therein.
//
namespace detail{
template <bool>
struct array_destroyer
{
template <class T>
static void destroy_array(T* i, T* j){ do_destroy_array(i, j); }
};
template <>
struct array_destroyer<true>
{
template <class T>
static void destroy_array(T*, T*){}
};
template <class T>
void do_destroy_array(T* first, T* last)
{
while(first != last)
{
first->~T();
++first;
}
}
}; // namespace detail
template <class T>
inline void destroy_array(T* p1, T* p2)
{
detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2);
}
//
// unoptimised versions of destroy_array:
//
template <class T>
void destroy_array1(T* first, T* last)
{
while(first != last)
{
first->~T();
++first;
}
}
template <class T>
void destroy_array2(T* first, T* last)
{
for(; first != last; ++first) first->~T();
}
} // namespace opt
//
// define some global data:
//
const int array_size = 1000;
int i_array[array_size] = {0,};
const int ci_array[array_size] = {0,};
char c_array[array_size] = {0,};
const char cc_array[array_size] = { 0,};
const int iter_count = 1000000;
int main()
{
boost::timer t;
double result;
int i;
//
// test destroy_array,
// compare destruction time of an array of ints
// with unoptimised form.
//
cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
cout << "testing destroy_array...\n"
"[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl;
// cache load:
opt::destroy_array(i_array, i_array + array_size);
// time optimised version:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::destroy_array(i_array, i_array + array_size);
}
result = t.elapsed();
cout << "destroy_array<int>: " << result << endl;
// cache load:
opt::destroy_array1(i_array, i_array + array_size);
// time unoptimised version #1:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::destroy_array1(i_array, i_array + array_size);
}
result = t.elapsed();
cout << "destroy_array<int>(unoptimised#1): " << result << endl;
// cache load:
opt::destroy_array2(i_array, i_array + array_size);
// time unoptimised version #2:
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::destroy_array2(i_array, i_array + array_size);
}
result = t.elapsed();
cout << "destroy_array<int>(unoptimised#2): " << result << endl << endl;
return 0;
}

View File

@ -10,14 +10,33 @@
#ifndef BOOST_TYPE_TRAITS_HPP
#define BOOST_TYPE_TRAITS_HPP
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#include <boost/type_traits/fwd.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/type_traits/arithmetic_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/type_traits/composite_traits.hpp>
#include <boost/type_traits/alignment_traits.hpp>
#include <boost/type_traits/object_traits.hpp>
#include <boost/type_traits/transform_traits.hpp>
#include <boost/type_traits/same_traits.hpp>
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#include <boost/detail/ob_type_traits.hpp>
#else
#include <boost/detail/type_traits.hpp>
#endif
/**************************************************************************/
//
// undefine helper macro's:
//
#undef BOOST_IS_CLASS
#undef BOOST_IS_ENUM
#undef BOOST_IS_UNION
#undef BOOST_IS_POD
#undef BOOST_IS_EMPTY
#undef BOOST_HAS_TRIVIAL_CONSTRUCTOR
#undef BOOST_HAS_TRIVIAL_COPY
#undef BOOST_HAS_TRIVIAL_ASSIGN
#undef BOOST_HAS_TRIVIAL_DESTRUCTOR
#endif // BOOST_TYPE_TRAITS_HPP

View File

@ -0,0 +1,82 @@
// (C) Copyright John Maddock 2000.
// 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.
//
// defines alignment_of:
#ifndef ALIGNMENT_TYPE_TRAITS_HPP
#define ALIGNMENT_TYPE_TRAITS_HPP
#include <cstdlib>
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
namespace boost{
//
// get the alignment of some arbitrary type:
namespace detail{
template <class T>
struct alignment_of_hack
{
char c;
T t;
alignment_of_hack();
};
template <unsigned A, unsigned S>
struct alignment_logic
{
BOOST_DECL_MC(std::size_t, value, A < S ? A : S);
};
} // namespace detail
template <class T>
struct alignment_of
{
BOOST_DECL_MC(std::size_t, value,
(::boost::detail::alignment_logic<
sizeof(detail::alignment_of_hack<T>) - sizeof(T),
sizeof(T)
>::value));
};
//
// references have to be treated specially, assume
// that a reference is just a special pointer:
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct alignment_of<T&>
{
public:
BOOST_DECL_MC(std::size_t, value, alignment_of<T*>::value);
};
#endif
//
// void has to be treated specially:
template <>
struct alignment_of<void>
{ BOOST_DECL_MC(std::size_t, value, 0); };
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct alignment_of<const void>
{ BOOST_DECL_MC(std::size_t, value, 0); };
template <>
struct alignment_of<volatile void>
{ BOOST_DECL_MC(std::size_t, value, 0); };
template <>
struct alignment_of<const volatile void>
{ BOOST_DECL_MC(std::size_t, value, 0); };
#endif
} // namespace boost
#endif // ALIGNMENT_TYPE_TRAITS_HPP

View File

@ -0,0 +1,262 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// defines traits classes for arithmetic types:
// is_void, is_integral, is_float, is_arithmetic, is_fundamental.
//
#ifndef ARITHMETIC_TYPE_TRAITS_HPP
#define ARITHMETIC_TYPE_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
namespace boost{
//* is a type T void - is_void<T>
template <typename T> struct is_void{ BOOST_DECL_MC(bool, value, false); };
template <> struct is_void<void>{ BOOST_DECL_MC(bool, value, true); };
//* is a type T an integral type described in the standard (3.9.1p3)
template <typename T> struct is_integral
{ BOOST_DECL_MC(bool, value, false); };
template <> struct is_integral<unsigned char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<unsigned short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<unsigned int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<unsigned long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<signed char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<signed short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<signed int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<signed long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<char>
{ BOOST_DECL_MC(bool, value, true); };
#ifndef BOOST_MSVC
template <> struct is_integral<wchar_t>
{ BOOST_DECL_MC(bool, value, true); };
#endif
template <> struct is_integral<bool>
{ BOOST_DECL_MC(bool, value, true); };
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
template <> struct is_integral<unsigned long long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<long long>
{ BOOST_DECL_MC(bool, value, true); };
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__)
template <> struct is_integral<unsigned __int64>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<__int64>
{ BOOST_DECL_MC(bool, value, true); };
#endif
//* is a type T a floating-point type described in the standard (3.9.1p8)
template <typename T> struct is_float
{ BOOST_DECL_MC(bool, value, false); };
template <> struct is_float<float>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<double>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<long double>
{ BOOST_DECL_MC(bool, value, true); };
//
// declare cv-qualified specialisations of these templates only
// if BOOST_NO_CV_SPECIALIZATIONS is not defined:
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <> struct is_void<const void>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_void<volatile void>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_void<const volatile void>
{ BOOST_DECL_MC(bool, value, true); };
#endif
#ifndef BOOST_NO_CV_SPECIALIZATIONS
// const-variations:
template <> struct is_integral<const unsigned char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const unsigned short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const unsigned int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const unsigned long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const signed char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const signed short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const signed int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const signed long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const char>
{ BOOST_DECL_MC(bool, value, true); };
#ifndef BOOST_MSVC
template <> struct is_integral<const wchar_t>
{ BOOST_DECL_MC(bool, value, true); };
#endif
template <> struct is_integral<const bool>
{ BOOST_DECL_MC(bool, value, true); };
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
template <> struct is_integral<const unsigned long long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const long long>
{ BOOST_DECL_MC(bool, value, true); };
#endif // ULLONG_MAX
#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__)
template <> struct is_integral<const unsigned __int64>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const __int64>
{ BOOST_DECL_MC(bool, value, true); };
#endif //__int64
template <> struct is_float<const float>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<const double>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<const long double>
{ BOOST_DECL_MC(bool, value, true); };
// volatile-variations:
template <> struct is_integral<volatile unsigned char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile unsigned short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile unsigned int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile unsigned long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile signed char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile signed short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile signed int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile signed long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile char>
{ BOOST_DECL_MC(bool, value, true); };
#ifndef BOOST_MSVC
template <> struct is_integral<volatile wchar_t>
{ BOOST_DECL_MC(bool, value, true); };
#endif
template <> struct is_integral<volatile bool>
{ BOOST_DECL_MC(bool, value, true); };
#ifdef ULLONG_MAX
template <> struct is_integral<volatile unsigned long long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile long long>
{ BOOST_DECL_MC(bool, value, true); };
#endif // ULLONG_MAX
#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__)
template <> struct is_integral<volatile unsigned __int64>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<volatile __int64>
{ BOOST_DECL_MC(bool, value, true); };
#endif //__int64
template <> struct is_float<volatile float>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<volatile double>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<volatile long double>
{ BOOST_DECL_MC(bool, value, true); };
// const-volatile-variations:
template <> struct is_integral<const volatile unsigned char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile unsigned short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile unsigned int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile unsigned long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile signed char>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile signed short>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile signed int>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile signed long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile char>
{ BOOST_DECL_MC(bool, value, true); };
#ifndef BOOST_MSVC
template <> struct is_integral<const volatile wchar_t>
{ BOOST_DECL_MC(bool, value, true); };
#endif
template <> struct is_integral<const volatile bool>
{ BOOST_DECL_MC(bool, value, true); };
#ifdef ULLONG_MAX
template <> struct is_integral<const volatile unsigned long long>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile long long>
{ BOOST_DECL_MC(bool, value, true); };
#endif // ULLONG_MAX
#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__)
template <> struct is_integral<const volatile unsigned __int64>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_integral<const volatile __int64>
{ BOOST_DECL_MC(bool, value, true); };
#endif //__int64
template <> struct is_float<const volatile float>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<const volatile double>
{ BOOST_DECL_MC(bool, value, true); };
template <> struct is_float<const volatile long double>
{ BOOST_DECL_MC(bool, value, true); };
#endif // BOOST_NO_CV_SPECIALIZATIONS
//* is a type T an arithmetic type described in the standard (3.9.1p8)
template <typename T>
struct is_arithmetic
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_integral<T>::value,
::boost::is_float<T>::value
>::value));
};
//* is a type T a fundamental type described in the standard (3.9.1)
template <typename T>
struct is_fundamental
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_arithmetic<T>::value,
::boost::is_void<T>::value
>::value));
};
} // namespace boost
#endif

View File

@ -0,0 +1,357 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// defines traits classes for composite types:
// is_array, is_pointer, is_reference, is_member_pointer, is_enum, is_union.
//
// Some workarounds in here use ideas suggested from "Generic<Programming>:
// Mappings between Types and Values"
// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
// Mat Marcus and Jesse Jones posted a version of is_pointer very similar to this one
// on the boost list (Copyright 2000 Adobe Systems Incorporated and others.
// All rights reserved.).
// Fixes for is_array are based on a newgroup posting by Jonathan Lundquist.
#ifndef COMPOSITE_TYPE_TRAITS_HPP
#define COMPOSITE_TYPE_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
#ifndef BOOST_CONVERSION_TYPE_TRAITS_HPP
#include <boost/type_traits/conversion_traits.hpp>
#endif
#ifndef CV_TYPE_TRAITS_HPP
#include <boost/type_traits/cv_traits.hpp>
#endif
#ifndef ARITHMETIC_TYPE_TRAITS_HPP
#include <boost/type_traits/arithmetic_traits.hpp>
#endif
namespace boost{
/**********************************************
*
* is_array
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T> struct is_array
{ BOOST_DECL_MC(bool, value, false); };
template <typename T, std::size_t N> struct is_array<T[N]>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, std::size_t N> struct is_array<const T[N]>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, std::size_t N> struct is_array<volatile T[N]>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, std::size_t N> struct is_array<const volatile T[N]>
{ BOOST_DECL_MC(bool, value, true); };
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace detail{
struct pointer_helper
{
pointer_helper(const volatile void*);
};
yes_type is_pointer_helper(pointer_helper);
no_type is_pointer_helper(...);
template <class T>
yes_type is_pointer_helper3(T (*)(void));
template <class T, class A1>
yes_type is_pointer_helper3(T (*)(A1));
template <class T, class A1, class A2>
yes_type is_pointer_helper3(T (*)(A1, A2));
template <class T, class A1, class A2, class A3>
yes_type is_pointer_helper3(T (*)(A1, A2, A3));
no_type is_pointer_helper3(...);
yes_type is_array_helper(const volatile void*, const volatile void*);
template <class T>
no_type is_array_helper(T*const volatile*, const volatile void*);
no_type is_array_helper(...);
} // namespace detail
template <typename T>
struct is_array
{
private:
static T t;
public:
BOOST_DECL_MC(bool, value, (1 == sizeof(detail::is_array_helper(&t, t)))
& !is_reference<T>::value
& !(1 == sizeof(detail::is_pointer_helper3(t))) );
};
template <>
struct is_array<void>
{
BOOST_DECL_MC(bool, value, false);
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_array<const void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_array<volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_array<const volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
#endif
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
/**********************************************
*
* is_pointer
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace detail{
template <typename T> struct is_pointer_helper
{ BOOST_DECL_MC(bool, value, false); };
template <typename T> struct is_pointer_helper<T*>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T> struct is_pointer_helper<T*const>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T> struct is_pointer_helper<T*volatile>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T> struct is_pointer_helper<T*const volatile>
{ BOOST_DECL_MC(bool, value, true); };
} // namespace detail
template <typename T> struct is_pointer
{ BOOST_DECL_MC(bool, value, (::boost::type_traits::ice_and< ::boost::detail::is_pointer_helper<T>::value, !::boost::is_member_pointer<T>::value>::value)); };
#else
template <typename T>
struct is_pointer
{
private:
static T t;
public:
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
!::boost::is_reference<T>::value,
!::boost::is_array<T>::value,
(::boost::type_traits::ice_or<
(1 == sizeof(detail::is_pointer_helper(t))),
(1 == sizeof(detail::is_pointer_helper3(t)))
>::value)
>::value ) );
};
template <>
struct is_pointer <void>
{
BOOST_DECL_MC(bool, value, false);
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_pointer <const void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_pointer <volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_pointer <const volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
#endif
#endif
/**********************************************
*
* is_reference
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T> struct is_reference
{ BOOST_DECL_MC(bool, value, false); };
template <typename T> struct is_reference<T&>
{ BOOST_DECL_MC(bool, value, true); };
#if defined(__BORLANDC__)
// these are illegal specialisations; cv-qualifies applied to
// references have no effect according to [8.3.2p1],
// C++ Builder requires them though as it treats cv-qualified
// references as distinct types...
template <typename T> struct is_reference<T&const>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T> struct is_reference<T&volatile>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T> struct is_reference<T&const volatile>
{ BOOST_DECL_MC(bool, value, true); };
#endif
#else
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4181)
# endif // BOOST_MSVC
template <typename T> struct is_reference
{
private:
typedef T const volatile cv_t;
public:
BOOST_DECL_MC(bool, value, (::boost::type_traits::ice_or<!::boost::is_const<cv_t>::value, !::boost::is_volatile<cv_t>::value>::value));
};
template <> struct is_reference<void>
{
BOOST_DECL_MC(bool, value, false);
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <> struct is_reference<const void>
{ BOOST_DECL_MC(bool, value, false); };
template <> struct is_reference<volatile void>
{ BOOST_DECL_MC(bool, value, false); };
template <> struct is_reference<const volatile void>
{ BOOST_DECL_MC(bool, value, false); };
#endif
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif // BOOST_MSVC
#endif
/**********************************************
*
* is_union
*
**********************************************/
template <typename T> struct is_union
{
private:
typedef typename remove_cv<T>::type cvt;
public:
BOOST_DECL_MC(bool, value, BOOST_IS_UNION(cvt));
};
/**********************************************
*
* is_enum
*
**********************************************/
namespace detail{
struct int_convertible
{
int_convertible(int);
};
} // namespace detail
#ifndef __BORLANDC__
template <typename T> struct is_enum
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
!::boost::is_arithmetic<T>::value,
!::boost::is_reference<T>::value,
::boost::is_convertible<T, detail::int_convertible>::value
>::value));
};
#else // __BORLANDC__
//
// buggy is_convertible prevents working
// implementation of is_enum:
template <typename T> struct is_enum
{
public:
BOOST_DECL_MC(bool, value, BOOST_IS_ENUM(T));
};
#endif
/**********************************************
*
* is_member_pointer
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T> struct is_member_pointer
{ BOOST_DECL_MC(bool, value, false); };
template <typename T, typename U> struct is_member_pointer<U T::*>
{ BOOST_DECL_MC(bool, value, true); };
#ifdef __GNUC__
// gcc workaround (JM 02 Oct 2000)
template <typename T, typename U> struct is_member_pointer<U (T::*)(void)>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, typename U, typename A1> struct is_member_pointer<U (T::*)(A1)>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, typename U, typename A1, typename A2> struct is_member_pointer<U (T::*)(A1, A2)>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, typename U, typename A1, typename A2, typename A3> struct is_member_pointer<U (T::*)(A1, A2, A3)>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, typename U, typename A1, typename A2, typename A3, typename A4> struct is_member_pointer<U (T::*)(A1, A2, A3, A4)>
{ BOOST_DECL_MC(bool, value, true); };
template <typename T, typename U, typename A1, typename A2, typename A3, typename A4, typename A5> struct is_member_pointer<U (T::*)(A1, A2, A3, A4, A5)>
{ BOOST_DECL_MC(bool, value, true); };
#endif
#else
namespace detail{
template <class T, class U>
yes_type is_member_pointer_helper(T (U::*));
template <class T, class U>
yes_type is_member_pointer_helper(T (U::*)(void));
template <class T, class U, class A1>
yes_type is_member_pointer_helper(T (U::*)(A1));
template <class T, class U, class A1, class A2>
yes_type is_member_pointer_helper(T (U::*)(A1, A2));
template <class T, class U, class A1, class A2, class A3>
yes_type is_member_pointer_helper(T (U::*)(A1, A2, A3));
template <class T, class U, class A1, class A2, class A3, class A4>
yes_type is_member_pointer_helper(T (U::*)(A1, A2, A3, A4));
template <class T, class U, class A1, class A2, class A3, class A4, class A5>
yes_type is_member_pointer_helper(T (U::*)(A1, A2, A3, A4, A5));
no_type is_member_pointer_helper(...);
}
template <typename T>
struct is_member_pointer
{
private:
static T t;
public:
BOOST_DECL_MC(bool, value, (1 == sizeof(detail::is_member_pointer_helper(t))) );
};
template <>
struct is_member_pointer<void>
{
BOOST_DECL_MC(bool, value, false);
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_member_pointer<const void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_member_pointer<volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_member_pointer<const volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
#endif
#endif
} // namespace boost
#endif // COMPOSITE_TYPE_TRAITS_HPP

View File

@ -0,0 +1,224 @@
// Copyright (C) 2000 John Maddock (john_maddock@compuserve.com)
// Copyright (C) 2000 Jeremy Siek (jsiek@lsc.nd.edu)
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
//
// Permission to copy and use 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.
#ifndef BOOST_CONVERSION_TYPE_TRAITS_HPP
#define BOOST_CONVERSION_TYPE_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
#ifndef ARITHMETIC_TYPE_TRAITS_HPP
#include <boost/type_traits/arithmetic_traits.hpp>
#endif
//
// is one type convertable to another?
//
// there are multiple versions of the is_convertible
// template, almost every compiler seems to require its
// own version.
//
// Thanks to Andrei Alexandrescu for the original version of the
// conversion detection technique!
//
namespace boost{
#ifdef BOOST_MSVC
//
// MS specific version:
//
namespace detail{
// This workaround is necessary to handle when From is void
// which is normally taken care of by the partial specialization
// of the is_convertible class.
using ::boost::type_traits::yes_type;
using ::boost::type_traits::no_type;
struct from_not_void_conversion {
template <class From, class To>
struct bind {
static no_type check(...);
static yes_type check(To);
public:
void foo(); // avoid warning about all members being private
static From from;
enum { exists = sizeof( check(from) ) == sizeof(yes_type) };
};
};
struct from_is_void_conversion {
template <class From, class To>
struct bind {
enum { exists = ::boost::is_void<To>::value };
};
};
template <class From>
struct conversion_helper {
typedef from_not_void_conversion type;
};
template <>
struct conversion_helper<void> {
typedef from_is_void_conversion type;
};
} // namespace detail
template <class From, class To>
struct is_convertible
{
typedef typename detail::conversion_helper<From>::type Selector;
typedef Selector::template bind<From,To> Conversion;
public:
enum { value = Conversion::exists };
};
#elif defined(__BORLANDC__)
//
// special version for Borland compilers
// this version breaks when used for some
// UDT conversions:
//
template <class From, class To>
struct is_convertible_helper
{
private:
// This workaround for Borland breaks the EDG C++ frontend,
// so we only use it for Borland.
template <class T>
struct checker
{
static type_traits::no_type check(...);
static type_traits::yes_type check(T);
};
static From from;
public:
static const bool value = sizeof( checker<To>::check(from) ) == sizeof(type_traits::yes_type);
void foo(); // avoid warning about all members being private
};
template <class From, class To>
struct is_convertible
{
private:
typedef is_convertible_helper<From, To> c_type;
enum{ v = c_type::value };
char force_it[v ? 1 : 2];
public:
static const bool value = is_convertible_helper<From, To>::value;
};
template <class From>
struct is_convertible<From, void>
{
static const bool value = false;
};
template <class To>
struct is_convertible<void, To>
{
static const bool value = false;
};
template <>
struct is_convertible<void, void>
{
static const bool value = true;
};
#elif defined(__GNUC__)
//
// special version for gcc compiler
//
namespace detail{
struct any_conversion
{
template <class T>
any_conversion(const T&);
};
template <class T>
struct checker
{
static boost::type_traits::no_type check(any_conversion ...);
static boost::type_traits::yes_type check(T, int);
};
} // namespace detail
template <class From, class To>
struct is_convertible
{
private:
static From from;
public:
static const bool value = sizeof( detail::checker<To>::check(from, 0) ) == sizeof(type_traits::yes_type);
void foo(); // avoid warning about all members being private
};
template <class From>
struct is_convertible<From, void>
{
static const bool value = false;
};
template <class To>
struct is_convertible<void, To>
{
static const bool value = false;
};
template <>
struct is_convertible<void, void>
{
static const bool value = true;
};
#else
template <class From, class To>
struct is_convertible
{
private:
static type_traits::no_type check(...);
static type_traits::yes_type check(To);
static From from;
public:
BOOST_DECL_MC(bool, value, sizeof( check(from) ) == sizeof(type_traits::yes_type));
void foo(); // avoid warning about all members being private
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class From>
struct is_convertible<From, void>
{
BOOST_DECL_MC(bool, value, false);
};
template <class To>
struct is_convertible<void, To>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_convertible<void, void>
{
BOOST_DECL_MC(bool, value, true);
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#endif // is_convertible
} // namespace boost
#endif // include guard

View File

@ -0,0 +1,214 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// defines traits classes for cv-qualified types:
// is_const, is_volatile, remove_const, remove_volatile, remove_cv.
//
#ifndef CV_TYPE_TRAITS_HPP
#define CV_TYPE_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
namespace boost{
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace detail{
//
// implementation helper:
//
template <class T>
struct cv_traits_imp{};
template <class T>
struct cv_traits_imp<T*>
{
BOOST_DECL_MC(bool, is_const, false);
BOOST_DECL_MC(bool, is_volatile, false);
typedef T unqualified_type;
};
template <class T>
struct cv_traits_imp<const T*>
{
BOOST_DECL_MC(bool, is_const, true);
BOOST_DECL_MC(bool, is_volatile, false);
typedef T unqualified_type;
};
template <class T>
struct cv_traits_imp<volatile T*>
{
BOOST_DECL_MC(bool, is_const, false);
BOOST_DECL_MC(bool, is_volatile, true);
typedef T unqualified_type;
};
template <class T>
struct cv_traits_imp<const volatile T*>
{
BOOST_DECL_MC(bool, is_const, true);
BOOST_DECL_MC(bool, is_volatile, true);
typedef T unqualified_type;
};
template <class T, bool is_vol>
struct remove_const_helper
{
typedef T type;
};
template <class T>
struct remove_const_helper<T, true>
{
typedef volatile T type;
};
template <class T, bool is_vol>
struct remove_volatile_helper
{
typedef T type;
};
template <class T>
struct remove_volatile_helper<T, true>
{
typedef const T type;
};
} // namespace detail
// * convert a type T to a non-volatile type - remove_volatile<T>
template <typename T>
struct remove_volatile
{
typedef typename detail::cv_traits_imp<T*>::unqualified_type uq_type;
typedef typename detail::remove_volatile_helper<uq_type, ::boost::is_const<T>::value>::type type;
};
template <typename T> struct remove_volatile<T&>{ typedef T& type; };
// * convert a type T to non-const type - remove_const<T>
template <typename T>
struct remove_const
{
typedef typename detail::cv_traits_imp<T*>::unqualified_type uq_type;
typedef typename detail::remove_const_helper<uq_type, ::boost::is_volatile<T>::value>::type type;
};
template <typename T> struct remove_const<T&>{ typedef T& type; };
// convert a type T to a non-cv-qualified type - remove_cv<T>
template <typename T>
struct remove_cv
{
typedef typename detail::cv_traits_imp<T*>::unqualified_type type;
};
template <typename T> struct remove_cv<T&>{ typedef T& type; };
//* is a type T declared const - is_const<T>
template <typename T>
struct is_const
{
BOOST_DECL_MC(bool, value, detail::cv_traits_imp<T*>::is_const);
};
//* is a type T declared volatile - is_volatile<T>
template <typename T>
struct is_volatile
{
BOOST_DECL_MC(bool, value, detail::cv_traits_imp<T*>::is_volatile);
};
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// The following three don't work:
template <typename T> struct remove_volatile{ typedef T type; };
template <typename T> struct remove_const{ typedef T type; };
template <typename T> struct remove_cv{ typedef T type; };
namespace detail{
using ::boost::type_traits::yes_type;
using ::boost::type_traits::no_type;
yes_type is_const_helper(const volatile void*);
no_type is_const_helper(volatile void *);
yes_type is_volatile_helper(const volatile void*);
no_type is_volatile_helper(const void *);
}
template <typename T>
struct is_const
{
private:
static T t;
public:
BOOST_DECL_MC(bool, value, (sizeof(detail::yes_type) == sizeof(detail::is_const_helper(&t))));
};
template <>
struct is_const<void>
{
BOOST_DECL_MC(bool, value, false);
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_const<const void>
{
BOOST_DECL_MC(bool, value, true);
};
template <>
struct is_const<volatile void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_const<const volatile void>
{
BOOST_DECL_MC(bool, value, true);
};
#endif
template <typename T>
struct is_volatile
{
private:
static T t;
public:
BOOST_DECL_MC(bool, value, (sizeof(detail::yes_type) == sizeof(detail::is_volatile_helper(&t))));
};
template <>
struct is_volatile<void>
{
BOOST_DECL_MC(bool, value, false);
};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <>
struct is_volatile<const void>
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct is_volatile<volatile void>
{
BOOST_DECL_MC(bool, value, true);
};
template <>
struct is_volatile<const volatile void>
{
BOOST_DECL_MC(bool, value, true);
};
#endif
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace boost
#endif // CV_TYPE_TRAITS_HPP

View File

@ -0,0 +1,140 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// forward declarations of type_traits classes
//
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#define BOOST_FWD_TYPE_TRAITS_HPP
#include <cstdlib>
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
//
// Helper macros for builtin compiler support.
// If your compiler has builtin support for any of the following
// traits concepts, then redefine the appropriate macros to pick
// up on the compiler support:
//
// (these should largely ignore cv-qualifiers)
// BOOST_IS_CLASS(T) should evaluate to true if T is a class or struct type
// BOOST_IS_ENUM(T) should evaluate to true if T is an enumerator type
// BOOST_IS_UNION(T) should evaluate to true if T is a union type
// BOOST_IS_POD(T) should evaluate to true if T is a POD type
// BOOST_IS_EMPTY(T) should evaluate to true if T is an empty struct or union
// BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
// BOOST_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
// BOOST_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
// BOOST_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
#define BOOST_IS_CLASS(T) false
#define BOOST_IS_ENUM(T) false
#define BOOST_IS_UNION(T) false
#define BOOST_IS_POD(T) false
#define BOOST_IS_EMPTY(T) false
#define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) false
#define BOOST_HAS_TRIVIAL_COPY(T) false
#define BOOST_HAS_TRIVIAL_ASSIGN(T) false
#define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) false
namespace boost{
//
// forward declare all type traits templates here
//
// conversion_traits.hpp:
template <class From, class To>
struct is_convertible;
// alignment_traits.hpp:
template <class T>
struct alignment_of;
// arithmetic_traits.hpp:
template <class T>
struct is_void;
template <class T>
struct is_integral;
template <class T>
struct is_float;
template <class T>
struct is_arithmetic;
template <class T>
struct is_fundamental;
// cv_traits.hpp:
template <class T>
struct is_const;
template <class T>
struct is_volatile;
template <class T>
struct remove_const;
template <class T>
struct remove_volatile;
template <class T>
struct remove_cv;
// composite_traits.hpp:
template <class T>
struct is_array;
template <class T>
struct is_pointer;
template <class T>
struct is_reference;
template <class T>
struct is_member_pointer;
template <class T>
struct is_enum;
template <class T>
struct is_union;
// object_traits.hpp:
template <class T>
struct is_object;
template <class T>
struct is_scalar;
template <class T>
struct is_class;
template <class T>
struct is_compound;
template <class T>
struct is_POD;
template <class T>
struct has_trivial_constructor;
template <class T>
struct has_trivial_copy;
template <class T>
struct has_trivial_assign;
template <class T>
struct has_trivial_destructor;
template <class T>
struct is_empty;
// transform_traits.hpp:
template <class T>
struct remove_reference;
template <class T>
struct add_reference;
template <class T>
struct remove_bounds;
template <class T>
struct remove_pointer;
template <class T>
struct add_pointer;
// same_traits.hpp:
template <class T, class U>
struct is_same;
} // namespace boost
#endif // BOOST_FWD_TYPE_TRAITS_HPP

View File

@ -0,0 +1,76 @@
// (C) Copyright John Maddock and Steve Cleary 2000.
// 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 for most recent version including documentation.
//
// macros and helpers for working with integral-constant-expressions.
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#define BOOST_ICE_TYPE_TRAITS_HPP
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
#define BOOST_DECL_MC(type, name, value) enum{name = value }
#define BOOST_DECL_MC2(type, name, v1, v2) enum{name = v1,v2 }
#else
#define BOOST_DECL_MC(type, name, value) static const type name = value
#define BOOST_DECL_MC2(type, name, v1, v2) static const type name = v1,v2
#endif
namespace boost{
namespace type_traits{
typedef char yes_type;
typedef double no_type;
template <bool b>
struct ice_not
{ BOOST_DECL_MC(bool, value, true); };
template <>
struct ice_not<true>
{ BOOST_DECL_MC(bool, value, false); };
template <bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false, bool b6 = false, bool b7 = false>
struct ice_or;
template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7>
struct ice_or
{
BOOST_DECL_MC(bool, value, true);
};
template <>
struct ice_or<false, false, false, false, false, false, false>
{
BOOST_DECL_MC(bool, value, false);
};
template <bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, bool b6 = true, bool b7 = true>
struct ice_and;
template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7>
struct ice_and
{
BOOST_DECL_MC(bool, value, false);
};
template <>
struct ice_and<true, true, true, true, true, true, true>
{
BOOST_DECL_MC(bool, value, true);
};
} // namespace type_traits
} // namespace boost
#endif // BOOST_ICE_TYPE_TRAITS_HPP

View File

@ -0,0 +1,318 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// defines object traits classes:
// is_object, is_scalar, is_class, is_compound, is_POD,
// has_trivial_constructor, has_trivial_copy, has_trivial_assign,
// has_trivial_destructor, is_empty.
//
#ifndef OBJECT_TYPE_TRAITS_HPP
#define OBJECT_TYPE_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
#ifndef COMPOSITE_TYPE_TRAITS_HPP
#include <boost/type_traits/composite_traits.hpp>
#endif
#ifndef ARITHMETIC_TYPE_TRAITS_HPP
#include <boost/type_traits/arithmetic_traits.hpp>
#endif
namespace boost{
/**********************************************
*
* is_object
*
**********************************************/
template <typename T>
struct is_object
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
!::boost::is_reference<T>::value,
!::boost::is_void<T>::value
>::value));
};
/**********************************************
*
* is_scalar
*
**********************************************/
template <typename T>
struct is_scalar
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_arithmetic<T>::value,
::boost::is_enum<T>::value,
::boost::is_pointer<T>::value,
::boost::is_member_pointer<T>::value
>::value));
};
/**********************************************
*
* is_class
*
**********************************************/
template <typename T>
struct is_class
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
!::boost::is_union<T>::value,
!::boost::is_scalar<T>::value,
!::boost::is_array<T>::value,
!::boost::is_reference<T>::value,
!::boost::is_void<T>::value
>::value));
};
/**********************************************
*
* is_compound
*
**********************************************/
template <typename T> struct is_compound
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_array<T>::value,
::boost::is_pointer<T>::value,
::boost::is_reference<T>::value,
::boost::is_class<T>::value,
::boost::is_union<T>::value,
::boost::is_enum<T>::value,
::boost::is_member_pointer<T>::value
>::value));
};
/**********************************************
*
* is_POD
*
**********************************************/
template <typename T> struct is_POD
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_scalar<T>::value,
::boost::is_void<T>::value,
BOOST_IS_POD(T)
>::value));
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T, std::size_t sz>
struct is_POD<T[sz]>
{
BOOST_DECL_MC(bool, value, ::boost::is_POD<T>::value);
};
#endif
/**********************************************
*
* has_trivial_constructor
*
**********************************************/
template <typename T>
struct has_trivial_constructor
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_POD<T>::value,
BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
>::value));
};
/**********************************************
*
* has_trivial_copy
*
**********************************************/
template <typename T>
struct has_trivial_copy
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
::boost::type_traits::ice_or<
::boost::is_POD<T>::value,
BOOST_HAS_TRIVIAL_COPY(T)
>::value,
!::boost::is_volatile<T>::value
>::value));
};
/**********************************************
*
* has_trivial_assign
*
**********************************************/
template <typename T>
struct has_trivial_assign
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
::boost::type_traits::ice_or<
::boost::is_POD<T>::value,
BOOST_HAS_TRIVIAL_ASSIGN(T)
>::value,
!::boost::is_const<T>::value,
!::boost::is_volatile<T>::value
>::value));
};
/**********************************************
*
* has_trivial_destructor
*
**********************************************/
template <typename T>
struct has_trivial_destructor
{
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::is_POD<T>::value,
BOOST_HAS_TRIVIAL_DESTRUCTOR(T)
>::value));
};
/**********************************************
*
* is_empty
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace detail{
template <typename T>
struct empty_helper_t1 : public T
{
#ifdef __MWERKS__
empty_helper_t1(); // hh compiler bug workaround
#endif
int i[256];
};
struct empty_helper_t2 { int i[256]; };
template <typename T, bool b, bool b2>
struct empty_helper{ BOOST_DECL_MC(bool, value, false); };
template <typename T>
struct empty_helper<T, true, false>
{
BOOST_DECL_MC(bool, value,
(sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2)));
};
}
template <typename T>
struct is_empty
{
private:
typedef typename remove_cv<T>::type cvt;
public:
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<
::boost::detail::empty_helper<T,
::boost::is_class<T>::value ,
::boost::is_convertible<T,int>::value
>::value,
BOOST_IS_EMPTY(cvt)
>::value));
};
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
namespace detail{
template <typename T>
struct empty_helper_t1 : public T
{
int i[256];
};
struct empty_helper_t2 { int i[256]; };
template <typename T>
struct empty_helper_base
{
enum{ value = (sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2)) };
};
template <typename T>
struct empty_helper_nonbase
{
enum{ value = false };
};
template <bool base>
struct empty_helper_chooser
{
template <class T>
struct rebind
{
typedef empty_helper_nonbase<T> type;
};
};
template <>
struct empty_helper_chooser<true>
{
template <class T>
struct rebind
{
typedef empty_helper_base<T> type;
};
};
} // namespace detail
template <typename T>
struct is_empty
{
private:
typedef ::boost::detail::empty_helper_chooser<
::boost::type_traits::ice_and<
!::boost::is_convertible<T,int>::value,
!::boost::is_convertible<T,double>::value,
!::boost::is_pointer<T>::value,
!::boost::is_member_pointer<T>::value,
!::boost::is_array<T>::value,
!::boost::is_void<T>::value,
!::boost::is_convertible<T, const volatile void*>::value
>::value> chooser;
typedef typename chooser::template rebind<T> bound_type;
typedef typename bound_type::type eh_type;
public:
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_or<eh_type::value, BOOST_IS_EMPTY(T)>::value));
};
#else
template <typename T> struct is_empty
{ enum{ value = BOOST_IS_EMPTY(T) }; };
#endif // defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace boost
#endif // OBJECT_TYPE_TRAITS_HPP

View File

@ -0,0 +1,90 @@
// (C) Copyright Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// defines is_same:
#ifndef SAME_TRAITS_HPP
#define SAME_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
#if !defined(COMPOSITE_TYPE_TRAITS_HPP) && defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC)
#include <boost/type_traits/composite_traits.hpp>
#endif
namespace boost{
/**********************************************
*
* is_same
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T, typename U>
struct is_same
{ BOOST_DECL_MC(bool, value, false); };
template <typename T>
struct is_same<T, T>
{ BOOST_DECL_MC(bool, value, true); };
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#ifdef BOOST_MSVC
namespace detail{
template<class T1>
struct is_same_part_1 {
template<class T2> struct part_2 { enum { value = false }; };
template<> struct part_2<T1> { enum { value = true }; };
};
} // namespace detail
template<class T1, class T2>
struct is_same : detail::is_same_part_1<T1>::template part_2<T2> {};
#else // BOOST_MSVC
namespace detail{
template <class T>
::boost::type_traits::yes_type is_same_helper(T*, T*);
::boost::type_traits::no_type is_same_helper(...);
}
template <typename T, typename U>
struct is_same
{
private:
static T t;
static U u;
public:
BOOST_DECL_MC(bool, value,
(::boost::type_traits::ice_and<
(sizeof(type_traits::yes_type) == sizeof(detail::is_same_helper(&t,&u))),
(::boost::is_reference<T>::value == ::boost::is_reference<U>::value),
(sizeof(T) == sizeof(U))
>::value));
};
#endif // BOOST_MSVC
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace boost
#endif // SAME_TRAITS_HPP

View File

@ -0,0 +1,187 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// 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 for most recent version including documentation.
//
// defines traits classes for transforming one type to another:
// remove_reference, add_reference, remove_bounds, remove_pointer.
//
#ifndef TRANSFORM_TRAITS_HPP
#define TRANSFORM_TRAITS_HPP
#ifndef BOOST_ICE_TYPE_TRAITS_HPP
#include <boost/type_traits/ice.hpp>
#endif
#ifndef BOOST_FWD_TYPE_TRAITS_HPP
#include <boost/type_traits/fwd.hpp>
#endif
#if !defined(COMPOSITE_TYPE_TRAITS_HPP) && defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
#include <boost/type_traits/composite_traits.hpp>
#endif
namespace boost{
/**********************************************
*
* remove_reference
*
**********************************************/
template <typename T>
struct remove_reference
{ typedef T type; };
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T>
struct remove_reference<T&>
{ typedef T type; };
#endif
#if defined(__BORLANDC__) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
// these are illegal specialisations; cv-qualifies applied to
// references have no effect according to [8.3.2p1],
// C++ Builder requires them though as it treats cv-qualified
// references as distinct types...
template <typename T>
struct remove_reference<T&const>
{ typedef T type; };
template <typename T>
struct remove_reference<T&volatile>
{ typedef T type; };
template <typename T>
struct remove_reference<T&const volatile>
{ typedef T type; };
#endif
/**********************************************
*
* add_reference
*
**********************************************/
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T>
struct add_reference
{ typedef T& type; };
template <typename T>
struct add_reference<T&>
{ typedef T& type; };
#elif defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
namespace detail{
template <bool>
struct reference_adder
{
template <class T>
struct rebind
{
typedef T& type;
};
};
template <>
struct reference_adder<true>
{
template <class T>
struct rebind
{
typedef T type;
};
};
} // namespace detail
template <typename T>
struct add_reference
{
private:
typedef typename detail::reference_adder< ::boost::is_reference<T>::value>::template rebind<T> binder;
public:
typedef typename binder::type type;
};
#else
template <typename T>
struct add_reference
{ typedef T& type; };
#endif
/**********************************************
*
* remove_bounds
*
**********************************************/
template <typename T>
struct remove_bounds
{ typedef T type; };
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T, std::size_t N>
struct remove_bounds<T[N]>
{ typedef T type; };
template <typename T, std::size_t N>
struct remove_bounds<const T[N]>
{ typedef const T type; };
template <typename T, std::size_t N>
struct remove_bounds<volatile T[N]>
{ typedef volatile T type; };
template <typename T, std::size_t N>
struct remove_bounds<const volatile T[N]>
{ typedef const volatile T type; };
#endif
/**********************************************
*
* remove_pointer
*
**********************************************/
template <typename T>
struct remove_pointer
{ typedef T type; };
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T>
struct remove_pointer<T*>
{ typedef T type; };
template <typename T>
struct remove_pointer<T*const>
{ typedef T type; };
template <typename T>
struct remove_pointer<T*volatile>
{ typedef T type; };
template <typename T>
struct remove_pointer<T*const volatile>
{ typedef T type; };
#endif
/**********************************************
*
* add_pointer
*
**********************************************/
template <typename T>
struct add_pointer
{
private:
typedef typename remove_reference<T>::type no_ref_type;
typedef typename remove_bounds<no_ref_type>::type no_b_type;
public:
typedef no_b_type* type;
};
} // namespace boost
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
//
// if there is no partial specialisation support
// include a bunch of full specialisations as a workaround:
//
#include <boost/type_traits/transform_traits_spec.hpp>
#else
#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(x)
#endif
#endif // TRANSFORM_TRAITS_HPP

View File

@ -0,0 +1,74 @@
// Copyright (c) 2001 Aleksey Gurtovoy.
// 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.
#ifndef BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP
#define BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP
#ifndef TRANSFORM_TRAITS_HPP
#include <boost/type_traits/transform_traits.hpp>
#endif
#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_CONST_VOLATILE_RANK1(T) \
template<> struct remove_const<T const> { typedef T type; }; \
template<> struct remove_const<T const volatile> { typedef T volatile type; }; \
template<> struct remove_volatile<T volatile> { typedef T type; }; \
template<> struct remove_volatile<T const volatile> { typedef T const type; }; \
template<> struct remove_cv<T const> { typedef T type; }; \
template<> struct remove_cv<T volatile> { typedef T type; }; \
template<> struct remove_cv<T const volatile> { typedef T type; }; \
/**/
#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T) \
template<> struct remove_pointer<T*> { typedef T type; }; \
template<> struct remove_reference<T&> { typedef T type; }; \
/**/
#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_2(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T const) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T volatile) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T const volatile) \
/**/
#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_2(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_CONST_VOLATILE_RANK1(T) \
/**/
#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T*) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T const*) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T volatile*) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T const volatile*) \
/**/
#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(T) \
namespace boost { \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T*) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T const*) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T volatile*) \
BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T const volatile*) \
} \
/**/
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(char)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed char)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned char)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed short)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned short)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed int)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned int)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed long)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned long)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(float)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(double)
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(long double)
#endif // BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP

View File

@ -0,0 +1,361 @@
// (C) Copyright John Maddock 2000. 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.
// common test code for type-traits tests
// WARNING: contains code as well as declarations!
#ifndef BOOST_TYPE_TRAITS_TEST_HPP
#define BOOST_TYPE_TRAITS_TEST_HPP
#include <iostream>
#include <typeinfo>
//
// define tests here
unsigned failures = 0;
unsigned test_count = 0;
//
// This must get defined within the test file.
// All compilers have bugs, set this to the number of
// regressions *expected* from a given compiler,
// if there are no workarounds for the bugs, *and*
// the regressions have been investigated.
//
extern unsigned int expected_failures;
//
// proc check_result()
// Checks that there were no regressions:
//
int check_result(int argc, char** argv)
{
std::cout << test_count << " tests completed, "
<< failures << " failures found, "
<< expected_failures << " failures expected from this compiler." << std::endl;
if((argc == 2)
&& (argv[1][0] == '-')
&& (argv[1][1] == 'a')
&& (argv[1][2] == 0))
{
std::cout << "Press any key to continue...";
std::cin.get();
}
return (failures == expected_failures) ? 0 : failures;
}
//
// this one is to verify that a constant is indeed a
// constant-integral-expression:
//
template <bool>
struct checker
{
static void check(bool, bool, const char*, bool){ ++test_count; }
};
template <>
struct checker<false>
{
static void check(bool o, bool n, const char* name, bool soft)
{
++test_count;
++failures;
// if this is a soft test, then failure is expected,
// or may depend upon factors outside our control
// (like compiler options)...
if(soft)++expected_failures;
std::cout << "checking value of " << name << "...failed" << std::endl;
std::cout << "\tfound: " << n << " expected " << o << std::endl;
}
};
template <class T, class U>
struct type_checker
{
static void check(const char* TT, const char* TU, const char* expression)
{
++test_count;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
if((typeid(T) != typeid(U))
|| (::boost::is_reference<T>::value != ::boost::is_reference<U>::value)
|| (::boost::is_const<T>::value != ::boost::is_const<U>::value)
|| (::boost::is_volatile<T>::value != ::boost::is_volatile<U>::value))
{
#endif
++failures;
std::cout << "checking type of " << expression << "...failed" << std::endl;
std::cout << " expected type was " << TT << std::endl;
std::cout << " typeid(" << TT << ") was: " << typeid(T).name() << std::endl;
std::cout << " typeid(" << TU << ") was: " << typeid(U).name() << std::endl;
std::cout << " In template class " << typeid(type_checker<T,U>).name() << std::endl;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
}
#endif
}
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct type_checker<T,T>
{
static void check(const char*, const char*, const char*)
{
++test_count;
}
};
#endif
#define value_test(v, x) checker<(v == x)>::check(v, x, #x, false);
#define soft_value_test(v, x) checker<(v == x)>::check(v, x, #x, true);
#define value_fail(v, x) \
++test_count; \
++failures; \
std::cout << "checking value of " << #x << "...failed" << std::endl; \
std::cout << " " #x " does not compile on this compiler" << std::endl;
#define type_test(v, x) type_checker<v,x>::check(#v, #x, #x);
#define type_test3(v, x, z) type_checker<v,x,z>::check(#v, #x "," #z, #x "," #z);
#ifndef SHORT_TRANSFORM_TEST
#define transform_check(name, from_suffix, to_suffix)\
type_test(bool to_suffix, name<bool from_suffix>::type);\
type_test(char to_suffix, name<char from_suffix>::type);\
type_test(wchar_t to_suffix, name<wchar_t from_suffix>::type);\
type_test(signed char to_suffix, name<signed char from_suffix>::type);\
type_test(unsigned char to_suffix, name<unsigned char from_suffix>::type);\
type_test(short to_suffix, name<short from_suffix>::type);\
type_test(unsigned short to_suffix, name<unsigned short from_suffix>::type);\
type_test(int to_suffix, name<int from_suffix>::type);\
type_test(unsigned int to_suffix, name<unsigned int from_suffix>::type);\
type_test(long to_suffix, name<long from_suffix>::type);\
type_test(unsigned long to_suffix, name<unsigned long from_suffix>::type);\
type_test(float to_suffix, name<float from_suffix>::type);\
type_test(long double to_suffix, name<long double from_suffix>::type);\
type_test(double to_suffix, name<double from_suffix>::type);\
type_test(UDT to_suffix, name<UDT from_suffix>::type);\
type_test(enum1 to_suffix, name<enum1 from_suffix>::type);
#else
#define transform_check(name, from_suffix, to_suffix)\
type_test(int to_suffix, name<int from_suffix>::type);\
type_test(UDT to_suffix, name<UDT from_suffix>::type);\
type_test(enum1 to_suffix, name<enum1 from_suffix>::type);
#endif
#define boost_dummy_macro_param
template <class T>
struct test_align
{
struct padded
{
char c;
T t;
};
static void do_it()
{
padded p;
unsigned a = reinterpret_cast<char*>(&(p.t)) - reinterpret_cast<char*>(&p);
++test_count;
// only fail if we do not have a multiple of the actual value:
if((a > ::boost::alignment_of<T>::value) || (a % ::boost::alignment_of<T>::value))
{
++failures;
std::cout << "checking value of " << typeid(boost::alignment_of<T>).name() << "...failed" << std::endl;
std::cout << "\tfound: " << boost::alignment_of<T>::value << " expected " << a << std::endl;
}
// suppress warnings about unused variables:
(void)p;
(void)a;
}
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct test_align<T&>
{
static void do_it()
{
//
// we can't do the usual test because we can't take the address
// of a reference, so check that the result is the same as for a
// pointer type instead:
unsigned a = boost::alignment_of<T*>::value;
++test_count;
if(a != boost::alignment_of<T&>::value)
{
++failures;
std::cout << "checking value of " << typeid(boost::alignment_of<T&>).name() << "...failed" << std::endl;
std::cout << "\tfound: " << boost::alignment_of<T&>::value << " expected " << a << std::endl;
}
}
};
#endif
#define align_test(T) test_align<T>::do_it()
//
// the following code allows us to test that a particular
// template functions correctly when instanciated inside another template
// (some bugs only show up in that situation). For each template
// we declare one NESTED_DECL(classname) that sets up the template class
// and multiple NESTED_TEST(classname, template-arg) declarations, to carry
// the actual tests:
template <bool b>
struct nested_test
{
typedef nested_test type;
bool run_time_value;
const char* what;
nested_test(bool b2, const char* w) : run_time_value(b2), what(w) { check(); }
void check()
{
++test_count;
if(b != run_time_value)
{
++failures;
std::cerr << "Mismatch between runtime and compile time values in " << what << std::endl;
}
}
};
#define NESTED_DECL(what)\
template <class T> \
struct BOOST_TT_JOIN(nested_tester_,what){\
nested_test< (0 != ::boost::what<T>::value)> tester;\
BOOST_TT_JOIN(nested_tester_,what)(const char* s) : tester(::boost::what<T>::value, s){}\
};
#define NESTED_TEST(what, with)\
{BOOST_TT_JOIN(nested_tester_,what)<with> check(#what "<" #with ">"); (void)check;}
#define BOOST_TT_JOIN( X, Y ) BOOST_DO_TT_JOIN( X, Y )
#define BOOST_DO_TT_JOIN( X, Y ) X##Y
//
// define some types to test with:
//
enum enum_UDT{ one, two, three };
struct UDT
{
UDT(){};
~UDT(){};
UDT(const UDT&);
UDT& operator=(const UDT&);
int i;
void f1();
int f2();
int f3(int);
int f4(int, float);
};
typedef void(*f1)();
typedef int(*f2)(int);
typedef int(*f3)(int, bool);
typedef void (UDT::*mf1)();
typedef int (UDT::*mf2)();
typedef int (UDT::*mf3)(int);
typedef int (UDT::*mf4)(int, float);
typedef int (UDT::*mp);
// cv-qualifiers applied to reference types should have no effect
// declare these here for later use with is_reference and remove_reference:
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4181)
# endif // BOOST_MSVC
typedef int& r_type;
typedef const r_type cr_type;
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif // BOOST_MSVC
struct POD_UDT { int x; };
struct empty_UDT{ ~empty_UDT(){}; };
struct empty_POD_UDT{};
union union_UDT
{
int x;
double y;
~union_UDT();
};
union POD_union_UDT
{
int x;
double y;
};
union empty_union_UDT
{
~empty_union_UDT();
};
union empty_POD_union_UDT{};
class Base { };
class Deriverd : public Base { };
class NonDerived { };
enum enum1
{
one_,two_
};
enum enum2
{
three_,four_
};
struct VB
{
virtual ~VB(){};
};
struct VD : VB
{
~VD(){};
};
//
// struct non_pointer:
// used to verify that is_pointer does not return
// true for class types that implement operator void*()
//
struct non_pointer
{
operator void*(){return this;}
};
struct non_int_pointer
{
int i;
operator int*(){return &i;}
};
struct int_constructible
{
int_constructible(int);
};
struct int_convertible
{
operator int();
};
//
// struct non_empty:
// used to verify that is_empty does not emit
// spurious warnings or errors.
//
struct non_empty : boost::noncopyable
{
int i;
};
#endif // BOOST_TYPE_TRAITS_TEST_HPP

1202
index.htm Normal file

File diff suppressed because it is too large Load Diff

44
tests/alignment_test.cpp Normal file
View File

@ -0,0 +1,44 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/alignment_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"
NESTED_DECL(alignment_of)
int main(int argc, char* argv[])
{
NESTED_TEST(alignment_of, int)
NESTED_TEST(alignment_of, int_constructible)
align_test(int);
align_test(char);
align_test(double);
align_test(int[4]);
align_test(int(*)(int));
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
align_test(char&);
align_test(char (&)(int));
align_test(char(&)[4]);
#endif
align_test(int*);
//align_test(const int);
align_test(VB);
align_test(VD);
value_test(0, ::boost::alignment_of<void>::value);
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
unsigned int expected_failures = 0;

View File

@ -0,0 +1,197 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/arithmetic_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"
NESTED_DECL(is_void)
NESTED_DECL(is_integral)
NESTED_DECL(is_float)
NESTED_DECL(is_arithmetic)
NESTED_DECL(is_fundamental)
int main(int argc, char* argv[])
{
NESTED_TEST(is_void, void)
NESTED_TEST(is_void, int)
NESTED_TEST(is_integral, int)
NESTED_TEST(is_integral, float)
NESTED_TEST(is_float, void)
NESTED_TEST(is_float, double)
NESTED_TEST(is_arithmetic, void)
NESTED_TEST(is_arithmetic, int)
NESTED_TEST(is_fundamental, UDT)
NESTED_TEST(is_fundamental, int)
value_test(true, boost::is_void<void>::value)
value_test(true, boost::is_void<const void>::value)
value_test(true, boost::is_void<volatile void>::value)
value_test(true, boost::is_void<const volatile void>::value)
value_test(false, boost::is_void<int>::value)
value_test(false, boost::is_integral<UDT>::value)
value_test(false, boost::is_integral<void>::value)
value_test(true, boost::is_integral<bool>::value)
value_test(true, boost::is_integral<char>::value)
value_test(true, boost::is_integral<signed char>::value)
value_test(true, boost::is_integral<unsigned char>::value)
value_test(true, boost::is_integral<wchar_t>::value)
value_test(true, boost::is_integral<short>::value)
value_test(true, boost::is_integral<unsigned short>::value)
value_test(true, boost::is_integral<int>::value)
value_test(true, boost::is_integral<unsigned int>::value)
value_test(true, boost::is_integral<long>::value)
value_test(true, boost::is_integral<unsigned long>::value)
value_test(false, boost::is_integral<float>::value)
value_test(false, boost::is_integral<double>::value)
value_test(false, boost::is_integral<long double>::value)
#ifdef ULLONG_MAX
value_test(true, boost::is_integral<long long>::value)
value_test(true, boost::is_integral<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, boost::is_integral<__int64>::value)
value_test(true, boost::is_integral<unsigned __int64>::value)
#endif
//const qualified ints:
value_test(true, boost::is_integral<const bool>::value)
value_test(true, boost::is_integral<const char>::value)
value_test(true, boost::is_integral<const signed char>::value)
value_test(true, boost::is_integral<const unsigned char>::value)
value_test(true, boost::is_integral<const wchar_t>::value)
value_test(true, boost::is_integral<const short>::value)
value_test(true, boost::is_integral<const unsigned short>::value)
value_test(true, boost::is_integral<const int>::value)
value_test(true, boost::is_integral<const unsigned int>::value)
value_test(true, boost::is_integral<const long>::value)
value_test(true, boost::is_integral<const unsigned long>::value)
#ifdef ULLONG_MAX
value_test(true, boost::is_integral<const long long>::value)
value_test(true, boost::is_integral<const unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, boost::is_integral<const __int64>::value)
value_test(true, boost::is_integral<const unsigned __int64>::value)
#endif
// volatile qualified ints:
value_test(true, boost::is_integral<volatile bool>::value)
value_test(true, boost::is_integral<volatile char>::value)
value_test(true, boost::is_integral<volatile signed char>::value)
value_test(true, boost::is_integral<volatile unsigned char>::value)
value_test(true, boost::is_integral<volatile wchar_t>::value)
value_test(true, boost::is_integral<volatile short>::value)
value_test(true, boost::is_integral<volatile unsigned short>::value)
value_test(true, boost::is_integral<volatile int>::value)
value_test(true, boost::is_integral<volatile unsigned int>::value)
value_test(true, boost::is_integral<volatile long>::value)
value_test(true, boost::is_integral<volatile unsigned long>::value)
#ifdef ULLONG_MAX
value_test(true, boost::is_integral<volatile long long>::value)
value_test(true, boost::is_integral<volatile unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, boost::is_integral<volatile __int64>::value)
value_test(true, boost::is_integral<volatile unsigned __int64>::value)
#endif
//const qualified ints:
value_test(true, boost::is_integral<const volatile bool>::value)
value_test(true, boost::is_integral<const volatile char>::value)
value_test(true, boost::is_integral<const volatile signed char>::value)
value_test(true, boost::is_integral<const volatile unsigned char>::value)
value_test(true, boost::is_integral<const volatile wchar_t>::value)
value_test(true, boost::is_integral<const volatile short>::value)
value_test(true, boost::is_integral<const volatile unsigned short>::value)
value_test(true, boost::is_integral<const volatile int>::value)
value_test(true, boost::is_integral<const volatile unsigned int>::value)
value_test(true, boost::is_integral<const volatile long>::value)
value_test(true, boost::is_integral<const volatile unsigned long>::value)
#ifdef ULLONG_MAX
value_test(true, boost::is_integral<const volatile long long>::value)
value_test(true, boost::is_integral<const volatile unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, boost::is_integral<const volatile __int64>::value)
value_test(true, boost::is_integral<const volatile unsigned __int64>::value)
#endif
value_test(true, boost::is_float<const volatile float>::value)
value_test(true, boost::is_float<const volatile double>::value)
value_test(true, boost::is_float<const volatile long double>::value)
value_test(true, boost::is_float<volatile float>::value)
value_test(true, boost::is_float<volatile double>::value)
value_test(true, boost::is_float<volatile long double>::value)
value_test(true, boost::is_float<const float>::value)
value_test(true, boost::is_float<const double>::value)
value_test(true, boost::is_float<const long double>::value)
value_test(true, boost::is_float<float>::value)
value_test(true, boost::is_float<double>::value)
value_test(true, boost::is_float<long double>::value)
value_test(false, boost::is_float<int>::value)
value_test(false, boost::is_float<void>::value)
value_test(false, boost::is_float<UDT>::value)
value_test(false, boost::is_arithmetic<UDT>::value)
value_test(false, boost::is_arithmetic<void>::value)
value_test(true, boost::is_arithmetic<bool>::value)
value_test(true, boost::is_arithmetic<char>::value)
value_test(true, boost::is_arithmetic<signed char>::value)
value_test(true, boost::is_arithmetic<unsigned char>::value)
value_test(true, boost::is_arithmetic<wchar_t>::value)
value_test(true, boost::is_arithmetic<short>::value)
value_test(true, boost::is_arithmetic<unsigned short>::value)
value_test(true, boost::is_arithmetic<int>::value)
value_test(true, boost::is_arithmetic<unsigned int>::value)
value_test(true, boost::is_arithmetic<long>::value)
value_test(true, boost::is_arithmetic<unsigned long>::value)
value_test(true, boost::is_arithmetic<float>::value)
value_test(true, boost::is_arithmetic<double>::value)
value_test(true, boost::is_arithmetic<long double>::value)
#ifdef ULLONG_MAX
value_test(true, boost::is_arithmetic<long long>::value)
value_test(true, boost::is_arithmetic<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, boost::is_arithmetic<__int64>::value)
value_test(true, boost::is_arithmetic<unsigned __int64>::value)
#endif
value_test(false, boost::is_fundamental<UDT>::value)
value_test(true, boost::is_fundamental<void>::value)
value_test(true, boost::is_fundamental<bool>::value)
value_test(true, boost::is_fundamental<char>::value)
value_test(true, boost::is_fundamental<signed char>::value)
value_test(true, boost::is_fundamental<unsigned char>::value)
value_test(true, boost::is_fundamental<wchar_t>::value)
value_test(true, boost::is_fundamental<short>::value)
value_test(true, boost::is_fundamental<unsigned short>::value)
value_test(true, boost::is_fundamental<int>::value)
value_test(true, boost::is_fundamental<unsigned int>::value)
value_test(true, boost::is_fundamental<long>::value)
value_test(true, boost::is_fundamental<unsigned long>::value)
value_test(true, boost::is_fundamental<float>::value)
value_test(true, boost::is_fundamental<double>::value)
value_test(true, boost::is_fundamental<long double>::value)
#ifdef ULLONG_MAX
value_test(true, boost::is_fundamental<long long>::value)
value_test(true, boost::is_fundamental<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, boost::is_fundamental<__int64>::value)
value_test(true, boost::is_fundamental<unsigned __int64>::value)
#endif
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
unsigned int expected_failures = 0;

View File

@ -0,0 +1,116 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/composite_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"
NESTED_DECL(is_array)
NESTED_DECL(is_pointer)
NESTED_DECL(is_reference)
int main(int argc, char* argv[])
{
NESTED_TEST(is_array, int)
NESTED_TEST(is_array, int[2])
NESTED_TEST(is_array, int[3][4])
NESTED_TEST(is_array, int const [5])
NESTED_TEST(is_array, int(&)[2])
NESTED_TEST(is_array, int (*)(double))
NESTED_TEST(is_pointer, int)
NESTED_TEST(is_pointer, int*)
NESTED_TEST(is_reference, int)
NESTED_TEST(is_reference, int&)
value_test(false, boost::is_array<int>::value)
value_test(false, boost::is_array<int*>::value)
value_test(false, boost::is_array<const int*>::value)
value_test(false, boost::is_array<const volatile int*>::value)
value_test(false, boost::is_array<int*const>::value)
value_test(false, boost::is_array<const int*volatile>::value)
value_test(false, boost::is_array<const volatile int*const>::value)
value_test(true, boost::is_array<int[2]>::value)
value_test(true, boost::is_array<const int[2]>::value)
value_test(true, boost::is_array<const volatile int[2]>::value)
value_test(true, boost::is_array<int[2][3]>::value)
value_test(true, boost::is_array<UDT[2]>::value)
value_test(false, boost::is_array<int(&)[2]>::value)
value_test(false, boost::is_array<f1>::value)
value_test(false, boost::is_array<void>::value)
value_test(false, boost::is_pointer<int>::value)
value_test(false, boost::is_pointer<int&>::value)
value_test(true, boost::is_pointer<int*>::value)
value_test(true, boost::is_pointer<const int*>::value)
value_test(true, boost::is_pointer<volatile int*>::value)
value_test(true, boost::is_pointer<non_pointer*>::value)
// these were false in previous versions (JM 20 Dec 2000):
value_test(true, boost::is_pointer<int*const>::value)
value_test(true, boost::is_pointer<int*volatile>::value)
value_test(true, boost::is_pointer<int*const volatile>::value)
// JM 02 Oct 2000:
value_test(false, boost::is_pointer<non_pointer>::value)
value_test(false, boost::is_pointer<int*&>::value)
value_test(false, boost::is_pointer<int(&)[2]>::value)
value_test(false, boost::is_pointer<int[2]>::value)
value_test(false, boost::is_pointer<char[sizeof(void*)]>::value)
value_test(false, boost::is_pointer<void>::value)
value_test(true, boost::is_pointer<f1>::value)
value_test(true, boost::is_pointer<f2>::value)
value_test(true, boost::is_pointer<f3>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3
value_test(false, boost::is_pointer<mf1>::value)
value_test(false, boost::is_pointer<mf2>::value)
value_test(false, boost::is_pointer<mf3>::value)
value_test(false, boost::is_pointer<mf4>::value)
value_test(false, boost::is_reference<bool>::value)
value_test(true, boost::is_reference<int&>::value)
value_test(true, boost::is_reference<const int&>::value)
value_test(true, boost::is_reference<volatile int &>::value)
value_test(true, boost::is_reference<const volatile int &>::value)
value_test(true, boost::is_reference<r_type>::value)
value_test(true, boost::is_reference<cr_type>::value)
value_test(true, boost::is_reference<const UDT&>::value)
value_test(false, boost::is_reference<void>::value)
value_test(false, boost::is_member_pointer<f1>::value)
value_test(false, boost::is_member_pointer<f2>::value)
value_test(false, boost::is_member_pointer<f3>::value)
value_test(false, boost::is_member_pointer<void*>::value)
value_test(true, boost::is_member_pointer<mf1>::value)
value_test(true, boost::is_member_pointer<mf2>::value)
value_test(true, boost::is_member_pointer<mf3>::value)
value_test(true, boost::is_member_pointer<mf4>::value)
value_test(false, boost::is_member_pointer<void>::value)
value_test(false, boost::is_enum<int>::value)
value_test(true, boost::is_enum<enum_UDT>::value)
value_test(false, boost::is_enum<int_convertible>::value)
value_test(false, boost::is_enum<int&>::value)
value_test(false, boost::is_enum<void>::value)
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
#ifdef __BORLANDC__
unsigned int expected_failures = 2;
#elif defined(__GNUC__)
unsigned int expected_failures = 1; // can't handle cv-qualified references
#elif defined(BOOST_MSVC)
unsigned int expected_failures = 1;
#else
unsigned int expected_failures = 0;
#endif

50
tests/cv_traits_test.cpp Normal file
View File

@ -0,0 +1,50 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/cv_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"
NESTED_DECL(is_const)
NESTED_DECL(is_volatile)
int main(int argc, char* argv[])
{
NESTED_TEST(is_const, int)
NESTED_TEST(is_const, const int)
NESTED_TEST(is_const, volatile int)
NESTED_TEST(is_volatile, int)
NESTED_TEST(is_volatile, const int)
NESTED_TEST(is_volatile, volatile int)
value_test(false, boost::is_const<void>::value)
value_test(true, boost::is_const<const void>::value)
value_test(false, boost::is_const<int>::value)
value_test(true, boost::is_const<const int>::value)
value_test(true, boost::is_const<const UDT>::value)
value_test(true, boost::is_const<const volatile UDT>::value)
value_test(false, boost::is_volatile<void>::value)
value_test(true, boost::is_volatile<volatile void>::value)
value_test(false, boost::is_volatile<int>::value)
value_test(true, boost::is_volatile<volatile int>::value)
value_test(true, boost::is_volatile<volatile UDT>::value)
value_test(true, boost::is_volatile<volatile UDT>::value)
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
#ifdef BOOST_MSVC
unsigned int expected_failures = 2;
#else
unsigned int expected_failures = 0;
#endif

View File

@ -0,0 +1,72 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/utility.hpp>
#include "boost/type_traits/type_traits_test.hpp"
int main(int argc, char* argv[])
{
value_test(true, (boost::is_convertible<Deriverd,Base>::value));
value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
value_test(true, (boost::is_convertible<Base,Base>::value));
value_test(false, (boost::is_convertible<Base,Deriverd>::value));
value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
value_test(false, (boost::is_convertible<NonDerived,Base>::value));
value_test(false, (boost::is_convertible<boost::noncopyable, int>::value));
value_test(true, (boost::is_convertible<float,int>::value));
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
value_test(false, (boost::is_convertible<float,void>::value));
value_test(false, (boost::is_convertible<void,float>::value));
value_test(true, (boost::is_convertible<void,void>::value));
#endif
value_test(true, (boost::is_convertible<enum1, int>::value));
value_test(true, (boost::is_convertible<Deriverd*, Base*>::value));
value_test(false, (boost::is_convertible<Base*, Deriverd*>::value));
value_test(true, (boost::is_convertible<Deriverd&, Base&>::value));
value_test(false, (boost::is_convertible<Base&, Deriverd&>::value));
value_test(true, (boost::is_convertible<const Deriverd*, const Base*>::value));
value_test(false, (boost::is_convertible<const Base*, const Deriverd*>::value));
value_test(true, (boost::is_convertible<const Deriverd&, const Base&>::value));
value_test(false, (boost::is_convertible<const Base&, const Deriverd&>::value));
value_test(false, (boost::is_convertible<const int *, int*>::value));
value_test(false, (boost::is_convertible<const int&, int&>::value));
value_test(true, (boost::is_convertible<int*, int[2]>::value));
value_test(false, (boost::is_convertible<const int*, int[3]>::value));
value_test(true, (boost::is_convertible<const int&, int>::value));
value_test(true, (boost::is_convertible<int(&)[4], const int*>::value));
value_test(true, (boost::is_convertible<int(&)(int), int(*)(int)>::value));
value_test(true, (boost::is_convertible<int *, const int*>::value));
value_test(true, (boost::is_convertible<int&, const int&>::value));
value_test(true, (boost::is_convertible<int[2], int*>::value));
value_test(true, (boost::is_convertible<int[2], const int*>::value));
value_test(false, (boost::is_convertible<const int[2], int*>::value));
value_test(true, (boost::is_convertible<non_pointer, void*>::value));
value_test(false, (boost::is_convertible<non_pointer, int*>::value));
value_test(true, (boost::is_convertible<non_int_pointer, int*>::value));
value_test(true, (boost::is_convertible<non_int_pointer, void*>::value));
value_test(true, (boost::is_convertible<int, int_constructible>::value));
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
#ifdef __BORLANDC__
unsigned int expected_failures = 1;
#else
unsigned int expected_failures = 0;
#endif

42
tests/is_same_test.cpp Normal file
View File

@ -0,0 +1,42 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/same_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"
int main(int argc, char* argv[])
{
value_test(true, (::boost::is_same<int, int>::value))
value_test(false, (::boost::is_same<int, const int>::value))
value_test(false, (::boost::is_same<int, int&>::value))
value_test(false, (::boost::is_same<const int, int&>::value))
value_test(false, (::boost::is_same<int, const int&>::value))
value_test(false, (::boost::is_same<int*, const int*>::value))
value_test(false, (::boost::is_same<int*, int*const>::value))
value_test(false, (::boost::is_same<int, int[2]>::value))
value_test(false, (::boost::is_same<int*, int[2]>::value))
value_test(false, (::boost::is_same<int[4], int[2]>::value))
value_test(false, (::boost::is_same<void, int>::value))
value_test(true, (::boost::is_same<void, void>::value))
value_test(false, (::boost::is_same<void, const void>::value))
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
#ifdef BOOST_MSVC
// can't separate void and cv-void:
unsigned int expected_failures = 1;
#else
unsigned int expected_failures = 0;
#endif

View File

@ -0,0 +1,191 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/object_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"
NESTED_DECL(is_class)
NESTED_DECL(is_object)
NESTED_DECL(is_scalar)
NESTED_DECL(is_compound)
NESTED_DECL(is_POD)
int main(int argc, char* argv[])
{
NESTED_TEST(is_class, int)
NESTED_TEST(is_class, UDT)
NESTED_TEST(is_object, int)
NESTED_TEST(is_object, void)
NESTED_TEST(is_object, UDT)
NESTED_TEST(is_scalar, void)
NESTED_TEST(is_scalar, int)
NESTED_TEST(is_compound, int)
NESTED_TEST(is_compound, UDT)
NESTED_TEST(is_POD, int)
NESTED_TEST(is_POD, UDT)
value_test(false, boost::is_class<int>::value)
value_test(false, boost::is_class<const int>::value)
value_test(false, boost::is_class<volatile int>::value)
value_test(false, boost::is_class<int*>::value)
value_test(false, boost::is_class<int* const>::value)
value_test(false, boost::is_class<int[2]>::value)
value_test(false, boost::is_class<int&>::value)
value_test(false, boost::is_class<mf4>::value)
value_test(false, boost::is_class<f1>::value)
value_test(false, boost::is_class<enum_UDT>::value)
value_test(true, boost::is_class<UDT>::value)
value_test(true, boost::is_class<UDT const>::value)
value_test(true, boost::is_class<UDT volatile>::value)
value_test(true, boost::is_class<empty_UDT>::value)
value_test(true, boost::is_class<std::iostream>::value)
value_test(false, boost::is_class<UDT*>::value)
value_test(false, boost::is_class<UDT[2]>::value)
value_test(false, boost::is_class<UDT&>::value)
value_test(false, boost::is_class<void>::value)
value_test(true, boost::is_object<int>::value)
value_test(true, boost::is_object<UDT>::value)
value_test(false, boost::is_object<int&>::value)
value_test(false, boost::is_object<void>::value)
value_test(true, boost::is_scalar<int>::value)
value_test(true, boost::is_scalar<void*>::value)
value_test(false, boost::is_scalar<void>::value)
value_test(false, boost::is_scalar<UDT>::value)
value_test(false, boost::is_scalar<int&>::value)
value_test(true, boost::is_compound<UDT>::value)
value_test(true, boost::is_compound<void*>::value)
value_test(false, boost::is_compound<void>::value)
value_test(false, boost::is_compound<int>::value)
value_test(true, boost::is_POD<int>::value)
value_test(true, boost::is_POD<int*>::value)
value_test(false, boost::is_POD<int&>::value)
value_test(true, boost::is_POD<int*const>::value)
value_test(true, boost::is_POD<const int>::value)
value_test(true, boost::is_POD<volatile int>::value)
value_test(false, boost::is_POD<const int&>::value)
value_test(true, boost::is_POD<int[2]>::value)
value_test(true, boost::is_POD<int[3][2]>::value)
value_test(true, boost::is_POD<int[2][4][5][6][3]>::value)
value_test(true, boost::is_POD<f1>::value)
value_test(true, boost::is_POD<mf2>::value)
value_test(false, boost::is_POD<UDT>::value)
value_test(false, boost::is_POD<empty_UDT>::value)
value_test(true, boost::is_POD<enum_UDT>::value)
value_test(true, boost::is_POD<void>::value)
value_test(true, boost::has_trivial_constructor<int>::value)
value_test(true, boost::has_trivial_constructor<int*>::value)
value_test(true, boost::has_trivial_constructor<int*const>::value)
value_test(true, boost::has_trivial_constructor<const int>::value)
value_test(true, boost::has_trivial_constructor<volatile int>::value)
value_test(true, boost::has_trivial_constructor<int[2]>::value)
value_test(true, boost::has_trivial_constructor<int[3][2]>::value)
value_test(true, boost::has_trivial_constructor<int[2][4][5][6][3]>::value)
value_test(true, boost::has_trivial_constructor<f1>::value)
value_test(true, boost::has_trivial_constructor<mf2>::value)
value_test(false, boost::has_trivial_constructor<UDT>::value)
value_test(true, boost::has_trivial_constructor<empty_UDT>::value)
value_test(true, boost::has_trivial_constructor<enum_UDT>::value)
value_test(true, boost::has_trivial_constructor<void>::value)
value_test(true, boost::has_trivial_copy<int>::value)
value_test(true, boost::has_trivial_copy<int*>::value)
value_test(true, boost::has_trivial_copy<int*const>::value)
value_test(true, boost::has_trivial_copy<const int>::value)
// Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
value_test(false, boost::has_trivial_copy<volatile int>::value)
value_test(true, boost::has_trivial_copy<int[2]>::value)
value_test(true, boost::has_trivial_copy<int[3][2]>::value)
value_test(true, boost::has_trivial_copy<int[2][4][5][6][3]>::value)
value_test(true, boost::has_trivial_copy<f1>::value)
value_test(true, boost::has_trivial_copy<mf2>::value)
value_test(false, boost::has_trivial_copy<UDT>::value)
value_test(true, boost::has_trivial_copy<empty_UDT>::value)
value_test(true, boost::has_trivial_copy<enum_UDT>::value)
value_test(true, boost::has_trivial_copy<void>::value)
value_test(true, boost::has_trivial_assign<int>::value)
value_test(true, boost::has_trivial_assign<int*>::value)
value_test(false, boost::has_trivial_assign<int*const>::value)
value_test(false, boost::has_trivial_assign<const int>::value)
// Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
value_test(false, boost::has_trivial_assign<volatile int>::value)
value_test(true, boost::has_trivial_assign<int[2]>::value)
value_test(true, boost::has_trivial_assign<int[3][2]>::value)
value_test(true, boost::has_trivial_assign<int[2][4][5][6][3]>::value)
value_test(true, boost::has_trivial_assign<f1>::value)
value_test(true, boost::has_trivial_assign<mf2>::value)
value_test(false, boost::has_trivial_assign<UDT>::value)
value_test(true, boost::has_trivial_assign<empty_UDT>::value)
value_test(true, boost::has_trivial_assign<enum_UDT>::value)
value_test(true, boost::has_trivial_assign<void>::value)
value_test(true, boost::has_trivial_destructor<int>::value)
value_test(true, boost::has_trivial_destructor<int*>::value)
value_test(true, boost::has_trivial_destructor<int*const>::value)
value_test(true, boost::has_trivial_destructor<const int>::value)
value_test(true, boost::has_trivial_destructor<volatile int>::value)
value_test(true, boost::has_trivial_destructor<int[2]>::value)
value_test(true, boost::has_trivial_destructor<int[3][2]>::value)
value_test(true, boost::has_trivial_destructor<int[2][4][5][6][3]>::value)
value_test(true, boost::has_trivial_destructor<f1>::value)
value_test(true, boost::has_trivial_destructor<mf2>::value)
value_test(false, boost::has_trivial_destructor<UDT>::value)
value_test(false, boost::has_trivial_destructor<empty_UDT>::value)
value_test(true, boost::has_trivial_destructor<enum_UDT>::value)
value_test(true, boost::has_trivial_destructor<void>::value)
soft_value_test(false, boost::is_empty<int>::value)
soft_value_test(false, boost::is_empty<int*>::value)
soft_value_test(false, boost::is_empty<int&>::value)
soft_value_test(false, boost::is_empty<void>::value)
#if defined(__MWERKS__)
// apparent compiler bug causes this to fail to compile:
value_fail(false, boost::is_empty<int[2]>::value)
#else
soft_value_test(false, boost::is_empty<int[2]>::value)
#endif
soft_value_test(false, boost::is_empty<f1>::value)
soft_value_test(false, boost::is_empty<mf1>::value)
soft_value_test(false, boost::is_empty<UDT>::value)
soft_value_test(true, boost::is_empty<empty_UDT>::value)
soft_value_test(true, boost::is_empty<empty_POD_UDT>::value)
// this one will not compile on most compilers,
// because we can't tell the difference between
// unions and classes:
value_fail(true, boost::is_empty<empty_union_UDT>::value)
soft_value_test(false, boost::is_empty<enum_UDT>::value)
soft_value_test(true, boost::is_empty<boost::noncopyable>::value)
soft_value_test(false, boost::is_empty<non_empty>::value)
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
#ifdef __BORLANDC__
// can't handle enum's or classes that are POD's
unsigned int expected_failures = 10;
#elif defined(__GNUC__)
// classes that are POD's, or empty:
unsigned int expected_failures = 4;
#elif defined(BOOST_MSVC)
// can't handle classes that are POD's or arrays that are POD's
unsigned int expected_failures = 19;
#else
unsigned int expected_failures = 4;
#endif

View File

@ -0,0 +1,395 @@
// (C) Copyright John Maddock 2000. 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.
#include <boost/type_traits/transform_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/utility.hpp>
#ifdef __BORLANDC__
#pragma hrdstop
#endif
//
// some of these tests, particularly those involving
// the use of the transform_check macro are tantamount
// to "compiler-abuse", and actually hide a *lot* of
// template test code. To prevent "Internal Compiler Error"
// type messages, we have to split these up into lots of
// separate functions:
#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && (__BORLANDC__ < 0x550))
#define SHORT_TRANSFORM_TEST
#endif
#include "boost/type_traits/type_traits_test.hpp"
#define BOOST_DECL_TRANSFORM_TEST(name, type, from, to)\
void name(){ transform_check(type, from, to) }
#define BOOST_DECL_TRANSFORM_TEST3(name, type, from)\
void name(){ transform_check(type, from, boost_dummy_macro_param) }
#define BOOST_DECL_TRANSFORM_TEST2(name, type)\
void name(){ transform_check(type, boost_dummy_macro_param, boost_dummy_macro_param) }
/***********************************************************************
*
* tests for remove_const:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST3(remove_const_test_1, ::boost::remove_const, const)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_2, ::boost::remove_const, volatile, volatile)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_3, ::boost::remove_const, const volatile, volatile)
BOOST_DECL_TRANSFORM_TEST2(remove_const_test_4, ::boost::remove_const)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_6, ::boost::remove_const, *const, *)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_7, ::boost::remove_const, *volatile, *volatile)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_8, ::boost::remove_const, *const volatile, *volatile)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_9, ::boost::remove_const, *, *)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_11, ::boost::remove_const, volatile*, volatile*)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_12, ::boost::remove_const, const[2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_const_test_13, ::boost::remove_const, volatile[2], volatile[2])
BOOST_DECL_TRANSFORM_TEST(remove_const_test_14, ::boost::remove_const, const volatile[2], volatile[2])
BOOST_DECL_TRANSFORM_TEST(remove_const_test_15, ::boost::remove_const, [2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_const_test_16, ::boost::remove_const, const*, const*)
BOOST_DECL_TRANSFORM_TEST(remove_const_test_17, ::boost::remove_const, const*const, const*)
void check_remove_const()
{
remove_const_test_1();
remove_const_test_2();
remove_const_test_3();
remove_const_test_4();
remove_const_test_6();
remove_const_test_7();
remove_const_test_8();
remove_const_test_9();
remove_const_test_11();
remove_const_test_12();
remove_const_test_13();
remove_const_test_14();
remove_const_test_15();
remove_const_test_16();
remove_const_test_17();
}
/***********************************************************************
*
* tests for remove_volatile:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_1, ::boost::remove_volatile, const, const)
BOOST_DECL_TRANSFORM_TEST3(remove_volatile_test_2, ::boost::remove_volatile, volatile)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_3, ::boost::remove_volatile, const volatile, const)
BOOST_DECL_TRANSFORM_TEST2(remove_volatile_test_4, ::boost::remove_volatile)
BOOST_DECL_TRANSFORM_TEST2(remove_volatile_test_5, ::boost::remove_volatile)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_6, ::boost::remove_volatile, *const, *const)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_7, ::boost::remove_volatile, *volatile, *)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_8, ::boost::remove_volatile, *const volatile, *const)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_9, ::boost::remove_volatile, *, *)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_10, ::boost::remove_volatile, *, *)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_11, ::boost::remove_volatile, volatile*, volatile*)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_12, ::boost::remove_volatile, const[2], const[2])
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_13, ::boost::remove_volatile, volatile[2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_14, ::boost::remove_volatile, const volatile[2], const[2])
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_15, ::boost::remove_volatile, [2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_16, ::boost::remove_volatile, const*, const*)
BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_17, ::boost::remove_volatile, const*volatile, const*)
void check_remove_volatile()
{
remove_volatile_test_1();
remove_volatile_test_2();
remove_volatile_test_3();
remove_volatile_test_4();
remove_volatile_test_5();
remove_volatile_test_6();
remove_volatile_test_7();
remove_volatile_test_8();
remove_volatile_test_9();
remove_volatile_test_10();
remove_volatile_test_11();
remove_volatile_test_12();
remove_volatile_test_13();
remove_volatile_test_14();
remove_volatile_test_15();
remove_volatile_test_16();
remove_volatile_test_17();
}
/***********************************************************************
*
* tests for remove_cv:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST3(remove_cv_test_1, ::boost::remove_cv, const)
BOOST_DECL_TRANSFORM_TEST3(remove_cv_test_2, ::boost::remove_cv, volatile)
BOOST_DECL_TRANSFORM_TEST3(remove_cv_test_3, ::boost::remove_cv, const volatile)
BOOST_DECL_TRANSFORM_TEST2(remove_cv_test_4, ::boost::remove_cv)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_5, ::boost::remove_cv, const &, const&)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_6, ::boost::remove_cv, *const, *)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_7, ::boost::remove_cv, *volatile, *)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_8, ::boost::remove_cv, *const volatile, *)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_9, ::boost::remove_cv, *, *)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_10, ::boost::remove_cv, const*, const*)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_11, ::boost::remove_cv, volatile*, volatile*)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_12, ::boost::remove_cv, const[2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_13, ::boost::remove_cv, volatile[2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_14, ::boost::remove_cv, const volatile[2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_15, ::boost::remove_cv, [2], [2])
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_16, ::boost::remove_cv, const*, const*)
BOOST_DECL_TRANSFORM_TEST(remove_cv_test_17, ::boost::remove_cv, const*volatile, const*)
void check_remove_cv()
{
remove_cv_test_1();
remove_cv_test_2();
remove_cv_test_3();
remove_cv_test_4();
remove_cv_test_5();
remove_cv_test_6();
remove_cv_test_7();
remove_cv_test_8();
remove_cv_test_9();
remove_cv_test_10();
remove_cv_test_11();
remove_cv_test_12();
remove_cv_test_13();
remove_cv_test_14();
remove_cv_test_15();
remove_cv_test_16();
remove_cv_test_17();
}
/***********************************************************************
*
* tests for remove_reference:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_1, ::boost::remove_reference, const, const)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_2, ::boost::remove_reference, volatile, volatile)
BOOST_DECL_TRANSFORM_TEST3(remove_reference_test_3, ::boost::remove_reference, &)
BOOST_DECL_TRANSFORM_TEST2(remove_reference_test_4, ::boost::remove_reference)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_5, ::boost::remove_reference, const &, const)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_6, ::boost::remove_reference, *, *)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_7, ::boost::remove_reference, *volatile, *volatile)
BOOST_DECL_TRANSFORM_TEST3(remove_reference_test_8, ::boost::remove_reference, &)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_9, ::boost::remove_reference, const &, const)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_10, ::boost::remove_reference, const*, const*)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_11, ::boost::remove_reference, volatile*, volatile*)
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_12, ::boost::remove_reference, const[2], const[2])
BOOST_DECL_TRANSFORM_TEST(remove_reference_test_13, ::boost::remove_reference, (&)[2], [2])
void check_remove_reference()
{
remove_reference_test_1();
remove_reference_test_2();
remove_reference_test_3();
remove_reference_test_4();
remove_reference_test_5();
remove_reference_test_6();
remove_reference_test_7();
remove_reference_test_8();
remove_reference_test_9();
remove_reference_test_10();
remove_reference_test_11();
remove_reference_test_12();
remove_reference_test_13();
}
/***********************************************************************
*
* tests for remove_bounds:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_1, ::boost::remove_bounds, const, const)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_2, ::boost::remove_bounds, volatile, volatile)
BOOST_DECL_TRANSFORM_TEST3(remove_bounds_test_3, ::boost::remove_bounds, [2])
BOOST_DECL_TRANSFORM_TEST2(remove_bounds_test_4, ::boost::remove_bounds)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_5, ::boost::remove_bounds, const &, const&)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_6, ::boost::remove_bounds, *, *)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_7, ::boost::remove_bounds, *volatile, *volatile)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_8, ::boost::remove_bounds, const [2], const)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_9, ::boost::remove_bounds, const &, const&)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_10, ::boost::remove_bounds, const*, const*)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_11, ::boost::remove_bounds, volatile*, volatile*)
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_12, ::boost::remove_bounds, const[2][3], const[3])
BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_13, ::boost::remove_bounds, (&)[2], (&)[2])
void check_remove_bounds()
{
remove_bounds_test_1();
remove_bounds_test_2();
remove_bounds_test_3();
remove_bounds_test_4();
remove_bounds_test_5();
remove_bounds_test_6();
remove_bounds_test_7();
remove_bounds_test_8();
remove_bounds_test_9();
remove_bounds_test_10();
remove_bounds_test_11();
remove_bounds_test_12();
remove_bounds_test_13();
}
/***********************************************************************
*
* tests for remove_pointer:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_1, ::boost::remove_pointer, const, const)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_2, ::boost::remove_pointer, volatile, volatile)
BOOST_DECL_TRANSFORM_TEST3(remove_pointer_test_3, ::boost::remove_pointer, *)
BOOST_DECL_TRANSFORM_TEST2(remove_pointer_test_4, ::boost::remove_pointer)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_5, ::boost::remove_pointer, const &, const&)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_6, ::boost::remove_pointer, &, &)
BOOST_DECL_TRANSFORM_TEST3(remove_pointer_test_7, ::boost::remove_pointer, *volatile)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_8, ::boost::remove_pointer, const [2], const[2])
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_9, ::boost::remove_pointer, const &, const&)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_10, ::boost::remove_pointer, const*, const)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_11, ::boost::remove_pointer, volatile*, volatile)
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_12, ::boost::remove_pointer, const[2][3], const[2][3])
BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_13, ::boost::remove_pointer, (&)[2], (&)[2])
void check_remove_pointer()
{
remove_pointer_test_1();
remove_pointer_test_2();
remove_pointer_test_3();
remove_pointer_test_4();
remove_pointer_test_5();
remove_pointer_test_6();
remove_pointer_test_7();
remove_pointer_test_8();
remove_pointer_test_9();
remove_pointer_test_10();
remove_pointer_test_11();
remove_pointer_test_12();
remove_pointer_test_13();
}
/***********************************************************************
*
* tests for add_reference:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST(add_reference_test_1, ::boost::add_reference, const, const&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_2, ::boost::add_reference, volatile, volatile&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_3, ::boost::add_reference, *, *&)
//BOOST_DECL_TRANSFORM_TEST2(add_reference_test_4, ::boost::add_reference)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_5, ::boost::add_reference, const &, const&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_6, ::boost::add_reference, &, &)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_7, ::boost::add_reference, *volatile, *volatile&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_8, ::boost::add_reference, const [2], const (&)[2])
BOOST_DECL_TRANSFORM_TEST(add_reference_test_9, ::boost::add_reference, const &, const&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_10, ::boost::add_reference, const*, const*&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_11, ::boost::add_reference, volatile*, volatile*&)
BOOST_DECL_TRANSFORM_TEST(add_reference_test_12, ::boost::add_reference, const[2][3], const (&)[2][3])
BOOST_DECL_TRANSFORM_TEST(add_reference_test_13, ::boost::add_reference, (&)[2], (&)[2])
void check_add_reference()
{
add_reference_test_1();
add_reference_test_2();
add_reference_test_3();
//add_reference_test_4();
add_reference_test_5();
add_reference_test_6();
add_reference_test_7();
add_reference_test_8();
add_reference_test_9();
add_reference_test_10();
add_reference_test_11();
add_reference_test_12();
add_reference_test_13();
}
/***********************************************************************
*
* tests for add_pointer:
*
**********************************************************************/
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_1, ::boost::add_pointer, const, const*)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_2, ::boost::add_pointer, volatile, volatile*)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_3, ::boost::add_pointer, *, **)
//BOOST_DECL_TRANSFORM_TEST2(add_pointer_test_4, ::boost::add_pointer)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_7, ::boost::add_pointer, *volatile, *volatile*)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_10, ::boost::add_pointer, const*, const**)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_11, ::boost::add_pointer, volatile*, volatile**)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_5, ::boost::add_pointer, const &, const*)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_6, ::boost::add_pointer, &, *)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_8, ::boost::add_pointer, const [2], const *)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_9, ::boost::add_pointer, const &, const*)
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_12, ::boost::add_pointer, const[2][3], const (*)[3])
BOOST_DECL_TRANSFORM_TEST(add_pointer_test_13, ::boost::add_pointer, (&)[2], *)
#endif
void check_add_pointer()
{
add_pointer_test_1();
add_pointer_test_2();
add_pointer_test_3();
//add_pointer_test_4();
add_pointer_test_7();
add_pointer_test_10();
add_pointer_test_11();
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
add_pointer_test_5();
add_pointer_test_6();
add_pointer_test_8();
add_pointer_test_9();
add_pointer_test_12();
add_pointer_test_13();
#endif
}
int main(int argc, char* argv[])
{
check_remove_const();
check_remove_volatile();
check_remove_cv();
check_remove_reference();
check_remove_bounds();
check_remove_pointer();
check_add_reference();
check_add_pointer();
type_test(void, boost::remove_const<void>::type)
type_test(void, boost::remove_volatile<void>::type)
type_test(void, boost::remove_cv<void>::type)
type_test(int, boost::remove_reference<cr_type>::type)
type_test(void, boost::remove_reference<void>::type)
type_test(void, boost::remove_bounds<void>::type)
type_test(void, boost::remove_pointer<void>::type)
return check_result(argc, argv);
}
//
// define the number of failures expected for given compilers:
#ifdef __BORLANDC__
#ifdef SHORT_TRANSFORM_TEST
unsigned int expected_failures = 97; // cv-qualifiers
#else
unsigned int expected_failures = 422; // cv-qualifiers
#endif
#elif defined(__GNUC__)
unsigned int expected_failures = 1; // cv-qualified references
#else
unsigned int expected_failures = 0;
#endif