mirror of
https://github.com/boostorg/utility.git
synced 2025-10-13 09:05:21 +02:00
Compare commits
355 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
|
46dd855904 | ||
|
1c7a2a1476 | ||
|
7c40cc0b63 | ||
|
73a9e0d351 | ||
|
dc9856744a | ||
|
88f4e47550 | ||
|
1be04eeec5 | ||
|
56acf9c325 | ||
|
c6e3957efc | ||
|
25e8284950 | ||
|
37a6537a5b | ||
|
80df1d8f12 | ||
|
75afed7f17 | ||
|
1d7066aee1 | ||
|
12272a38d4 | ||
|
04f901e52e | ||
|
fabfb31bf6 | ||
|
683701cd07 | ||
|
119c64be0b | ||
|
d429c9a7d8 | ||
|
1e8216431b | ||
|
e45b2e2136 | ||
|
9e6951009b | ||
|
a009a209f1 | ||
|
97605056ed | ||
|
8fcfa33d33 | ||
|
aa65e3da3b | ||
|
b4cfadb4d5 | ||
|
45a6249668 | ||
|
1d601aef4d | ||
|
32fb45eba9 | ||
|
2b7d10aceb | ||
|
5dc62711e1 | ||
|
252c02aca0 | ||
|
9655beb7ba | ||
|
f0ea53e77e | ||
|
4755b42909 | ||
|
ef9af03c6c | ||
|
7439073cbf | ||
|
aff985a563 | ||
|
db425222d5 | ||
|
e20af510f7 | ||
|
d8230c6a73 | ||
|
f5690787bf | ||
|
a4fd7b32dd | ||
|
f4336ec693 | ||
|
03d906976b | ||
|
4ba6a96822 | ||
|
1ea4140d56 | ||
|
351d4ecb15 | ||
|
7fbf84dcc6 | ||
|
3ff49b272d | ||
|
5b52e3d418 | ||
|
8c0eb498d3 | ||
|
48a81ef7ea | ||
|
f7610c9b26 | ||
|
1755eaf019 | ||
|
6b8b218efb | ||
|
333d79b345 | ||
|
f0fa436fe4 | ||
|
13e6d78fa8 | ||
|
7126ea2685 | ||
|
a37518cb4a | ||
|
64b3e8c3bd | ||
|
339937380e | ||
|
6156f0d302 | ||
|
00560e8e17 | ||
|
029ff9828f | ||
|
ec188c7c3e | ||
|
0a0296a5d0 | ||
|
6e26a5bbe7 | ||
|
dc1b6246a0 | ||
|
15f69eaf14 | ||
|
4774a0d325 | ||
|
be78ab72c9 | ||
|
0bc4a1b20d | ||
|
c8b674d105 | ||
|
b421d4725a | ||
|
1662bb5713 | ||
|
ad79a21abd | ||
|
19645a52e6 | ||
|
74c3077c9a | ||
|
1f29191329 | ||
|
4b636a7680 | ||
|
e6fc2555f3 | ||
|
e27d0fcf2a | ||
|
2643c33b20 | ||
|
71af1e77c8 | ||
|
99e7406bd9 | ||
|
413265f497 | ||
|
fe44cdf09b | ||
|
e413428d71 | ||
|
88b9822db7 | ||
|
24045c0cd7 | ||
|
d2aa9f4a84 | ||
|
d2a5fd169f | ||
|
4e350d9934 | ||
|
f3f697bbc8 | ||
|
c7c09696db | ||
|
dbcc58d984 | ||
|
8231310c4d | ||
|
2988140430 | ||
|
7387966005 | ||
|
e0a5a61375 | ||
|
66ecd70689 | ||
|
67f4f45653 | ||
|
1bf28b3de2 | ||
|
eb3c3435d7 | ||
|
8a81d8b16c | ||
|
bc9d8b13d0 | ||
|
4768b167ab | ||
|
591ff70ed1 | ||
|
7bf2ad0b22 | ||
|
409c79b2e4 | ||
|
d0410691a1 | ||
|
64e5115138 | ||
|
7ae912d83c | ||
|
2937f5876c | ||
|
8619c9b5c3 | ||
|
e4d5684f6b | ||
|
3d69cf95da | ||
|
18944572b7 | ||
|
3e9d0f80c2 | ||
|
a2c4d1990a | ||
|
404261c6ee | ||
|
87abc59612 | ||
|
cb98ddf7db | ||
|
7d2e6c9025 | ||
|
75eaa14a18 | ||
|
082d6e3b32 | ||
|
35b3770b6f | ||
|
5b9d20c7e2 | ||
|
5bbed2372e | ||
|
a9d407d239 | ||
|
3ca4a33a65 | ||
|
95197f427c | ||
|
84cdfb032c | ||
|
ec2ceb9c96 | ||
|
6286c893fd | ||
|
354aef0e8c | ||
|
139e33c36d | ||
|
e01de59cdd | ||
|
686f822dea | ||
|
9961d5c9af | ||
|
628be0d125 | ||
|
633e45f61a | ||
|
2f357c3805 | ||
|
cda0894d0d | ||
|
117720a8bc | ||
|
a6f6c3613a | ||
|
7914f5b931 | ||
|
a1add0a6f6 | ||
|
c032b337c4 | ||
|
ec363261ae | ||
|
97cde2183d | ||
|
7f43c682db | ||
|
0c9eee3c6b | ||
|
3b1afa3ba6 | ||
|
93e6a75125 | ||
|
52f8a7c0ca | ||
|
55bfeb646f | ||
|
75c9dd3be1 | ||
|
6392e2788f | ||
|
6a97f3f9ba | ||
|
6e5f52e279 | ||
|
7f92bed902 | ||
|
d68a11cc42 | ||
|
328a81e194 | ||
|
31d0908b74 | ||
|
32c77599f4 | ||
|
812ebf3562 | ||
|
37f476013d | ||
|
9f3104166f | ||
|
64cc0daf34 | ||
|
d5d64df124 | ||
|
0edcfcd5c1 | ||
|
50ba2d419a | ||
|
ff3a77ca5a | ||
|
4eaed6c23d | ||
|
4d0dd46471 | ||
|
9c2549bd00 | ||
|
b7c8e0c17f | ||
|
dd3cfe1837 | ||
|
43f525298e | ||
|
1bb1898ab9 | ||
|
9578f24be9 | ||
|
46fae3aed2 | ||
|
e35f91a70a | ||
|
851052fcca | ||
|
5ef81b2952 | ||
|
ef2851c053 | ||
|
0b4387cff5 | ||
|
a40cf11fbf | ||
|
5c495cd223 | ||
|
cf1296dff8 | ||
|
d6d88db6e8 | ||
|
85c2a35257 | ||
|
836d8b1c64 | ||
|
98d8c8ab71 | ||
|
db45013339 | ||
|
a55c37e7f6 | ||
|
46a270fcca | ||
|
967856518e | ||
|
7f93e739fe | ||
|
2cd1422514 | ||
|
feb370b201 | ||
|
d1b34e64d8 | ||
|
b9a1eead40 | ||
|
1e4bfac98c | ||
|
3bb504fbf3 | ||
|
5029791c90 | ||
|
a1a68f0970 | ||
|
f8543d79eb | ||
|
f353415136 | ||
|
26240403b0 | ||
|
3a39729b58 | ||
|
096c961d9a | ||
|
01fe04a6a2 | ||
|
7ea4014993 | ||
|
d50b374f88 | ||
|
27dfb25570 | ||
|
b5ed77985e | ||
|
61243bd15f | ||
|
368b94d804 | ||
|
a5adbbfd5f | ||
|
a19d13f123 | ||
|
78886ab383 | ||
|
168012b465 | ||
|
d9d58ea66e | ||
|
56f5f6e8d5 | ||
|
3cb6420eda | ||
|
60be2c1186 | ||
|
ed210f6b2c | ||
|
029bc59d74 | ||
|
961c08a82f | ||
|
7ee484c614 | ||
|
05c6fbbf99 | ||
|
91078b7f7a | ||
|
20d804afc4 | ||
|
c21f6d1cbf | ||
|
393e79c1fd | ||
|
8b92c8a085 | ||
|
ff73dd94c9 | ||
|
af43904f38 | ||
|
485074f265 | ||
|
2e0ee55b5e | ||
|
e9105d32cb | ||
|
964d23f68c | ||
|
be5aaaae7b | ||
|
bf13bd7b3f | ||
|
352e392fcb | ||
|
083b1b02df | ||
|
648c6240a2 | ||
|
60cab840cb | ||
|
83a4380dab | ||
|
de84fe8d98 | ||
|
ed3cbfdb8e | ||
|
fda44ca17d | ||
|
272025bb07 | ||
|
8e92bcf1b2 | ||
|
84f1ffdefe | ||
|
7e25450054 | ||
|
4a563fa266 | ||
|
aa4c0ec000 | ||
|
e1ecfbdc43 | ||
|
a4e122a82e | ||
|
93216e8fb7 | ||
|
16272c210d | ||
|
e104b00da1 | ||
|
ce5c6bcc08 | ||
|
8694ce31fe | ||
|
d960e5eadd | ||
|
2dc71e87a3 | ||
|
6bf17edde2 | ||
|
88573d515d | ||
|
89b9f77823 | ||
|
765d9be17d | ||
|
7135373008 | ||
|
ee269884fc | ||
|
387540d5f1 | ||
|
2eba7b42a8 | ||
|
07115d26c7 | ||
|
c43ed815a0 | ||
|
ff01e36d12 | ||
|
ac4798b16c | ||
|
d4e14fed0e | ||
|
5f91259344 | ||
|
20a9d9645d | ||
|
c86f6b4abd | ||
|
d66489b5b2 | ||
|
b743ee9f0c | ||
|
95ba69c00a | ||
|
2ac273739c | ||
|
5b4d28708c | ||
|
4cc4383488 | ||
|
8935232248 | ||
|
5c6dd2f172 | ||
|
eeeb7ef5b9 | ||
|
2efc9c1178 | ||
|
a84c46f6e3 | ||
|
a5c3dcdd02 | ||
|
46f7a75eb7 | ||
|
94b6710c5b | ||
|
d8dd3da9ab | ||
|
803ced004a | ||
|
0ea7d36ad0 | ||
|
87aafab759 | ||
|
994d310abd | ||
|
228cdcf05e | ||
|
42598e352c | ||
|
36a9e4d1da | ||
|
456dfd0dea | ||
|
155457e2b5 | ||
|
b5c91485bf | ||
|
c959cf7870 | ||
|
5878c88636 | ||
|
ddcef2fb19 | ||
|
493d124c07 | ||
|
f42060c616 | ||
|
834facc932 | ||
|
f82d0b76ee | ||
|
c25d225275 | ||
|
c503a274b5 | ||
|
087069d215 | ||
|
826a6dd114 | ||
|
f31483838d | ||
|
d8a9b633d9 | ||
|
c060e4466a | ||
|
a9951376f4 | ||
|
bda0c8f5e3 | ||
|
71902f23a2 | ||
|
dfd6c85569 | ||
|
0e41b2cc1a | ||
|
e5c81d0702 | ||
|
6caf7d4d5a | ||
|
98e87c8afb | ||
|
d9e0f80d50 | ||
|
6396fdb5ff | ||
|
2470b53373 | ||
|
16334e92ca | ||
|
c22d98a8ec | ||
|
28617afbb9 | ||
|
0c3bc42bec | ||
|
e3d9745df1 | ||
|
b8471c1015 | ||
|
045b09c9ef | ||
|
4ac07b97d3 | ||
|
34c847c17f | ||
|
f694e557e1 | ||
|
6a0c3e92a0 | ||
|
cba48df8e3 | ||
|
a0e8d1bf36 | ||
|
912dedaca7 | ||
|
7dd90c3919 | ||
|
7c3a25a377 |
@@ -1,489 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
||||||
<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 a draft of an article that will appear in a future
|
|
||||||
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 "generic"
|
|
||||||
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<>::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<T>
|
|
||||||
has a member <i>value</i> that is true only if T is void.</p>
|
|
||||||
<pre>template <typename T>
|
|
||||||
struct is_void
|
|
||||||
{ static const bool value = false; };
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct is_void<void>
|
|
||||||
{ 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<T>: 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 <typename T>
|
|
||||||
struct is_pointer
|
|
||||||
{ static const bool value = false; };
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_pointer<T*>
|
|
||||||
{ 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 <<EFBFBD>> 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 <typename T>
|
|
||||||
class c{ /*details*/ };
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
|
|
||||||
class c<U>{ /*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<T>. 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 <typename T>
|
|
||||||
struct remove_bounds
|
|
||||||
{ typedef T type; };
|
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
|
||||||
struct remove_bounds<T[N]>
|
|
||||||
{ 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<int[4][5]>::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<typename Iter1, typename Iter2>
|
|
||||||
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<T>::value</code>
|
|
||||||
is true only if T has a trivial assignment operator. This class "just
|
|
||||||
works" 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 "safe" 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 "slow but safe version"). Following that there is a specialisation
|
|
||||||
for <i>copier<true></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 "optimised" copy.</p>
|
|
||||||
<p>In order to complete the implementation, what we need now is a version of
|
|
||||||
copy, that calls <code>copier<true>::do_copy</code> if it is safe to use <font size="2" face="Courier New">memcpy</font>,
|
|
||||||
and otherwise calls <code>copier<false>::do_copy</code> to do a
|
|
||||||
"generic" 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<Iter1>::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 "premature optimisation
|
|
||||||
is the root of all evil" [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<const T*, T*>
|
|
||||||
(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%">"Optimised" 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%">"Optimised" 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> </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 "std::pair", omitting the
|
|
||||||
comparision operators, default constructor, and template copy constructor for
|
|
||||||
simplicity:</p>
|
|
||||||
<pre>template <typename T1, typename T2>
|
|
||||||
struct pair
|
|
||||||
{
|
|
||||||
typedef T1 first_type;
|
|
||||||
typedef T2 second_type;
|
|
||||||
|
|
||||||
T1 first;
|
|
||||||
T2 second;
|
|
||||||
|
|
||||||
pair(const T1 & nfirst, const T2 & nsecond)
|
|
||||||
:first(nfirst), second(nsecond) { }
|
|
||||||
};</pre>
|
|
||||||
<p>Now, this "pair" 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 "pair" 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 "T1"</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 &</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="50%">
|
|
||||||
<pre>T &</pre>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="50%">
|
|
||||||
<pre>T &</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="50%">
|
|
||||||
<pre>const T &</pre>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="50%">
|
|
||||||
<pre>const T &</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 "add_reference",
|
|
||||||
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 "T1"</td>
|
|
||||||
<td valign="top" width="27%">Type of "const T1"</td>
|
|
||||||
<td valign="top" width="53%">Type of "add_reference<const
|
|
||||||
T1>::type"</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 &</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="21%">
|
|
||||||
<pre>T &</pre>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="27%">
|
|
||||||
<pre>T & [8]</pre>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="53%">
|
|
||||||
<pre>T &</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="21%">
|
|
||||||
<pre>const T &</pre>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="27%">
|
|
||||||
<pre>const T &</pre>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="53%">
|
|
||||||
<pre>const T &</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>This allows us to build a primary template definition for "pair"
|
|
||||||
that can contain non-reference types, reference types, and constant reference
|
|
||||||
types:</p>
|
|
||||||
<pre>template <typename T1, typename T2>
|
|
||||||
struct pair
|
|
||||||
{
|
|
||||||
typedef T1 first_type;
|
|
||||||
typedef T2 second_type;
|
|
||||||
|
|
||||||
T1 first;
|
|
||||||
T2 second;
|
|
||||||
|
|
||||||
pair(boost::add_reference<const T1>::type nfirst,
|
|
||||||
boost::add_reference<const T2>::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 "pair", but to specialize "pair" 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 "compressed_pair"
|
|
||||||
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 "compressed".</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 "reference to a reference to T" to mean the same thing as a
|
|
||||||
"reference to T", 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 "const T &"
|
|
||||||
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 <bool b>
|
|
||||||
struct copier
|
|
||||||
{
|
|
||||||
template<typename I1, typename I2>
|
|
||||||
static I2 do_copy(I1 first,
|
|
||||||
I1 last, I2 out);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <bool b>
|
|
||||||
template<typename I1, typename I2>
|
|
||||||
I2 copier<b>::do_copy(I1 first,
|
|
||||||
I1 last,
|
|
||||||
I2 out)
|
|
||||||
{
|
|
||||||
while(first != last)
|
|
||||||
{
|
|
||||||
*out = *first;
|
|
||||||
++out;
|
|
||||||
++first;
|
|
||||||
}
|
|
||||||
return 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
enum{ can_opt =
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
return detail::copier<can_opt>::
|
|
||||||
do_copy(first, last, out);
|
|
||||||
}</pre>
|
|
||||||
<hr>
|
|
||||||
<p><EFBFBD> Copyright John Maddock and Steve Cleary, 2000</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
38
include/boost/assert.hpp
Normal file
38
include/boost/assert.hpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// boost/assert.hpp - BOOST_ASSERT(expr)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Note: There are no include guards. This is intentional.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org/libs/utility/assert.html for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#undef BOOST_ASSERT
|
||||||
|
|
||||||
|
#if defined(BOOST_DISABLE_ASSERTS)
|
||||||
|
|
||||||
|
# define BOOST_ASSERT(expr) ((void)0)
|
||||||
|
|
||||||
|
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
||||||
|
|
||||||
|
#include <boost/current_function.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||||
|
|
||||||
|
#else
|
||||||
|
# include <assert.h>
|
||||||
|
# define BOOST_ASSERT(expr) assert(expr)
|
||||||
|
#endif
|
23
include/boost/call_traits.hpp
Normal file
23
include/boost/call_traits.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// (C) Copyright Boost.org 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/libs/utility/call_traits.htm for Documentation.
|
||||||
|
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
|
||||||
|
// for full copyright notices.
|
||||||
|
|
||||||
|
#ifndef BOOST_CALL_TRAITS_HPP
|
||||||
|
#define BOOST_CALL_TRAITS_HPP
|
||||||
|
|
||||||
|
#ifndef BOOST_CONFIG_HPP
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
#include <boost/detail/ob_call_traits.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/detail/call_traits.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BOOST_CALL_TRAITS_HPP
|
63
include/boost/checked_delete.hpp
Normal file
63
include/boost/checked_delete.hpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||||
|
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1020
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/checked_delete.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
|
||||||
|
// Copyright (c) 2002, 2003 Peter Dimov
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
// verify that types are complete for increased safety
|
||||||
|
|
||||||
|
template<class T> inline void checked_delete(T * x)
|
||||||
|
{
|
||||||
|
typedef char type_must_be_complete[sizeof(T)];
|
||||||
|
delete x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline void checked_array_delete(T * x)
|
||||||
|
{
|
||||||
|
typedef char type_must_be_complete[sizeof(T)];
|
||||||
|
delete [] x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> struct checked_deleter
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
typedef T * argument_type;
|
||||||
|
|
||||||
|
void operator()(T * x) const
|
||||||
|
{
|
||||||
|
boost::checked_delete(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> struct checked_array_deleter
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
typedef T * argument_type;
|
||||||
|
|
||||||
|
void operator()(T * x) const
|
||||||
|
{
|
||||||
|
boost::checked_array_delete(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
23
include/boost/compressed_pair.hpp
Normal file
23
include/boost/compressed_pair.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// (C) Copyright Boost.org 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.
|
||||||
|
// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
|
||||||
|
// for full copyright notices.
|
||||||
|
|
||||||
|
#ifndef BOOST_COMPRESSED_PAIR_HPP
|
||||||
|
#define BOOST_COMPRESSED_PAIR_HPP
|
||||||
|
|
||||||
|
#ifndef BOOST_CONFIG_HPP
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
#include <boost/detail/ob_compressed_pair.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/detail/compressed_pair.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BOOST_COMPRESSED_PAIR_HPP
|
62
include/boost/current_function.hpp
Normal file
62
include/boost/current_function.hpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||||
|
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1020
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
|
||||||
|
//
|
||||||
|
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/utility/current_function.html
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void current_function_helper()
|
||||||
|
{
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
|
||||||
|
|
||||||
|
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||||
|
|
||||||
|
#elif defined(__FUNCSIG__)
|
||||||
|
|
||||||
|
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
|
||||||
|
|
||||||
|
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
|
||||||
|
|
||||||
|
# define BOOST_CURRENT_FUNCTION __FUNCTION__
|
||||||
|
|
||||||
|
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
|
||||||
|
|
||||||
|
# define BOOST_CURRENT_FUNCTION __FUNC__
|
||||||
|
|
||||||
|
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||||
|
|
||||||
|
# define BOOST_CURRENT_FUNCTION __func__
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define BOOST_CURRENT_FUNCTION "(unknown)"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
75
include/boost/generator_iterator.hpp
Normal file
75
include/boost/generator_iterator.hpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// (C) Copyright Jens Maurer 2001. 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
|
||||||
|
// 15 Nov 2001 Jens Maurer
|
||||||
|
// created.
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation.
|
||||||
|
|
||||||
|
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||||
|
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||||
|
|
||||||
|
#include <boost/iterator_adaptors.hpp>
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template<class Generator>
|
||||||
|
class generator_iterator_policies
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
generator_iterator_policies() { }
|
||||||
|
|
||||||
|
template<class Base>
|
||||||
|
void initialize(Base& base) {
|
||||||
|
m_value = (*base)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Iter template argument is necessary for compatibility with a MWCW
|
||||||
|
// bug workaround
|
||||||
|
template <class IteratorAdaptor>
|
||||||
|
void increment(IteratorAdaptor& iter) {
|
||||||
|
m_value = (*iter.base())();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IteratorAdaptor>
|
||||||
|
const typename Generator::result_type&
|
||||||
|
dereference(const IteratorAdaptor&) const
|
||||||
|
{ return m_value; }
|
||||||
|
|
||||||
|
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||||
|
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||||
|
{ return x.base() == y.base() &&
|
||||||
|
x.policies().m_value == y.policies().m_value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename Generator::result_type m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Generator>
|
||||||
|
struct generator_iterator_generator
|
||||||
|
{
|
||||||
|
typedef iterator_adaptor<Generator*, generator_iterator_policies<Generator>,
|
||||||
|
typename Generator::result_type, const typename Generator::result_type&,
|
||||||
|
const typename Generator::result_type*, std::input_iterator_tag,
|
||||||
|
long> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Generator>
|
||||||
|
inline typename generator_iterator_generator<Generator>::type
|
||||||
|
make_generator_iterator(Generator & gen)
|
||||||
|
{
|
||||||
|
typedef typename generator_iterator_generator<Generator>::type result_t;
|
||||||
|
return result_t(&gen);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||||
|
|
33
include/boost/next_prior.hpp
Normal file
33
include/boost/next_prior.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Boost next_prior.hpp header file ---------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
|
||||||
|
// and distribute this software is granted provided this copyright
|
||||||
|
// notice appears in all copies. This software is provided "as is" without
|
||||||
|
// express or implied warranty, and with no claim as to its suitability for
|
||||||
|
// any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/utility for documentation.
|
||||||
|
|
||||||
|
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
|
||||||
|
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
// Helper functions for classes like bidirectional iterators not supporting
|
||||||
|
// operator+ and operator-
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// const std::list<T>::iterator p = get_some_iterator();
|
||||||
|
// const std::list<T>::iterator prev = boost::prior(p);
|
||||||
|
|
||||||
|
// Contributed by Dave Abrahams
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T next(T x) { return ++x; }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T prior(T x) { return --x; }
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED
|
33
include/boost/noncopyable.hpp
Normal file
33
include/boost/noncopyable.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Boost noncopyable.hpp header file --------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
|
||||||
|
// and distribute this software is granted provided this copyright
|
||||||
|
// notice appears in all copies. This software is provided "as is" without
|
||||||
|
// express or implied warranty, and with no claim as to its suitability for
|
||||||
|
// any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/utility for documentation.
|
||||||
|
|
||||||
|
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
|
||||||
|
#define BOOST_NONCOPYABLE_HPP_INCLUDED
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
// Private copy constructor and copy assignment ensure classes derived from
|
||||||
|
// class noncopyable cannot be copied.
|
||||||
|
|
||||||
|
// Contributed by Dave Abrahams
|
||||||
|
|
||||||
|
class noncopyable
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
noncopyable() {}
|
||||||
|
~noncopyable() {}
|
||||||
|
private: // emphasize the following members are private
|
||||||
|
noncopyable( const noncopyable& );
|
||||||
|
const noncopyable& operator=( const noncopyable& );
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED
|
957
include/boost/operators.hpp
Normal file
957
include/boost/operators.hpp
Normal file
@@ -0,0 +1,957 @@
|
|||||||
|
// Boost operators.hpp header file ----------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software is
|
||||||
|
// granted provided this copyright notice appears in all copies. This
|
||||||
|
// software is provided "as is" without express or implied warranty, and
|
||||||
|
// with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/utility/operators.htm for documentation.
|
||||||
|
|
||||||
|
// Revision History
|
||||||
|
// 04 May 05 Added operator class bool_testable. (Sam Partington)
|
||||||
|
// 21 Oct 02 Modified implementation of operators to allow compilers with a
|
||||||
|
// correct named return value optimization (NRVO) to produce optimal
|
||||||
|
// code. (Daniel Frey)
|
||||||
|
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
|
||||||
|
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
|
||||||
|
// 27 Aug 01 'left' form for non commutative operators added;
|
||||||
|
// additional classes for groups of related operators added;
|
||||||
|
// workaround for empty base class optimization
|
||||||
|
// bug of GCC 3.0 (Helmut Zeisel)
|
||||||
|
// 25 Jun 01 output_iterator_helper changes: removed default template
|
||||||
|
// parameters, added support for self-proxying, additional
|
||||||
|
// documentation and tests (Aleksey Gurtovoy)
|
||||||
|
// 29 May 01 Added operator classes for << and >>. Added input and output
|
||||||
|
// iterator helper classes. Added classes to connect equality and
|
||||||
|
// relational operators. Added classes for groups of related
|
||||||
|
// operators. Reimplemented example operator and iterator helper
|
||||||
|
// classes in terms of the new groups. (Daryle Walker, with help
|
||||||
|
// from Alexy Gurtovoy)
|
||||||
|
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||||
|
// supplied arguments from actually being used (Dave Abrahams)
|
||||||
|
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||||
|
// refactoring of compiler workarounds, additional documentation
|
||||||
|
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
|
||||||
|
// Dave Abrahams)
|
||||||
|
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
|
||||||
|
// Jeremy Siek (Dave Abrahams)
|
||||||
|
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
|
||||||
|
// (Mark Rodgers)
|
||||||
|
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
|
||||||
|
// 10 Jun 00 Support for the base class chaining technique was added
|
||||||
|
// (Aleksey Gurtovoy). See documentation and the comments below
|
||||||
|
// for the details.
|
||||||
|
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||||
|
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
|
||||||
|
// specializations of dividable, subtractable, modable (Ed Brey)
|
||||||
|
// 17 Nov 99 Add comments (Beman Dawes)
|
||||||
|
// Remove unnecessary specialization of operators<> (Ed Brey)
|
||||||
|
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
|
||||||
|
// operators.(Beman Dawes)
|
||||||
|
// 12 Nov 99 Add operators templates (Ed Brey)
|
||||||
|
// 11 Nov 99 Add single template parameter version for compilers without
|
||||||
|
// partial specialization (Beman Dawes)
|
||||||
|
// 10 Nov 99 Initial version
|
||||||
|
|
||||||
|
// 10 Jun 00:
|
||||||
|
// An additional optional template parameter was added to most of
|
||||||
|
// operator templates to support the base class chaining technique (see
|
||||||
|
// documentation for the details). Unfortunately, a straightforward
|
||||||
|
// implementation of this change would have broken compatibility with the
|
||||||
|
// previous version of the library by making it impossible to use the same
|
||||||
|
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
|
||||||
|
// an operator template. This implementation solves the backward-compatibility
|
||||||
|
// issue at the cost of some simplicity.
|
||||||
|
//
|
||||||
|
// One of the complications is an existence of special auxiliary class template
|
||||||
|
// 'is_chained_base<>' (see 'detail' namespace below), which is used
|
||||||
|
// to determine whether its template parameter is a library's operator template
|
||||||
|
// or not. You have to specialize 'is_chained_base<>' for each new
|
||||||
|
// operator template you add to the library.
|
||||||
|
//
|
||||||
|
// However, most of the non-trivial implementation details are hidden behind
|
||||||
|
// several local macros defined below, and as soon as you understand them,
|
||||||
|
// you understand the whole library implementation.
|
||||||
|
|
||||||
|
#ifndef BOOST_OPERATORS_HPP
|
||||||
|
#define BOOST_OPERATORS_HPP
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/preprocessor/seq/cat.hpp>
|
||||||
|
|
||||||
|
#if defined(__sgi) && !defined(__GNUC__)
|
||||||
|
# pragma set woff 1234
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_MSVC)
|
||||||
|
# pragma warning( disable : 4284 ) // complaint about return type of
|
||||||
|
#endif // operator-> not begin a UDT
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
|
||||||
|
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
|
||||||
|
class empty_base {
|
||||||
|
bool dummy;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class empty_base {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
// In this section we supply the xxxx1 and xxxx2 forms of the operator
|
||||||
|
// templates, which are explicitly targeted at the 1-type-argument and
|
||||||
|
// 2-type-argument operator forms, respectively. Some compilers get confused
|
||||||
|
// when inline friend functions are overloaded in namespaces other than the
|
||||||
|
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
|
||||||
|
// these templates must go in the global namespace.
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Basic operator classes (contributed by Dave Abrahams) ------------------//
|
||||||
|
|
||||||
|
// Note that friend functions defined in a class are implicitly inline.
|
||||||
|
// See the C++ std, 11.4 [class.friend] paragraph 5
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct less_than_comparable2 : B
|
||||||
|
{
|
||||||
|
friend bool operator<=(const T& x, const U& y) { return !(x > y); }
|
||||||
|
friend bool operator>=(const T& x, const U& y) { return !(x < y); }
|
||||||
|
friend bool operator>(const U& x, const T& y) { return y < x; }
|
||||||
|
friend bool operator<(const U& x, const T& y) { return y > x; }
|
||||||
|
friend bool operator<=(const U& x, const T& y) { return !(y < x); }
|
||||||
|
friend bool operator>=(const U& x, const T& y) { return !(y > x); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct less_than_comparable1 : B
|
||||||
|
{
|
||||||
|
friend bool operator>(const T& x, const T& y) { return y < x; }
|
||||||
|
friend bool operator<=(const T& x, const T& y) { return !(y < x); }
|
||||||
|
friend bool operator>=(const T& x, const T& y) { return !(x < y); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct equality_comparable2 : B
|
||||||
|
{
|
||||||
|
friend bool operator==(const U& y, const T& x) { return x == y; }
|
||||||
|
friend bool operator!=(const U& y, const T& x) { return !(x == y); }
|
||||||
|
friend bool operator!=(const T& y, const U& x) { return !(y == x); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct equality_comparable1 : B
|
||||||
|
{
|
||||||
|
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// A macro which produces "name_2left" from "name".
|
||||||
|
#define BOOST_OPERATOR2_LEFT(name) BOOST_PP_SEQ_CAT_S(1,(name)(2)(_)(left))
|
||||||
|
|
||||||
|
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
|
||||||
|
|
||||||
|
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||||
|
|
||||||
|
// This is the optimal implementation for ISO/ANSI C++,
|
||||||
|
// but it requires the compiler to implement the NRVO.
|
||||||
|
// If the compiler has no NRVO, this is the best symmetric
|
||||||
|
// implementation available.
|
||||||
|
|
||||||
|
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##2 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||||
|
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##1 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##2 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##1 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||||
|
|
||||||
|
// For compilers without NRVO the following code is optimal, but not
|
||||||
|
// symmetric! Note that the implementation of
|
||||||
|
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
|
||||||
|
// optimization opportunities to the compiler :)
|
||||||
|
|
||||||
|
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##2 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||||
|
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##1 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##2 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const U& lhs, const T& rhs ) \
|
||||||
|
{ return T( lhs ) OP##= rhs; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##1 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||||
|
|
||||||
|
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
|
||||||
|
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
|
||||||
|
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
|
||||||
|
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
|
||||||
|
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
|
||||||
|
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
|
||||||
|
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
|
||||||
|
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
|
||||||
|
|
||||||
|
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
|
||||||
|
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
|
||||||
|
#undef BOOST_OPERATOR2_LEFT
|
||||||
|
|
||||||
|
// incrementable and decrementable contributed by Jeremy Siek
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct incrementable : B
|
||||||
|
{
|
||||||
|
friend T operator++(T& x, int)
|
||||||
|
{
|
||||||
|
incrementable_type nrv(x);
|
||||||
|
++x;
|
||||||
|
return nrv;
|
||||||
|
}
|
||||||
|
private: // The use of this typedef works around a Borland bug
|
||||||
|
typedef T incrementable_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct decrementable : B
|
||||||
|
{
|
||||||
|
friend T operator--(T& x, int)
|
||||||
|
{
|
||||||
|
decrementable_type nrv(x);
|
||||||
|
--x;
|
||||||
|
return nrv;
|
||||||
|
}
|
||||||
|
private: // The use of this typedef works around a Borland bug
|
||||||
|
typedef T decrementable_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
|
||||||
|
|
||||||
|
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||||
|
struct dereferenceable : B
|
||||||
|
{
|
||||||
|
P operator->() const
|
||||||
|
{
|
||||||
|
return &*static_cast<const T&>(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class I, class R, class B = ::boost::detail::empty_base>
|
||||||
|
struct indexable : B
|
||||||
|
{
|
||||||
|
R operator[](I n) const
|
||||||
|
{
|
||||||
|
return *(static_cast<const T&>(*this) + n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// bool_testable -----------------------------------------------------------//
|
||||||
|
// (contributed by Sam Partington, David Abrahams and Daniel Frey) ---------//
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct bool_testable : B
|
||||||
|
{
|
||||||
|
friend bool operator!(const T& t) { return !static_cast<bool>(t); }
|
||||||
|
private:
|
||||||
|
typedef signed char private_number_type;
|
||||||
|
operator private_number_type() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// More operator classes (contributed by Daryle Walker) --------------------//
|
||||||
|
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
|
||||||
|
|
||||||
|
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||||
|
|
||||||
|
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##2 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const T& lhs, const U& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##1 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( const T& lhs, const T& rhs ) \
|
||||||
|
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||||
|
|
||||||
|
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##2 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct NAME##1 : B \
|
||||||
|
{ \
|
||||||
|
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||||
|
|
||||||
|
BOOST_BINARY_OPERATOR( left_shiftable, << )
|
||||||
|
BOOST_BINARY_OPERATOR( right_shiftable, >> )
|
||||||
|
|
||||||
|
#undef BOOST_BINARY_OPERATOR
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct equivalent2 : B
|
||||||
|
{
|
||||||
|
friend bool operator==(const T& x, const U& y)
|
||||||
|
{
|
||||||
|
return !(x < y) && !(x > y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct equivalent1 : B
|
||||||
|
{
|
||||||
|
friend bool operator==(const T&x, const T&y)
|
||||||
|
{
|
||||||
|
return !(x < y) && !(y < x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct partially_ordered2 : B
|
||||||
|
{
|
||||||
|
friend bool operator<=(const T& x, const U& y)
|
||||||
|
{ return (x < y) || (x == y); }
|
||||||
|
friend bool operator>=(const T& x, const U& y)
|
||||||
|
{ return (x > y) || (x == y); }
|
||||||
|
friend bool operator>(const U& x, const T& y)
|
||||||
|
{ return y < x; }
|
||||||
|
friend bool operator<(const U& x, const T& y)
|
||||||
|
{ return y > x; }
|
||||||
|
friend bool operator<=(const U& x, const T& y)
|
||||||
|
{ return (y > x) || (y == x); }
|
||||||
|
friend bool operator>=(const U& x, const T& y)
|
||||||
|
{ return (y < x) || (y == x); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct partially_ordered1 : B
|
||||||
|
{
|
||||||
|
friend bool operator>(const T& x, const T& y)
|
||||||
|
{ return y < x; }
|
||||||
|
friend bool operator<=(const T& x, const T& y)
|
||||||
|
{ return (x < y) || (x == y); }
|
||||||
|
friend bool operator>=(const T& x, const T& y)
|
||||||
|
{ return (y < x) || (x == y); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Combined operator classes (contributed by Daryle Walker) ----------------//
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct totally_ordered2
|
||||||
|
: less_than_comparable2<T, U
|
||||||
|
, equality_comparable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct totally_ordered1
|
||||||
|
: less_than_comparable1<T
|
||||||
|
, equality_comparable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct additive2
|
||||||
|
: addable2<T, U
|
||||||
|
, subtractable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct additive1
|
||||||
|
: addable1<T
|
||||||
|
, subtractable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct multiplicative2
|
||||||
|
: multipliable2<T, U
|
||||||
|
, dividable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct multiplicative1
|
||||||
|
: multipliable1<T
|
||||||
|
, dividable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_multiplicative2
|
||||||
|
: multiplicative2<T, U
|
||||||
|
, modable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_multiplicative1
|
||||||
|
: multiplicative1<T
|
||||||
|
, modable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct arithmetic2
|
||||||
|
: additive2<T, U
|
||||||
|
, multiplicative2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct arithmetic1
|
||||||
|
: additive1<T
|
||||||
|
, multiplicative1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_arithmetic2
|
||||||
|
: additive2<T, U
|
||||||
|
, integer_multiplicative2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_arithmetic1
|
||||||
|
: additive1<T
|
||||||
|
, integer_multiplicative1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct bitwise2
|
||||||
|
: xorable2<T, U
|
||||||
|
, andable2<T, U
|
||||||
|
, orable2<T, U, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct bitwise1
|
||||||
|
: xorable1<T
|
||||||
|
, andable1<T
|
||||||
|
, orable1<T, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct unit_steppable
|
||||||
|
: incrementable<T
|
||||||
|
, decrementable<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct shiftable2
|
||||||
|
: left_shiftable2<T, U
|
||||||
|
, right_shiftable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct shiftable1
|
||||||
|
: left_shiftable1<T
|
||||||
|
, right_shiftable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct ring_operators2
|
||||||
|
: additive2<T, U
|
||||||
|
, subtractable2_left<T, U
|
||||||
|
, multipliable2<T, U, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct ring_operators1
|
||||||
|
: additive1<T
|
||||||
|
, multipliable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct ordered_ring_operators2
|
||||||
|
: ring_operators2<T, U
|
||||||
|
, totally_ordered2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct ordered_ring_operators1
|
||||||
|
: ring_operators1<T
|
||||||
|
, totally_ordered1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct field_operators2
|
||||||
|
: ring_operators2<T, U
|
||||||
|
, dividable2<T, U
|
||||||
|
, dividable2_left<T, U, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct field_operators1
|
||||||
|
: ring_operators1<T
|
||||||
|
, dividable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct ordered_field_operators2
|
||||||
|
: field_operators2<T, U
|
||||||
|
, totally_ordered2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct ordered_field_operators1
|
||||||
|
: field_operators1<T
|
||||||
|
, totally_ordered1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct euclidian_ring_operators2
|
||||||
|
: ring_operators2<T, U
|
||||||
|
, dividable2<T, U
|
||||||
|
, dividable2_left<T, U
|
||||||
|
, modable2<T, U
|
||||||
|
, modable2_left<T, U, B
|
||||||
|
> > > > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct euclidian_ring_operators1
|
||||||
|
: ring_operators1<T
|
||||||
|
, dividable1<T
|
||||||
|
, modable1<T, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct ordered_euclidian_ring_operators2
|
||||||
|
: totally_ordered2<T, U
|
||||||
|
, euclidian_ring_operators2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct ordered_euclidian_ring_operators1
|
||||||
|
: totally_ordered1<T
|
||||||
|
, euclidian_ring_operators1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||||
|
struct input_iteratable
|
||||||
|
: equality_comparable1<T
|
||||||
|
, incrementable<T
|
||||||
|
, dereferenceable<T, P, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct output_iteratable
|
||||||
|
: incrementable<T, B
|
||||||
|
> {};
|
||||||
|
|
||||||
|
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||||
|
struct forward_iteratable
|
||||||
|
: input_iteratable<T, P, B
|
||||||
|
> {};
|
||||||
|
|
||||||
|
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||||
|
struct bidirectional_iteratable
|
||||||
|
: forward_iteratable<T, P
|
||||||
|
, decrementable<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
// To avoid repeated derivation from equality_comparable,
|
||||||
|
// which is an indirect base class of bidirectional_iterable,
|
||||||
|
// random_access_iteratable must not be derived from totally_ordered1
|
||||||
|
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||||
|
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
|
||||||
|
struct random_access_iteratable
|
||||||
|
: bidirectional_iteratable<T, P
|
||||||
|
, less_than_comparable1<T
|
||||||
|
, additive2<T, D
|
||||||
|
, indexable<T, D, R, B
|
||||||
|
> > > > {};
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
} // namespace boost
|
||||||
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
|
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
|
||||||
|
//
|
||||||
|
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
||||||
|
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||||
|
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
|
||||||
|
// two-argument forms. Note that these macros expect to be invoked from within
|
||||||
|
// boost.
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
// The template is already in boost so we have nothing to do.
|
||||||
|
# define BOOST_IMPORT_TEMPLATE4(template_name)
|
||||||
|
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
||||||
|
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||||
|
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||||
|
|
||||||
|
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
# ifndef BOOST_NO_USING_TEMPLATE
|
||||||
|
|
||||||
|
// Bring the names in with a using-declaration
|
||||||
|
// to avoid stressing the compiler.
|
||||||
|
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
|
||||||
|
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
|
||||||
|
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
||||||
|
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
|
||||||
|
// from working, we are forced to use inheritance for that compiler.
|
||||||
|
# define BOOST_IMPORT_TEMPLATE4(template_name) \
|
||||||
|
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
|
||||||
|
struct template_name : ::template_name<T, U, V, W, B> {};
|
||||||
|
|
||||||
|
# define BOOST_IMPORT_TEMPLATE3(template_name) \
|
||||||
|
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
|
||||||
|
struct template_name : ::template_name<T, U, V, B> {};
|
||||||
|
|
||||||
|
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
|
struct template_name : ::template_name<T, U, B> {};
|
||||||
|
|
||||||
|
# define BOOST_IMPORT_TEMPLATE1(template_name) \
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct template_name : ::template_name<T, B> {};
|
||||||
|
|
||||||
|
# endif // BOOST_NO_USING_TEMPLATE
|
||||||
|
|
||||||
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
//
|
||||||
|
// Here's where we put it all together, defining the xxxx forms of the templates
|
||||||
|
// in namespace boost. We also define specializations of is_chained_base<> for
|
||||||
|
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||||
|
// neccessary.
|
||||||
|
//
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
// is_chained_base<> - a traits class used to distinguish whether an operator
|
||||||
|
// template argument is being used for base class chaining, or is specifying a
|
||||||
|
// 2nd argument type.
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
// A type parameter is used instead of a plain bool because Borland's compiler
|
||||||
|
// didn't cope well with the more obvious non-type template parameter.
|
||||||
|
namespace detail {
|
||||||
|
struct true_t {};
|
||||||
|
struct false_t {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// Unspecialized version assumes that most types are not being used for base
|
||||||
|
// class chaining. We specialize for the operator templates defined in this
|
||||||
|
// library.
|
||||||
|
template<class T> struct is_chained_base {
|
||||||
|
typedef ::boost::detail::false_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
// Import a 4-type-argument operator template into boost (if neccessary) and
|
||||||
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||||
|
BOOST_IMPORT_TEMPLATE4(template_name4) \
|
||||||
|
template<class T, class U, class V, class W, class B> \
|
||||||
|
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
||||||
|
typedef ::boost::detail::true_t value; \
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import a 3-type-argument operator template into boost (if neccessary) and
|
||||||
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||||
|
BOOST_IMPORT_TEMPLATE3(template_name3) \
|
||||||
|
template<class T, class U, class V, class B> \
|
||||||
|
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
|
||||||
|
typedef ::boost::detail::true_t value; \
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import a 2-type-argument operator template into boost (if neccessary) and
|
||||||
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
|
BOOST_IMPORT_TEMPLATE2(template_name2) \
|
||||||
|
template<class T, class U, class B> \
|
||||||
|
struct is_chained_base< ::boost::template_name2<T, U, B> > { \
|
||||||
|
typedef ::boost::detail::true_t value; \
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import a 1-type-argument operator template into boost (if neccessary) and
|
||||||
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||||
|
BOOST_IMPORT_TEMPLATE1(template_name1) \
|
||||||
|
template<class T, class B> \
|
||||||
|
struct is_chained_base< ::boost::template_name1<T, B> > { \
|
||||||
|
typedef ::boost::detail::true_t value; \
|
||||||
|
};
|
||||||
|
|
||||||
|
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
|
||||||
|
// can be used for specifying both 1-argument and 2-argument forms. Requires the
|
||||||
|
// existence of two previously defined class templates named '<template_name>1'
|
||||||
|
// and '<template_name>2' which must implement the corresponding 1- and 2-
|
||||||
|
// argument forms.
|
||||||
|
//
|
||||||
|
// The template type parameter O == is_chained_base<U>::value is used to
|
||||||
|
// distinguish whether the 2nd argument to <template_name> is being used for
|
||||||
|
// base class chaining from another boost operator template or is describing a
|
||||||
|
// 2nd operand type. O == true_t only when U is actually an another operator
|
||||||
|
// template from the library. Partial specialization is used to select an
|
||||||
|
// implementation in terms of either '<template_name>1' or '<template_name>2'.
|
||||||
|
//
|
||||||
|
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE(template_name) \
|
||||||
|
template <class T \
|
||||||
|
,class U = T \
|
||||||
|
,class B = ::boost::detail::empty_base \
|
||||||
|
,class O = typename is_chained_base<U>::value \
|
||||||
|
> \
|
||||||
|
struct template_name : template_name##2<T, U, B> {}; \
|
||||||
|
\
|
||||||
|
template<class T, class U, class B> \
|
||||||
|
struct template_name<T, U, B, ::boost::detail::true_t> \
|
||||||
|
: template_name##1<T, U> {}; \
|
||||||
|
\
|
||||||
|
template <class T, class B> \
|
||||||
|
struct template_name<T, T, B, ::boost::detail::false_t> \
|
||||||
|
: template_name##1<T, B> {}; \
|
||||||
|
\
|
||||||
|
template<class T, class U, class B, class O> \
|
||||||
|
struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
|
||||||
|
typedef ::boost::detail::true_t value; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
||||||
|
|
||||||
|
|
||||||
|
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||||
|
BOOST_IMPORT_TEMPLATE4(template_name4)
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||||
|
BOOST_IMPORT_TEMPLATE3(template_name3)
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
|
BOOST_IMPORT_TEMPLATE2(template_name2)
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||||
|
BOOST_IMPORT_TEMPLATE1(template_name1)
|
||||||
|
|
||||||
|
// In this case we can only assume that template_name<> is equivalent to the
|
||||||
|
// more commonly needed template_name1<> form.
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE(template_name) \
|
||||||
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
|
struct template_name : template_name##1<T, B> {};
|
||||||
|
|
||||||
|
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(addable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(modable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(andable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(orable)
|
||||||
|
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||||
|
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE3(indexable)
|
||||||
|
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(bool_testable)
|
||||||
|
|
||||||
|
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||||
|
|
||||||
|
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(additive)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(bitwise)
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(shiftable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(ring_operators)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(field_operators)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
|
||||||
|
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE4
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE3
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE2
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE1
|
||||||
|
#undef BOOST_IMPORT_TEMPLATE1
|
||||||
|
#undef BOOST_IMPORT_TEMPLATE2
|
||||||
|
#undef BOOST_IMPORT_TEMPLATE3
|
||||||
|
#undef BOOST_IMPORT_TEMPLATE4
|
||||||
|
|
||||||
|
// The following 'operators' classes can only be used portably if the derived class
|
||||||
|
// declares ALL of the required member operators.
|
||||||
|
template <class T, class U>
|
||||||
|
struct operators2
|
||||||
|
: totally_ordered2<T,U
|
||||||
|
, integer_arithmetic2<T,U
|
||||||
|
, bitwise2<T,U
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
template <class T, class U = T>
|
||||||
|
struct operators : operators2<T, U> {};
|
||||||
|
|
||||||
|
template <class T> struct operators<T, T>
|
||||||
|
#else
|
||||||
|
template <class T> struct operators
|
||||||
|
#endif
|
||||||
|
: totally_ordered<T
|
||||||
|
, integer_arithmetic<T
|
||||||
|
, bitwise<T
|
||||||
|
, unit_steppable<T
|
||||||
|
> > > > {};
|
||||||
|
|
||||||
|
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
||||||
|
// (Input and output iterator helpers contributed by Daryle Walker) -------//
|
||||||
|
// (Changed to use combined operator classes by Daryle Walker) ------------//
|
||||||
|
template <class T,
|
||||||
|
class V,
|
||||||
|
class D = std::ptrdiff_t,
|
||||||
|
class P = V const *,
|
||||||
|
class R = V const &>
|
||||||
|
struct input_iterator_helper
|
||||||
|
: input_iteratable<T, P
|
||||||
|
, boost::iterator<std::input_iterator_tag, V, D, P, R
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct output_iterator_helper
|
||||||
|
: output_iteratable<T
|
||||||
|
, boost::iterator<std::output_iterator_tag, void, void, void, void
|
||||||
|
> >
|
||||||
|
{
|
||||||
|
T& operator*() { return static_cast<T&>(*this); }
|
||||||
|
T& operator++() { return static_cast<T&>(*this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
class V,
|
||||||
|
class D = std::ptrdiff_t,
|
||||||
|
class P = V*,
|
||||||
|
class R = V&>
|
||||||
|
struct forward_iterator_helper
|
||||||
|
: forward_iteratable<T, P
|
||||||
|
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
class V,
|
||||||
|
class D = std::ptrdiff_t,
|
||||||
|
class P = V*,
|
||||||
|
class R = V&>
|
||||||
|
struct bidirectional_iterator_helper
|
||||||
|
: bidirectional_iteratable<T, P
|
||||||
|
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
class V,
|
||||||
|
class D = std::ptrdiff_t,
|
||||||
|
class P = V*,
|
||||||
|
class R = V&>
|
||||||
|
struct random_access_iterator_helper
|
||||||
|
: random_access_iteratable<T, P, D, R
|
||||||
|
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||||
|
> >
|
||||||
|
{
|
||||||
|
friend D requires_difference_operator(const T& x, const T& y) {
|
||||||
|
return x - y;
|
||||||
|
}
|
||||||
|
}; // random_access_iterator_helper
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#if defined(__sgi) && !defined(__GNUC__)
|
||||||
|
#pragma reset woff 1234
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BOOST_OPERATORS_HPP
|
163
include/boost/ref.hpp
Normal file
163
include/boost/ref.hpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#ifndef BOOST_REF_HPP_INCLUDED
|
||||||
|
# define BOOST_REF_HPP_INCLUDED
|
||||||
|
|
||||||
|
# if _MSC_VER+0 >= 1020
|
||||||
|
# pragma once
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include <boost/config.hpp>
|
||||||
|
# include <boost/utility/addressof.hpp>
|
||||||
|
# include <boost/mpl/bool.hpp>
|
||||||
|
|
||||||
|
//
|
||||||
|
// ref.hpp - ref/cref, useful helper functions
|
||||||
|
//
|
||||||
|
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
|
||||||
|
// Copyright (C) 2001, 2002 Peter Dimov
|
||||||
|
// Copyright (C) 2002 David Abrahams
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org/libs/bind/ref.html for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class reference_wrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T type;
|
||||||
|
|
||||||
|
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||||
|
|
||||||
|
explicit reference_wrapper(T& t): t_(&t) {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
explicit reference_wrapper(T& t): t_(addressof(t)) {}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
operator T& () const { return *t_; }
|
||||||
|
|
||||||
|
T& get() const { return *t_; }
|
||||||
|
|
||||||
|
T* get_pointer() const { return t_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T* t_;
|
||||||
|
};
|
||||||
|
|
||||||
|
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
|
||||||
|
# define BOOST_REF_CONST
|
||||||
|
# else
|
||||||
|
# define BOOST_REF_CONST const
|
||||||
|
# endif
|
||||||
|
|
||||||
|
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
|
||||||
|
{
|
||||||
|
return reference_wrapper<T>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
|
||||||
|
{
|
||||||
|
return reference_wrapper<T const>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
# undef BOOST_REF_CONST
|
||||||
|
|
||||||
|
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
template<typename T>
|
||||||
|
class is_reference_wrapper
|
||||||
|
: public mpl::false_
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class is_reference_wrapper<reference_wrapper<T> >
|
||||||
|
: public mpl::true_
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class unwrap_reference
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class unwrap_reference<reference_wrapper<T> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
# else // no partial specialization
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/type.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
typedef char (&yes_reference_wrapper_t)[1];
|
||||||
|
typedef char (&no_reference_wrapper_t)[2];
|
||||||
|
|
||||||
|
no_reference_wrapper_t is_reference_wrapper_test(...);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
|
||||||
|
|
||||||
|
template<bool wrapped>
|
||||||
|
struct reference_unwrapper
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct reference_unwrapper<true>
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct apply
|
||||||
|
{
|
||||||
|
typedef typename T::type type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class is_reference_wrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BOOST_STATIC_CONSTANT(
|
||||||
|
bool, value = (
|
||||||
|
sizeof(detail::is_reference_wrapper_test(type<T>()))
|
||||||
|
== sizeof(detail::yes_reference_wrapper_t)));
|
||||||
|
|
||||||
|
typedef ::boost::mpl::bool_<value> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class unwrap_reference
|
||||||
|
: public detail::reference_unwrapper<
|
||||||
|
is_reference_wrapper<T>::value
|
||||||
|
>::template apply<T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_REF_HPP_INCLUDED
|
21
include/boost/utility.hpp
Normal file
21
include/boost/utility.hpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Boost utility.hpp header file -------------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
|
||||||
|
// and distribute this software is granted provided this copyright
|
||||||
|
// notice appears in all copies. This software is provided "as is" without
|
||||||
|
// express or implied warranty, and with no claim as to its suitability for
|
||||||
|
// any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/utility for documentation.
|
||||||
|
|
||||||
|
#ifndef BOOST_UTILITY_HPP
|
||||||
|
#define BOOST_UTILITY_HPP
|
||||||
|
|
||||||
|
#include <boost/utility/addressof.hpp>
|
||||||
|
#include <boost/utility/base_from_member.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/next_prior.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_UTILITY_HPP
|
||||||
|
|
34
include/boost/utility_fwd.hpp
Normal file
34
include/boost/utility_fwd.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Boost utility_fwd.hpp header file ---------------------------------------//
|
||||||
|
|
||||||
|
// (C) Copyright boost.org 2001. Permission to copy, use, modify, sell
|
||||||
|
// and distribute this software is granted provided this copyright
|
||||||
|
// notice appears in all copies. This software is provided "as is" without
|
||||||
|
// express or implied warranty, and with no claim as to its suitability for
|
||||||
|
// any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/utility for documentation.
|
||||||
|
|
||||||
|
#ifndef BOOST_UTILITY_FWD_HPP
|
||||||
|
#define BOOST_UTILITY_FWD_HPP
|
||||||
|
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// From <boost/utility/base_from_member.hpp> -------------------------------//
|
||||||
|
|
||||||
|
template < typename MemberType, int UniqueID = 0 >
|
||||||
|
class base_from_member;
|
||||||
|
|
||||||
|
|
||||||
|
// From <boost/utility.hpp> ------------------------------------------------//
|
||||||
|
|
||||||
|
class noncopyable;
|
||||||
|
|
||||||
|
// Also has a few function templates
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_UTILITY_FWD_HPP
|
Reference in New Issue
Block a user