Compare commits

..

6 Commits

Author SHA1 Message Date
Jeremy Siek
50817f6339 Added traits arguments to the iterator adaptor classes for vc++ port.
[SVN r7671]
2000-08-01 00:45:42 +00:00
Dave Abrahams
2bd78704cc A first stab at vc6 compatibility
[SVN r7668]
2000-07-31 15:39:33 +00:00
Jeremy Siek
cf7f110c89 added include for algorithms
[SVN r7654]
2000-07-27 18:35:03 +00:00
Jeremy Siek
e8deb965a1 new files for iterator_adaptors, includes testing, examples, and documentation
[SVN r7651]
2000-07-27 17:59:40 +00:00
nobody
8454835ac4 This commit was manufactured by cvs2svn to create branch
'iterator-adaptors'.

[SVN r7633]
2000-07-26 20:32:15 +00:00
Beman Dawes
13f6d43e5e 1.16.1 initial CVS checkin
[SVN r7620]
2000-07-07 16:04:40 +00:00
34 changed files with 3453 additions and 2358 deletions

423
algo_opt_examples.cpp Normal file
View File

@@ -0,0 +1,423 @@
/*
*
* Copyright (c) 1999
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* This file provides some example of type_traits usage -
* by "optimising" various algorithms:
*
* opt::copy - optimised for trivial copy (cf std::copy)
* opt::fill - optimised for trivial copy/small types (cf std::fill)
* opt::destroy_array - an example of optimisation based upon omitted destructor calls
* opt::iter_swap - uses type_traits to determine whether the iterator is a proxy
* in which case it uses a "safe" approach, otherwise calls swap
* on the assumption that swap may be specialised for the pointed-to type.
*
*/
/* Release notes:
23rd July 2000:
Added explicit failure for broken compilers that don't support these examples.
Fixed broken gcc support (broken using directive).
Reordered tests slightly.
*/
#include <iostream>
#include <typeinfo>
#include <algorithm>
#include <iterator>
#include <vector>
#include <memory>
#include <boost/timer.hpp>
#include <boost/type_traits.hpp>
#include <boost/call_traits.hpp>
using std::cout;
using std::endl;
using std::cin;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#error "Sorry, without template partial specialisation support there isn't anything to test here..."
#endif
namespace opt{
//
// algorithm destroy_arry:
// The reverse of std::unitialized_copy, takes a block of
// unitialized memory and calls destructors on all objects therein.
//
namespace detail{
template <bool>
struct array_destroyer
{
template <class T>
static void destroy_array(T* i, T* j){ do_destroy_array(i, j); }
};
template <>
struct array_destroyer<true>
{
template <class T>
static void destroy_array(T*, T*){}
};
template <class T>
void do_destroy_array(T* first, T* last)
{
while(first != last)
{
first->~T();
++first;
}
}
}; // namespace detail
template <class T>
inline void destroy_array(T* p1, T* p2)
{
detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2);
}
//
// unoptimised versions of destroy_array:
//
template <class T>
void destroy_array1(T* first, T* last)
{
while(first != last)
{
first->~T();
++first;
}
}
template <class T>
void destroy_array2(T* first, T* last)
{
for(; first != last; ++first) first->~T();
}
//
// opt::copy
// same semantics as std::copy
// calls memcpy where appropiate.
//
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);
}
//
// fill
// same as std::fill, uses memset where appropriate, along with call_traits
// to "optimise" parameter passing.
//
namespace detail{
template <bool opt>
struct filler
{
template <typename I, typename T>
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
};
template <bool b>
template <typename I, typename T>
void filler<b>::do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
{
while(first != last)
{
*first = val;
++first;
}
}
template <>
struct filler<true>
{
template <typename I, typename T>
static void do_fill(I first, I last, T val)
{
memset(first, val, last-first);
}
};
}
template <class I, class T>
inline void fill(I first, I last, const T& val)
{
enum{ can_opt = boost::is_pointer<I>::value
&& boost::is_arithmetic<T>::value
&& (sizeof(T) == 1) };
typedef detail::filler<can_opt> filler_t;
filler_t::template do_fill<I,T>(first, last, val);
}
//
// iter_swap:
// tests whether iterator is a proxying iterator or not, and
// uses optimal form accordingly:
//
namespace detail{
template <bool b>
struct swapper
{
template <typename I>
static void do_swap(I one, I two)
{
typedef typename std::iterator_traits<I>::value_type v_t;
v_t v = *one;
*one = *two;
*two = v;
}
};
#ifdef __GNUC__
using std::swap;
#endif
template <>
struct swapper<true>
{
template <typename I>
static void do_swap(I one, I two)
{
using std::swap;
swap(*one, *two);
}
};
}
template <typename I1, typename I2>
inline void iter_swap(I1 one, I2 two)
{
typedef typename std::iterator_traits<I1>::reference r1_t;
typedef typename std::iterator_traits<I2>::reference r2_t;
enum{ can_opt = boost::is_reference<r1_t>::value && boost::is_reference<r2_t>::value && boost::is_same<r1_t, r2_t>::value };
detail::swapper<can_opt>::do_swap(one, two);
}
}; // namespace opt
//
// define some global data:
//
const int array_size = 1000;
int i_array[array_size] = {0,};
const int ci_array[array_size] = {0,};
char c_array[array_size] = {0,};
const char cc_array[array_size] = { 0,};
const int iter_count = 1000000;
int main()
{
//
// test destroy_array,
// compare destruction time of an array of ints
// with unoptimised form.
//
cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
cout << "testing destroy_array...\n"
"[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl;
/*cache load*/ opt::destroy_array(i_array, i_array + array_size);
boost::timer t;
double result;
int i;
for(i = 0; i < iter_count; ++i)
{
opt::destroy_array(i_array, i_array + array_size);
}
result = t.elapsed();
cout << "destroy_array<int>: " << result << endl;
/*cache load*/ opt::destroy_array1(i_array, i_array + array_size);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::destroy_array1(i_array, i_array + array_size);
}
result = t.elapsed();
cout << "destroy_array<int>(unoptimised#1): " << result << endl;
/*cache load*/ opt::destroy_array2(i_array, i_array + array_size);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::destroy_array2(i_array, i_array + array_size);
}
result = t.elapsed();
cout << "destroy_array<int>(unoptimised#2): " << result << endl << endl;
cout << "testing fill(char)...\n"
"[Some standard library versions may already perform this optimisation.]" << endl;
/*cache load*/ opt::fill<char*, char>(c_array, c_array + array_size, (char)3);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::fill<char*, char>(c_array, c_array + array_size, (char)3);
}
result = t.elapsed();
cout << "opt::fill<char*, char>: " << result << endl;
/*cache load*/ std::fill(c_array, c_array + array_size, (char)3);
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::fill(c_array, c_array + array_size, (char)3);
}
result = t.elapsed();
cout << "std::fill<char*, char>: " << result << endl << endl;
cout << "testing fill(int)...\n"
"[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl;
/*cache load*/ opt::fill<int*, int>(i_array, i_array + array_size, 3);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::fill<int*, int>(i_array, i_array + array_size, 3);
}
result = t.elapsed();
cout << "opt::fill<int*, int>: " << result << endl;
/*cache load*/ std::fill(i_array, i_array + array_size, 3);
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::fill(i_array, i_array + array_size, 3);
}
result = t.elapsed();
cout << "std::fill<int*, int>: " << result << endl << endl;
cout << "testing copy...\n"
"[Some standard library versions may already perform this optimisation.]" << endl;
/*cache load*/ opt::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
}
result = t.elapsed();
cout << "opt::copy<const int*, int*>: " << result << endl;
/*cache load*/ std::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
}
result = t.elapsed();
cout << "std::copy<const int*, int*>: " << result << endl;
/*cache load*/ opt::detail::copier<false>::template do_copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::detail::copier<false>::template do_copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
}
result = t.elapsed();
cout << "standard \"unoptimised\" copy: " << result << endl << endl;
/*cache load*/ opt::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
}
result = t.elapsed();
cout << "opt::copy<const char*, char*>: " << result << endl;
/*cache load*/ std::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
t.restart();
for(i = 0; i < iter_count; ++i)
{
std::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
}
result = t.elapsed();
cout << "std::copy<const char*, char*>: " << result << endl;
/*cache load*/ opt::detail::copier<false>::template do_copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
t.restart();
for(i = 0; i < iter_count; ++i)
{
opt::detail::copier<false>::template do_copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
}
result = t.elapsed();
cout << "standard \"unoptimised\" copy: " << result << endl << endl;
//
// testing iter_swap
// really just a check that it does in fact compile...
std::vector<int> v1;
v1.push_back(0);
v1.push_back(1);
std::vector<bool> v2;
v2.push_back(0);
v2.push_back(1);
opt::iter_swap(v1.begin(), v1.begin()+1);
opt::iter_swap(v2.begin(), v2.begin()+1);
cout << "Press any key to exit...";
cin.get();
}

368
call_traits_test.cpp Normal file
View File

@@ -0,0 +1,368 @@
#include <cassert>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <typeinfo>
#include <boost/call_traits.hpp>
#ifdef __BORLANDC__
// turn off some warnings, the way we do the tests will generate a *lot* of these
// this is a result of the tests not call_traits itself....
#pragma option -w-8004 -w-ccc -w-rch -w-eff -w-aus
#endif
//
// struct contained models a type that contains a type (for example std::pair)
// arrays are contained by value, and have to be treated as a special case:
//
template <class T>
struct contained
{
// define our typedefs first, arrays are stored by value
// so value_type is not the same as result_type:
typedef typename boost::call_traits<T>::param_type param_type;
typedef typename boost::call_traits<T>::reference reference;
typedef typename boost::call_traits<T>::const_reference const_reference;
typedef T value_type;
typedef typename boost::call_traits<T>::value_type result_type;
// stored value:
value_type v_;
// constructors:
contained() {}
contained(param_type p) : v_(p){}
// return byval:
result_type value()const { return v_; }
// return by_ref:
reference get() { return v_; }
const_reference const_get()const { return v_; }
// pass value:
void call(param_type p){}
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, std::size_t N>
struct contained<T[N]>
{
typedef typename boost::call_traits<T[N]>::param_type param_type;
typedef typename boost::call_traits<T[N]>::reference reference;
typedef typename boost::call_traits<T[N]>::const_reference const_reference;
typedef T value_type[N];
typedef typename boost::call_traits<T[N]>::value_type result_type;
value_type v_;
contained(param_type p)
{
std::copy(p, p+N, v_);
}
// return byval:
result_type value()const { return v_; }
// return by_ref:
reference get() { return v_; }
const_reference const_get()const { return v_; }
void call(param_type p){}
};
#endif
template <class T>
contained<typename boost::call_traits<T>::value_type> wrap(const T& t)
{
typedef typename boost::call_traits<T>::value_type ct;
return contained<ct>(t);
}
namespace test{
template <class T1, class T2>
std::pair<
typename boost::call_traits<T1>::value_type,
typename boost::call_traits<T2>::value_type>
make_pair(const T1& t1, const T2& t2)
{
return std::pair<
typename boost::call_traits<T1>::value_type,
typename boost::call_traits<T2>::value_type>(t1, t2);
}
} // namespace test
using namespace std;
//
// struct checker:
// verifies behaviour of contained example:
//
template <class T>
struct checker
{
typedef typename boost::call_traits<T>::param_type param_type;
void operator()(param_type);
};
template <class T>
void checker<T>::operator()(param_type p)
{
T t(p);
contained<T> c(t);
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
assert(t == c.value());
assert(t == c.get());
assert(t == c.const_get());
cout << "typeof contained<" << typeid(T).name() << ">::v_ is: " << typeid(&contained<T>::v_).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained<T>::value).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained<T>::get).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained<T>::const_get).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained<T>::call).name() << endl;
cout << endl;
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, std::size_t N>
struct checker<T[N]>
{
typedef typename boost::call_traits<T[N]>::param_type param_type;
void operator()(param_type t)
{
contained<T[N]> c(t);
cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl;
unsigned int i = 0;
for(i = 0; i < N; ++i)
assert(t[i] == c.value()[i]);
for(i = 0; i < N; ++i)
assert(t[i] == c.get()[i]);
for(i = 0; i < N; ++i)
assert(t[i] == c.const_get()[i]);
cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is: " << typeid(&contained<T[N]>::v_).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained<T[N]>::value).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained<T[N]>::get).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained<T[N]>::const_get).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained<T[N]>::call).name() << endl;
cout << endl;
}
};
#endif
//
// check_wrap:
template <class T, class U>
void check_wrap(const contained<T>& w, const U& u)
{
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
assert(w.value() == u);
}
//
// check_make_pair:
// verifies behaviour of "make_pair":
//
template <class T, class U, class V>
void check_make_pair(T c, U u, V v)
{
cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl;
assert(c.first == u);
assert(c.second == v);
cout << endl;
}
struct UDT
{
int i_;
UDT() : i_(2){}
bool operator == (const UDT& v){ return v.i_ == i_; }
};
//
// define tests here
unsigned failures = 0;
unsigned test_count = 0;
#define value_test(v, x) ++test_count;\
if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#define type_test(v, x) ++test_count;\
if(boost::is_same<v, x>::value == false){\
++failures; \
std::cout << "checking type of " << #x << "...failed" << std::endl; \
std::cout << " expected type was " << #v << std::endl; \
std::cout << " " << typeid(boost::is_same<v, x>).name() << "::value is false" << std::endl; }
#else
#define type_test(v, x) ++test_count;\
if(typeid(v) != typeid(x)){\
++failures; \
std::cout << "checking type of " << #x << "...failed" << std::endl; \
std::cout << " expected type was " << #v << std::endl; \
std::cout << " " << "typeid(" #v ") != typeid(" #x ")" << std::endl; }
#endif
int main()
{
checker<UDT> c1;
UDT u;
c1(u);
checker<int> c2;
int i = 2;
c2(i);
int* pi = &i;
checker<int*> c3;
c3(pi);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
checker<int&> c4;
c4(i);
checker<const int&> c5;
c5(i);
int a[2] = {1,2};
checker<int[2]> c6;
c6(a);
#endif
check_wrap(wrap(2), 2);
const char ca[4] = "abc";
// compiler can't deduce this for some reason:
//check_wrap(wrap(ca), ca);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
check_wrap(wrap(a), a);
check_make_pair(test::make_pair(a, a), a, a);
#endif
// cv-qualifiers applied to reference types should have no effect
// declare these here for later use with is_reference and remove_reference:
typedef int& r_type;
typedef const r_type cr_type;
type_test(UDT, boost::call_traits<UDT>::value_type)
type_test(UDT&, boost::call_traits<UDT>::reference)
type_test(const UDT&, boost::call_traits<UDT>::const_reference)
type_test(const UDT&, boost::call_traits<UDT>::param_type)
type_test(int, boost::call_traits<int>::value_type)
type_test(int&, boost::call_traits<int>::reference)
type_test(const int&, boost::call_traits<int>::const_reference)
type_test(const int, boost::call_traits<int>::param_type)
type_test(int*, boost::call_traits<int*>::value_type)
type_test(int*&, boost::call_traits<int*>::reference)
type_test(int*const&, boost::call_traits<int*>::const_reference)
type_test(int*const, boost::call_traits<int*>::param_type)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
type_test(int&, boost::call_traits<int&>::value_type)
type_test(int&, boost::call_traits<int&>::reference)
type_test(const int&, boost::call_traits<int&>::const_reference)
type_test(int&, boost::call_traits<int&>::param_type)
#if !(defined(__GNUC__) && (__GNUC__ < 3))
type_test(int&, boost::call_traits<cr_type>::value_type)
type_test(int&, boost::call_traits<cr_type>::reference)
type_test(const int&, boost::call_traits<cr_type>::const_reference)
type_test(int&, boost::call_traits<cr_type>::param_type)
#else
std::cout << "GNU C++ cannot instantiate call_traits<cr_type>, skipping four tests (4 errors)" << std::endl;
failures += 4;
test_count += 4;
#endif
type_test(const int&, boost::call_traits<const int&>::value_type)
type_test(const int&, boost::call_traits<const int&>::reference)
type_test(const int&, boost::call_traits<const int&>::const_reference)
type_test(const int&, boost::call_traits<const int&>::param_type)
type_test(const int*, boost::call_traits<int[3]>::value_type)
type_test(int(&)[3], boost::call_traits<int[3]>::reference)
type_test(const int(&)[3], boost::call_traits<int[3]>::const_reference)
type_test(const int*const, boost::call_traits<int[3]>::param_type)
type_test(const int*, boost::call_traits<const int[3]>::value_type)
type_test(const int(&)[3], boost::call_traits<const int[3]>::reference)
type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference)
type_test(const int*const, boost::call_traits<const int[3]>::param_type)
#else
std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl;
failures += 20;
test_count += 20;
#endif
std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
std::cin.get();
return failures;
}
//
// define call_traits tests to check that the assertions in the docs do actually work
// this is an instantiate only set of tests:
//
template <typename T, bool isarray = false>
struct call_traits_test
{
static void assert_construct(boost::call_traits<T>::param_type val);
};
template <typename T, bool isarray>
void call_traits_test<T, isarray>::assert_construct(boost::call_traits<T>::param_type val)
{
//
// this is to check that the call_traits assertions are valid:
T t(val);
boost::call_traits<T>::value_type v(t);
boost::call_traits<T>::reference r(t);
boost::call_traits<T>::const_reference cr(t);
boost::call_traits<T>::param_type p(t);
boost::call_traits<T>::value_type v2(v);
boost::call_traits<T>::value_type v3(r);
boost::call_traits<T>::value_type v4(p);
boost::call_traits<T>::reference r2(v);
boost::call_traits<T>::reference r3(r);
boost::call_traits<T>::const_reference cr2(v);
boost::call_traits<T>::const_reference cr3(r);
boost::call_traits<T>::const_reference cr4(cr);
boost::call_traits<T>::const_reference cr5(p);
boost::call_traits<T>::param_type p2(v);
boost::call_traits<T>::param_type p3(r);
boost::call_traits<T>::param_type p4(p);
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T>
struct call_traits_test<T, true>
{
static void assert_construct(boost::call_traits<T>::param_type val);
};
template <typename T>
void call_traits_test<T, true>::assert_construct(boost::call_traits<T>::param_type val)
{
//
// this is to check that the call_traits assertions are valid:
T t;
boost::call_traits<T>::value_type v(t);
boost::call_traits<T>::value_type v5(val);
boost::call_traits<T>::reference r = t;
boost::call_traits<T>::const_reference cr = t;
boost::call_traits<T>::reference r2 = r;
#ifndef __BORLANDC__
// C++ Builder buglet:
boost::call_traits<T>::const_reference cr2 = r;
#endif
boost::call_traits<T>::param_type p(t);
boost::call_traits<T>::value_type v2(v);
boost::call_traits<T>::const_reference cr3 = cr;
boost::call_traits<T>::value_type v3(r);
boost::call_traits<T>::value_type v4(p);
boost::call_traits<T>::param_type p2(v);
boost::call_traits<T>::param_type p3(r);
boost::call_traits<T>::param_type p4(p);
}
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
//
// now check call_traits assertions by instantiating call_traits_test:
template struct call_traits_test<int>;
template struct call_traits_test<const int>;
template struct call_traits_test<int*>;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template struct call_traits_test<int&>;
template struct call_traits_test<const int&>;
template struct call_traits_test<int[2], true>;
#endif

149
cast_test.cpp Normal file
View File

@@ -0,0 +1,149 @@
// boost utility cast test program -----------------------------------------//
// (C) Copyright boost.org 1999. 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.
// Revision History
// 28 Jun 00 implicit_cast removed (Beman Dawes)
// 30 Aug 99 value_cast replaced by numeric_cast
// 3 Aug 99 Initial Version
#include <iostream>
#include <climits>
#include <limits>
#include <boost/cast.hpp>
# if SCHAR_MAX == LONG_MAX
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
# endif
using namespace boost;
using std::cout;
namespace
{
struct Base
{
virtual char kind() { return 'B'; }
};
struct Base2
{
virtual char kind2() { return '2'; }
};
struct Derived : public Base, Base2
{
virtual char kind() { return 'D'; }
};
}
int main( int argc, char * argv[] )
{
cout << "Usage: test_casts [n], where n omitted or is:\n"
" 1 = execute #1 assert failure (#ifndef NDEBUG)\n"
" 2 = execute #2 assert failure (#ifndef NDEBUG)\n"
"Example: test_casts 2\n\n";
# ifdef NDEBUG
cout << "NDEBUG is defined\n";
# else
cout << "NDEBUG is not defined\n";
# endif
cout << "\nBeginning tests...\n";
// test polymorphic_cast ---------------------------------------------------//
// tests which should succeed
Base * base = new Derived;
Base2 * base2 = 0;
Derived * derived = 0;
derived = polymorphic_downcast<Derived*>( base ); // downcast
assert( derived->kind() == 'D' );
derived = 0;
derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
assert( derived->kind() == 'D' );
base2 = polymorphic_cast<Base2*>( base ); // crosscast
assert( base2->kind2() == '2' );
// tests which should result in errors being detected
int err_count = 0;
base = new Base;
if ( argc > 1 && *argv[1] == '1' )
{ derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
bool caught_exception = false;
try { derived = polymorphic_cast<Derived*>( base ); }
catch (std::bad_cast)
{ cout<<"caught bad_cast\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
// the following is just so generated code can be inspected
if ( derived->kind() == 'B' ) ++err_count;
// test implicit_cast and numeric_cast -------------------------------------//
// tests which should succeed
long small_value = 1;
long small_negative_value = -1;
long large_value = std::numeric_limits<long>::max();
long large_negative_value = std::numeric_limits<long>::min();
signed char c = 0;
c = large_value; // see if compiler generates warning
c = numeric_cast<signed char>( small_value );
assert( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_value );
assert( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_negative_value );
assert( c == -1 );
// tests which should result in errors being detected
caught_exception = false;
try { c = numeric_cast<signed char>( large_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { c = numeric_cast<signed char>( large_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
unsigned long ul;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( large_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( small_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { numeric_cast<int>( std::numeric_limits<double>::max() ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
cout << err_count << " errors detected\nTest "
<< (err_count==0 ? "passed\n" : "failed\n");
return err_count;
} // main

140
compressed_pair_test.cpp Normal file
View File

@@ -0,0 +1,140 @@
// boost::compressed_pair test program
// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <iostream>
#include <typeinfo>
#include <cassert>
#include <boost/compressed_pair.hpp>
using namespace boost;
#ifdef __BORLANDC__
#pragma option -w-ccc -w-rch -w-eff -w-aus
#endif
//
// define tests here
unsigned failures = 0;
unsigned test_count = 0;
#define value_test(v, x) ++test_count;\
if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#define type_test(v, x) ++test_count;\
if(boost::is_same<v, x>::value == false){\
++failures; \
std::cout << "checking type of " << #x << "...failed" << std::endl; \
std::cout << " expected type was " << #v << std::endl; \
std::cout << " " << typeid(boost::is_same<v, x>).name() << "::value is false" << std::endl; }
#else
#define type_test(v, x) ++test_count;\
if(typeid(v) != typeid(x)){\
++failures; \
std::cout << "checking type of " << #x << "...failed" << std::endl; \
std::cout << " expected type was " << #v << std::endl; \
std::cout << " " << "typeid(" #v ") != typeid(" #x ")" << std::endl; }
#endif
struct empty_POD_UDT{};
struct empty_UDT
{
~empty_UDT(){};
};
namespace boost {
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template <> struct is_empty<empty_UDT>
{ static const bool value = true; };
template <> struct is_empty<empty_POD_UDT>
{ static const bool value = true; };
template <> struct is_POD<empty_POD_UDT>
{ static const bool value = true; };
#else
template <> struct is_empty<empty_UDT>
{ enum{ value = true }; };
template <> struct is_empty<empty_POD_UDT>
{ enum{ value = true }; };
template <> struct is_POD<empty_POD_UDT>
{ enum{ value = true }; };
#endif
}
int main()
{
compressed_pair<int, double> cp1(1, 1.3);
assert(cp1.first() == 1);
assert(cp1.second() == 1.3);
compressed_pair<int, double> cp1b(2, 2.3);
assert(cp1b.first() == 2);
assert(cp1b.second() == 2.3);
swap(cp1, cp1b);
assert(cp1b.first() == 1);
assert(cp1b.second() == 1.3);
assert(cp1.first() == 2);
assert(cp1.second() == 2.3);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
compressed_pair<empty_UDT, int> cp2(2);
assert(cp2.second() == 2);
#endif
compressed_pair<int, empty_UDT> cp3(1);
assert(cp3.first() ==1);
compressed_pair<empty_UDT, empty_UDT> cp4;
compressed_pair<empty_UDT, empty_POD_UDT> cp5;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
int i = 0;
compressed_pair<int&, int&> cp6(i,i);
assert(cp6.first() == i);
assert(cp6.second() == i);
assert(&cp6.first() == &i);
assert(&cp6.second() == &i);
compressed_pair<int, double[2]> cp7;
cp7.first();
double* pd = cp7.second();
#endif
value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>)))
value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>)))
value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>)))
value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>)))
value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >)))
std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
std::cin.get();
return failures;
}
//
// instanciate some compressed pairs:
template class boost::compressed_pair<int, double>;
template class boost::compressed_pair<int, int>;
template class boost::compressed_pair<empty_UDT, int>;
template class boost::compressed_pair<int, empty_UDT>;
template class boost::compressed_pair<empty_UDT, empty_UDT>;
template class boost::compressed_pair<empty_UDT, empty_POD_UDT>;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
//
// now some for which only a few specific members can be instantiated,
// first references:
template double& compressed_pair<double, int&>::first();
template int& compressed_pair<double, int&>::second();
template compressed_pair<double, int&>::compressed_pair(int&);
template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&);
//
// and then arrays:
#ifndef __BORLANDC__
template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second();
#endif
template call_traits<double>::reference compressed_pair<double, int[2]>::first();
template compressed_pair<double, int[2]>::compressed_pair(const double&);
template compressed_pair<double, int[2]>::compressed_pair();
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@@ -1,38 +0,0 @@
//
// 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

View File

@@ -1,10 +1,9 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// (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/call_traits.hpp and boost/detail/ob_call_traits.hpp
// for full copyright notices.

View File

@@ -1,71 +0,0 @@
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/checked_delete.hpp
//
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
// Copyright (c) 2002, 2003 Peter Dimov
// Copyright (c) 2003 Daniel Frey
// Copyright (c) 2003 Howard Hinnant
//
// 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)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
template<class T> inline void checked_array_delete(T * x)
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete [] x;
}
template<class T> struct checked_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
{
// boost:: disables ADL
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

View File

@@ -1,10 +1,9 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// (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.

View File

@@ -1,64 +0,0 @@
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_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

View File

@@ -1,12 +1,10 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// 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.
// call_traits: defines typedefs for function usage
// (see libs/utility/call_traits.htm)
// See http://www.boost.org for most recent version including documentation.
/* Release notes:
23rd July 2000:
@@ -21,41 +19,29 @@
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#include <cstddef>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_pointer.hpp>
#ifndef BOOST_TYPE_TRAITS_HPP
#include <boost/type_traits.hpp>
#endif
namespace boost{
namespace detail{
template <typename T, bool small_>
struct ct_imp2
{
typedef const T& param_type;
};
template <typename T>
struct ct_imp2<T, true>
{
typedef const T param_type;
};
template <typename T, bool isp, bool b1>
template <typename T, bool isp, bool b1, bool b2>
struct ct_imp
{
typedef const T& param_type;
};
template <typename T, bool isp>
struct ct_imp<T, isp, true>
struct ct_imp<T, isp, true, true>
{
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
typedef T const param_type;
};
template <typename T, bool b1>
struct ct_imp<T, true, b1>
template <typename T, bool b1, bool b2>
struct ct_imp<T, true, b1, b2>
{
typedef T const param_type;
};
@@ -75,11 +61,7 @@ public:
// however compiler bugs prevent this - instead pass three bool's to
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation
// of ct_imp to handle the logic. (JM)
typedef typename detail::ct_imp<
T,
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value
>::param_type param_type;
typedef typename detail::ct_imp<T, ::boost::is_pointer<typename remove_const<T>::type>::value, ::boost::is_arithmetic<typename remove_const<T>::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type;
};
template <typename T>
@@ -91,7 +73,7 @@ struct call_traits<T&>
typedef T& param_type; // hh removed const
};
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x550)
// these are illegal specialisations; cv-qualifies applied to
// references have no effect according to [8.3.2p1],
// C++ Builder requires them though as it treats cv-qualified
@@ -121,7 +103,7 @@ struct call_traits<T&const volatile>
typedef T& param_type; // hh removed const
};
#endif
#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
template <typename T, std::size_t N>
struct call_traits<T [N]>
{
@@ -147,7 +129,6 @@ public:
typedef const array_type& const_reference;
typedef const T* const param_type;
};
#endif
}

View File

@@ -1,16 +1,12 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// 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.
// compressed_pair: pair that "compresses" empty members
// (see libs/utility/compressed_pair.htm)
//
// JM changes 25 Jan 2004:
// For the case where T1 == T2 and both are empty, then first() and second()
// should return different objects.
// JM changes 25 Jan 2000:
// Removed default arguments from compressed_pair_switch to get
// C++ Builder 4 to accept them
@@ -21,19 +17,16 @@
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
#include <algorithm>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_empty.hpp>
#include <boost/type_traits/is_same.hpp>
#ifndef BOOST_TYPE_TRAITS_HPP
#include <boost/type_traits.hpp>
#endif
#ifndef BOOST_CALL_TRAITS_HPP
#include <boost/call_traits.hpp>
#endif
namespace boost
{
template <class T1, class T2>
class compressed_pair;
// compressed_pair
namespace details
@@ -80,9 +73,7 @@ namespace details
template <typename T>
inline void cp_swap(T& t1, T& t2)
{
#ifndef __GNUC__
using std::swap;
#endif
swap(t1, t2);
}
@@ -106,10 +97,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {}
compressed_pair_imp(first_param_type x)
explicit compressed_pair_imp(first_param_type x)
: first_(x) {}
compressed_pair_imp(second_param_type y)
explicit compressed_pair_imp(second_param_type y)
: second_(y) {}
first_reference first() {return first_;}
@@ -118,10 +109,10 @@ namespace details
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(::boost::compressed_pair<T1, T2>& y)
void swap(compressed_pair_imp& y)
{
cp_swap(first_, y.first());
cp_swap(second_, y.second());
cp_swap(first_, y.first_);
cp_swap(second_, y.second_);
}
private:
first_type first_;
@@ -149,10 +140,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_(y) {}
compressed_pair_imp(first_param_type x)
explicit compressed_pair_imp(first_param_type x)
: first_type(x) {}
compressed_pair_imp(second_param_type y)
explicit compressed_pair_imp(second_param_type y)
: second_(y) {}
first_reference first() {return *this;}
@@ -161,10 +152,10 @@ namespace details
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(::boost::compressed_pair<T1,T2>& y)
void swap(compressed_pair_imp& y)
{
// no need to swap empty base class:
cp_swap(second_, y.second());
cp_swap(second_, y.second_);
}
private:
second_type second_;
@@ -191,10 +182,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: second_type(y), first_(x) {}
compressed_pair_imp(first_param_type x)
explicit compressed_pair_imp(first_param_type x)
: first_(x) {}
compressed_pair_imp(second_param_type y)
explicit compressed_pair_imp(second_param_type y)
: second_type(y) {}
first_reference first() {return first_;}
@@ -203,10 +194,10 @@ namespace details
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(::boost::compressed_pair<T1,T2>& y)
void swap(compressed_pair_imp& y)
{
// no need to swap empty base class:
cp_swap(first_, y.first());
cp_swap(first_, y.first_);
}
private:
@@ -235,10 +226,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_type(y) {}
compressed_pair_imp(first_param_type x)
explicit compressed_pair_imp(first_param_type x)
: first_type(x) {}
compressed_pair_imp(second_param_type y)
explicit compressed_pair_imp(second_param_type y)
: second_type(y) {}
first_reference first() {return *this;}
@@ -248,7 +239,7 @@ namespace details
second_const_reference second() const {return *this;}
//
// no need to swap empty bases:
void swap(::boost::compressed_pair<T1,T2>&) {}
void swap(compressed_pair_imp&) {}
};
// JM
@@ -271,21 +262,20 @@ namespace details
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), m_second(y) {}
compressed_pair_imp(first_param_type x, second_param_type)
: first_type(x) {}
compressed_pair_imp(first_param_type x)
: first_type(x), m_second(x) {}
explicit compressed_pair_imp(first_param_type x)
: first_type(x) {}
first_reference first() {return *this;}
first_const_reference first() const {return *this;}
second_reference second() {return m_second;}
second_const_reference second() const {return m_second;}
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(::boost::compressed_pair<T1,T2>&) {}
void swap(compressed_pair_imp&) {}
private:
T2 m_second;
};
// 5 T1 == T2 and are not empty: //JM
@@ -308,7 +298,7 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {}
compressed_pair_imp(first_param_type x)
explicit compressed_pair_imp(first_param_type x)
: first_(x), second_(x) {}
first_reference first() {return first_;}
@@ -317,10 +307,10 @@ namespace details
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(::boost::compressed_pair<T1, T2>& y)
void swap(compressed_pair_imp<T1, T2, 5>& y)
{
cp_swap(first_, y.first());
cp_swap(second_, y.second());
cp_swap(first_, y.first_);
cp_swap(second_, y.second_);
}
private:
first_type first_;
@@ -404,10 +394,7 @@ public:
compressed_pair() : base() {}
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
explicit
#endif
compressed_pair(first_param_type x) : base(x) {}
explicit compressed_pair(first_param_type x) : base(x) {}
first_reference first() {return base::first();}
first_const_reference first() const {return base::first();}
@@ -415,7 +402,7 @@ public:
second_reference second() {return base::second();}
second_const_reference second() const {return base::second();}
void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
void swap(compressed_pair& y) { base::swap(y); }
};
template <class T1, class T2>
@@ -431,4 +418,3 @@ swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP

View File

@@ -1,21 +1,13 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// 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.
//
// Crippled version for crippled compilers:
// see libs/utility/call_traits.htm
//
/* Release notes:
01st October 2000:
Fixed call_traits on VC6, using "poor man's partial specialisation",
using ideas taken from "Generative programming" by Krzysztof Czarnecki
& Ulrich Eisenecker.
*/
#ifndef BOOST_OB_CALL_TRAITS_HPP
#define BOOST_OB_CALL_TRAITS_HPP
@@ -23,135 +15,12 @@
#include <boost/config.hpp>
#endif
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
#include <boost/type_traits/arithmetic_traits.hpp>
#endif
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
#include <boost/type_traits/composite_traits.hpp>
#ifndef BOOST_TYPE_TRAITS_HPP
#include <boost/type_traits.hpp>
#endif
namespace boost{
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
//
// use member templates to emulate
// partial specialisation:
//
namespace detail{
template <class T>
struct standard_call_traits
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef const T& param_type;
};
template <class T>
struct simple_call_traits
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef const T param_type;
};
template <class T>
struct reference_call_traits
{
typedef T value_type;
typedef T reference;
typedef T const_reference;
typedef T param_type;
};
template <bool pointer, bool arithmetic, bool reference>
struct call_traits_chooser
{
template <class T>
struct rebind
{
typedef standard_call_traits<T> type;
};
};
template <>
struct call_traits_chooser<true, false, false>
{
template <class T>
struct rebind
{
typedef simple_call_traits<T> type;
};
};
template <>
struct call_traits_chooser<false, false, true>
{
template <class T>
struct rebind
{
typedef reference_call_traits<T> type;
};
};
template <bool size_is_small>
struct call_traits_sizeof_chooser2
{
template <class T>
struct small_rebind
{
typedef simple_call_traits<T> small_type;
};
};
template<>
struct call_traits_sizeof_chooser2<false>
{
template <class T>
struct small_rebind
{
typedef standard_call_traits<T> small_type;
};
};
template <>
struct call_traits_chooser<false, true, false>
{
template <class T>
struct rebind
{
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
typedef typename chooser::template small_rebind<T> bound_type;
typedef typename bound_type::small_type type;
};
};
} // namespace detail
template <typename T>
struct call_traits
{
private:
typedef detail::call_traits_chooser<
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value,
::boost::is_reference<T>::value
> chooser;
typedef typename chooser::template rebind<T> bound_type;
typedef typename bound_type::type call_traits_type;
public:
typedef typename call_traits_type::value_type value_type;
typedef typename call_traits_type::reference reference;
typedef typename call_traits_type::const_reference const_reference;
typedef typename call_traits_type::param_type param_type;
};
#else
//
// sorry call_traits is completely non-functional
// blame your broken compiler:
//
template <typename T>
struct call_traits
{
@@ -161,8 +30,6 @@ struct call_traits
typedef const T& param_type;
};
#endif // member templates
}
#endif // BOOST_OB_CALL_TRAITS_HPP

View File

@@ -1,18 +1,12 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// see libs/utility/compressed_pair.hpp
// 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.
//
/* Release notes:
20 Jan 2001:
Fixed obvious bugs (David Abrahams)
07 Oct 2000:
Added better single argument constructor support.
03 Oct 2000:
Added VC6 support (JM).
23rd July 2000:
Additional comments added. (JM)
Jan 2000:
@@ -25,11 +19,8 @@
#define BOOST_OB_COMPRESSED_PAIR_HPP
#include <algorithm>
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
#include <boost/type_traits/object_traits.hpp>
#endif
#ifndef BOOST_SAME_TRAITS_HPP
#include <boost/type_traits/same_traits.hpp>
#ifndef BOOST_TYPE_TRAITS_HPP
#include <boost/type_traits.hpp>
#endif
#ifndef BOOST_CALL_TRAITS_HPP
#include <boost/call_traits.hpp>
@@ -37,426 +28,6 @@
namespace boost
{
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
//
// use member templates to emulate
// partial specialisation. Note that due to
// problems with overload resolution with VC6
// each of the compressed_pair versions that follow
// have one template single-argument constructor
// in place of two specific constructors:
//
template <class T1, class T2>
class compressed_pair;
namespace detail{
template <class A, class T1, class T2>
struct best_conversion_traits
{
typedef char one;
typedef char (&two)[2];
static A a;
static one test(T1);
static two test(T2);
enum { value = sizeof(test(a)) };
};
template <int>
struct init_one;
template <>
struct init_one<1>
{
template <class A, class T1, class T2>
static void init(const A& a, T1* p1, T2*)
{
*p1 = a;
}
};
template <>
struct init_one<2>
{
template <class A, class T1, class T2>
static void init(const A& a, T1*, T2* p2)
{
*p2 = a;
}
};
// T1 != T2, both non-empty
template <class T1, class T2>
class compressed_pair_0
{
private:
T1 _first;
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_0() : _first(), _second() {}
compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
template <class A>
explicit compressed_pair_0(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
}
compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
: _first(x.first()), _second(x.second()) {}
#if 0
compressed_pair_0& operator=(const compressed_pair_0& x) {
cout << "assigning compressed pair 0" << endl;
_first = x._first;
_second = x._second;
cout << "finished assigning compressed pair 0" << endl;
return *this;
}
#endif
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair_0& y)
{
using std::swap;
swap(_first, y._first);
swap(_second, y._second);
}
};
// T1 != T2, T2 empty
template <class T1, class T2>
class compressed_pair_1 : T2
{
private:
T1 _first;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_1() : T2(), _first() {}
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
template <class A>
explicit compressed_pair_1(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
}
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
: T2(x.second()), _first(x.first()) {}
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
// Total weirdness. If the assignment to _first is moved after
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
// by way of iterator_adaptor.
compressed_pair_1& operator=(const compressed_pair_1& x) {
_first = x._first;
T2::operator=(x);
return *this;
}
#endif
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return *this; }
second_const_reference second() const { return *this; }
void swap(compressed_pair_1& y)
{
// no need to swap empty base class:
using std::swap;
swap(_first, y._first);
}
};
// T1 != T2, T1 empty
template <class T1, class T2>
class compressed_pair_2 : T1
{
private:
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_2() : T1(), _second() {}
compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
template <class A>
explicit compressed_pair_2(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
}
compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()), _second(x.second()) {}
#if 0
compressed_pair_2& operator=(const compressed_pair_2& x) {
cout << "assigning compressed pair 2" << endl;
T1::operator=(x);
_second = x._second;
cout << "finished assigning compressed pair 2" << endl;
return *this;
}
#endif
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair_2& y)
{
// no need to swap empty base class:
using std::swap;
swap(_second, y._second);
}
};
// T1 != T2, both empty
template <class T1, class T2>
class compressed_pair_3 : T1, T2
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_3() : T1(), T2() {}
compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
template <class A>
explicit compressed_pair_3(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
}
compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()), T2(x.second()) {}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
second_reference second() { return *this; }
second_const_reference second() const { return *this; }
void swap(compressed_pair_3& y)
{
// no need to swap empty base classes:
}
};
// T1 == T2, and empty
template <class T1, class T2>
class compressed_pair_4 : T1
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_4() : T1() {}
compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
// only one single argument constructor since T1 == T2
explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()), m_second(x.second()) {}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
second_reference second() { return m_second; }
second_const_reference second() const { return m_second; }
void swap(compressed_pair_4& y)
{
// no need to swap empty base classes:
}
private:
T2 m_second;
};
// T1 == T2, not empty
template <class T1, class T2>
class compressed_pair_5
{
private:
T1 _first;
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_5() : _first(), _second() {}
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
// only one single argument constructor since T1 == T2
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
: _first(c.first()), _second(c.second()) {}
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair_5& y)
{
using std::swap;
swap(_first, y._first);
swap(_second, y._second);
}
};
template <bool e1, bool e2, bool same>
struct compressed_pair_chooser
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_0<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<false, true, false>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_1<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<true, false, false>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_2<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<true, true, false>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_3<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<true, true, true>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_4<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<false, false, true>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_5<T1, T2> type;
};
};
template <class T1, class T2>
struct compressed_pair_traits
{
private:
typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
typedef typename chooser::template rebind<T1, T2> bound_type;
public:
typedef typename bound_type::type type;
};
} // namespace detail
template <class T1, class T2>
class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
{
private:
typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair() : base_type() {}
compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
template <class A>
explicit compressed_pair(const A& x) : base_type(x){}
first_reference first() { return base_type::first(); }
first_const_reference first() const { return base_type::first(); }
second_reference second() { return base_type::second(); }
second_const_reference second() const { return base_type::second(); }
};
template <class T1, class T2>
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
{
x.swap(y);
}
#else
// no partial specialisation, no member templates:
template <class T1, class T2>
class compressed_pair
@@ -500,11 +71,7 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
x.swap(y);
}
#endif
} // boost
#endif // BOOST_OB_COMPRESSED_PAIR_HPP

View File

@@ -1,81 +0,0 @@
// (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/iterator_facade.hpp>
#include <boost/ref.hpp>
namespace boost {
template<class Generator>
class generator_iterator
: public iterator_facade<
generator_iterator<Generator>
, typename Generator::result_type
, single_pass_traversal_tag
, typename Generator::result_type const&
>
{
typedef iterator_facade<
generator_iterator<Generator>
, typename Generator::result_type
, single_pass_traversal_tag
, typename Generator::result_type const&
> super_t;
public:
generator_iterator() {}
generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {}
void increment()
{
m_value = (*m_g)();
}
const typename Generator::result_type&
dereference() const
{
return m_value;
}
bool equal(generator_iterator const& y) const
{
return this->m_g == y.m_g && this->m_value == y.m_value;
}
private:
Generator* m_g;
typename Generator::result_type m_value;
};
template<class Generator>
struct generator_iterator_generator
{
typedef generator_iterator<Generator> type;
};
template <class Generator>
inline generator_iterator<Generator>
make_generator_iterator(Generator & gen)
{
typedef generator_iterator<Generator> result_t;
return result_t(&gen);
}
} // namespace boost
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP

View File

@@ -1,53 +0,0 @@
// 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.
// Revision History
// 13 Dec 2003 Added next(x, n) and prior(x, n) (Daniel Walker)
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
#include <iterator>
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);
// const std::list<T>::iterator next = boost::next(prev, 2);
// Contributed by Dave Abrahams
template <class T>
inline T next(T x) { return ++x; }
template <class T, class Distance>
inline T next(T x, Distance n)
{
std::advance(x, n);
return x;
}
template <class T>
inline T prior(T x) { return --x; }
template <class T, class Distance>
inline T prior(T x, Distance n)
{
std::advance(x, -n);
return x;
}
} // namespace boost
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED

View File

@@ -1,33 +0,0 @@
// 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

View File

@@ -1,34 +1,20 @@
// 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.
// (C) Copyright David Abrahams 1999. 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.
// (C) Copyright Jeremy Siek 1999. 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.
// Revision History
// 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
@@ -78,27 +64,15 @@
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/detail/workaround.hpp>
#if defined(__sgi) && !defined(__GNUC__)
# pragma set woff 1234
#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
@@ -153,112 +127,106 @@ 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) 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; } \
template <class T, class U, class B = ::boost::detail::empty_base>
struct multipliable2 : B
{
friend T operator*(T x, const U& y) { return x *= y; }
friend T operator*(const U& y, T x) { return x *= y; }
};
#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; } \
template <class T, class B = ::boost::detail::empty_base>
struct multipliable1 : B
{
friend T operator*(T x, const T& y) { return x *= y; }
};
#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; } \
template <class T, class U, class B = ::boost::detail::empty_base>
struct addable2 : B
{
friend T operator+(T x, const U& y) { return x += y; }
friend T operator+(const U& y, T x) { return x += y; }
};
#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; } \
template <class T, class B = ::boost::detail::empty_base>
struct addable1 : B
{
friend T operator+(T x, const T& y) { return x += y; }
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
template <class T, class U, class B = ::boost::detail::empty_base>
struct subtractable2 : B
{
friend T operator-(T x, const U& y) { return x -= y; }
};
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, | )
template <class T, class B = ::boost::detail::empty_base>
struct subtractable1 : B
{
friend T operator-(T x, const T& y) { return x -= y; }
};
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
#undef BOOST_OPERATOR2_LEFT
template <class T, class U, class B = ::boost::detail::empty_base>
struct dividable2 : B
{
friend T operator/(T x, const U& y) { return x /= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct dividable1 : B
{
friend T operator/(T x, const T& y) { return x /= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct modable2 : B
{
friend T operator%(T x, const U& y) { return x %= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct modable1 : B
{
friend T operator%(T x, const T& y) { return x %= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct xorable2 : B
{
friend T operator^(T x, const U& y) { return x ^= y; }
friend T operator^(const U& y, T x) { return x ^= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct xorable1 : B
{
friend T operator^(T x, const T& y) { return x ^= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct andable2 : B
{
friend T operator&(T x, const U& y) { return x &= y; }
friend T operator&(const U& y, T x) { return x &= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct andable1 : B
{
friend T operator&(T x, const T& y) { return x &= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct orable2 : B
{
friend T operator|(T x, const U& y) { return x |= y; }
friend T operator|(const U& y, T x) { return x |= y; }
};
template <class T, class B = ::boost::detail::empty_base>
struct orable1 : B
{
friend T operator|(T x, const T& y) { return x |= y; }
};
// incrementable and decrementable contributed by Jeremy Siek
@@ -267,9 +235,9 @@ struct incrementable : B
{
friend T operator++(T& x, int)
{
incrementable_type nrv(x);
incrementable_type tmp(x);
++x;
return nrv;
return tmp;
}
private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
@@ -280,9 +248,9 @@ struct decrementable : B
{
friend T operator--(T& x, int)
{
decrementable_type nrv(x);
decrementable_type tmp(x);
--x;
return nrv;
return tmp;
}
private: // The use of this typedef works around a Borland bug
typedef T decrementable_type;
@@ -308,319 +276,12 @@ struct indexable : B
}
};
// 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 -
// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 -
//
// 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
@@ -628,37 +289,12 @@ struct random_access_iteratable
// two-argument forms. Note that these macros expect to be invoked from within
// boost.
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
#if defined(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> {};
# if defined(BOOST_NO_USING_TEMPLATE)
// 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_TEMPLATE2(template_name) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, B> {};
@@ -667,8 +303,21 @@ struct random_access_iteratable
template <class T, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, B> {};
# else
// Otherwise, bring the names in with a using-declaration to avoid
// stressing the compiler
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
# endif // BOOST_NO_USING_TEMPLATE
#else // !BOOST_NO_OPERATORS_IN_NAMESPACE
// The template is already in boost so we have nothing to do.
# define BOOST_IMPORT_TEMPLATE2(template_name)
# define BOOST_IMPORT_TEMPLATE1(template_name)
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
//
@@ -677,7 +326,7 @@ struct random_access_iteratable
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
// neccessary.
//
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#if !defined(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
@@ -700,24 +349,6 @@ template<class T> struct is_chained_base {
} // 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) \
@@ -777,10 +408,6 @@ 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) \
@@ -801,65 +428,55 @@ 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_TEMPLATE(left_shiftable)
BOOST_OPERATOR_TEMPLATE(right_shiftable)
BOOST_OPERATOR_TEMPLATE(equivalent)
BOOST_OPERATOR_TEMPLATE(partially_ordered)
// indexable doesn't follow the patterns above (it has 4 template arguments), so
// we just write out the compiler hacks explicitly.
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
# ifdef BOOST_NO_USING_TEMPLATE
template <class T, class I, class R, class B = ::boost::detail::empty_base>
struct indexable : ::indexable<T,I,R,B> {};
# else
using ::indexable;
# endif
#endif
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)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class I, class R, class B>
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
typedef ::boost::detail::true_t operator_template_type;
};
#endif
#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
> > > {};
: less_than_comparable2<T,U
, equality_comparable2<T,U
, addable2<T,U
, subtractable2<T,U
, multipliable2<T,U
, dividable2<T,U
, modable2<T,U
, orable2<T,U
, andable2<T,U
, xorable2<T,U
> > > > > > > > > > {};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class U = T>
@@ -869,44 +486,32 @@ 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
> > > > {};
: less_than_comparable<T
, equality_comparable<T
, addable<T
, subtractable<T
, multipliable<T
, dividable<T
, modable<T
, orable<T
, andable<T
, xorable<T
, incrementable<T
, decrementable<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
> > {};
: equality_comparable<T
, incrementable<T
, dereferenceable<T,P
, boost::iterator<std::forward_iterator_tag, V, D
> > > > {};
template <class T,
class V,
@@ -914,9 +519,12 @@ template <class 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
> > {};
: equality_comparable<T
, incrementable<T
, decrementable<T
, dereferenceable<T,P
, boost::iterator<std::bidirectional_iterator_tag, V, D
> > > > > {};
template <class T,
class V,
@@ -924,13 +532,22 @@ template <class 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
> >
: equality_comparable<T
, less_than_comparable<T
, incrementable<T
, decrementable<T
, dereferenceable<T,P
, addable2<T,D
, subtractable2<T,D
, indexable<T,D,R
, boost::iterator<std::random_access_iterator_tag, V, D
> > > > > > > > >
{
#ifndef __BORLANDC__
friend D requires_difference_operator(const T& x, const T& y) {
return x - y;
}
#endif
}; // random_access_iterator_helper
} // namespace boost

View File

@@ -1,165 +0,0 @@
#ifndef BOOST_REF_HPP_INCLUDED
#define BOOST_REF_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 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_(boost::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

View File

@@ -1,19 +1,69 @@
// Boost utility.hpp header file -------------------------------------------//
// boost utility.hpp header file -------------------------------------------//
// Copyright 1999-2003 Boost.org. Use, modification, and distribution are
// subject to the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
// (C) Copyright boost.org 1999. 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 the library's home page.
// See http://www.boost.org for most recent version including documentation.
// Classes appear in alphabetical order
// Revision History
// 26 Jan 00 protected noncopyable destructor added (Miki Jovanovic)
// 10 Dec 99 next() and prior() templates added (Dave Abrahams)
// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes)
// 3 Aug 99 cast templates added
// 20 Jul 99 name changed to utility.hpp
// 9 Jun 99 protected noncopyable default ctor
// 2 Jun 99 Initial Version. Class noncopyable only contents (Dave Abrahams)
#ifndef BOOST_UTILITY_HPP
#define BOOST_UTILITY_HPP
#include <boost/utility/addressof.hpp>
#include <boost/utility/base_from_member.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/checked_delete.hpp>
#include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>
#include <boost/config.hpp>
#include <cstddef> // for size_t
namespace boost
{
// next() and prior() template functions -----------------------------------//
// 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>
T next(T x) { return ++x; }
template <class T>
T prior(T x) { return --x; }
// class noncopyable -------------------------------------------------------//
// 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& );
}; // noncopyable
} // namespace boost
#endif // BOOST_UTILITY_HPP

View File

@@ -1,43 +0,0 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Doug Gregor (gregod@cs.rpi.edu)
// Peter Dimov
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
# define BOOST_UTILITY_ADDRESSOF_HPP
# include <boost/config.hpp>
# include <boost/detail/workaround.hpp>
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
# include <boost/type_traits/add_pointer.hpp>
# endif
namespace boost {
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
// VC7 strips const from nested classes unless we add indirection here
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
template <typename T> typename add_pointer<T>::type
# else
template <typename T> T*
# endif
addressof(T& v)
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
}
#endif // BOOST_UTILITY_ADDRESSOF_HPP

View File

@@ -1,99 +0,0 @@
// boost utility/base_from_member.hpp header file --------------------------//
// Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution are
// subject to the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
// See <http://www.boost.org/libs/utility/> for the library's home page.
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#include <boost/utility_fwd.hpp> // required for parameter defaults
namespace boost
{
// Base-from-member class template -----------------------------------------//
// Helper to initialize a base object so a derived class can use this
// object in the initialization of another base class. Used by
// Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a
// base class needing to be initialized by a member.
// Contributed by Daryle Walker
template < typename MemberType, int UniqueID >
class base_from_member
{
protected:
MemberType member;
base_from_member()
: member()
{}
template< typename T1 >
explicit base_from_member( T1 x1 )
: member( x1 )
{}
template< typename T1, typename T2 >
base_from_member( T1 x1, T2 x2 )
: member( x1, x2 )
{}
template< typename T1, typename T2, typename T3 >
base_from_member( T1 x1, T2 x2, T3 x3 )
: member( x1, x2, x3 )
{}
template< typename T1, typename T2, typename T3, typename T4 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4 )
: member( x1, x2, x3, x4 )
{}
template< typename T1, typename T2, typename T3, typename T4, typename T5 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5 )
: member( x1, x2, x3, x4, x5 )
{}
template< typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6 )
: member( x1, x2, x3, x4, x5, x6 )
{}
template< typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7 )
: member( x1, x2, x3, x4, x5, x6, x7 )
{}
template< typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8 )
: member( x1, x2, x3, x4, x5, x6, x7, x8 )
{}
template< typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8,
T9 x9 )
: member( x1, x2, x3, x4, x5, x6, x7, x8, x9 )
{}
template< typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10 >
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8,
T9 x9, T10 x10 )
: member( x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 )
{}
}; // boost::base_from_member
} // namespace boost
#endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP

View File

@@ -1,68 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
#define BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
#include<functional>
namespace boost {
// template<class OP> bool equal_pointees(OP const& x, OP const& y);
// template<class OP> struct equal_pointees_t;
//
// Being OP a model of OptionalPointee (either a pointer or an optional):
//
// If both x and y have valid pointees, returns the result of (*x == *y)
// If only one has a valid pointee, returns false.
// If none have valid pointees, returns true.
// No-throw
template<class OptionalPointee>
inline
bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
{
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
}
template<class OptionalPointee>
struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
{
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return equal_pointees(x,y) ; }
} ;
// template<class OP> bool less_pointees(OP const& x, OP const& y);
// template<class OP> struct less_pointees_t;
//
// Being OP a model of OptionalPointee (either a pointer or an optional):
//
// If y has not a valid pointee, returns false.
// ElseIf x has not a valid pointee, returns true.
// ElseIf both x and y have valid pointees, returns the result of (*x < *y)
// No-throw
template<class OptionalPointee>
inline
bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
{
return !y ? false : ( !x ? true : (*x) < (*y) ) ;
}
template<class OptionalPointee>
struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
{
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return less_pointees(x,y) ; }
} ;
} // namespace boost
#endif

View File

@@ -1,78 +0,0 @@
#if !defined(BOOST_PP_IS_ITERATING)
# error Boost result_of - do not include this file!
#endif
// CWPro8 requires an argument in a function type specialization
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0
# define BOOST_RESULT_OF_ARGS void
#else
# define BOOST_RESULT_OF_ARGS BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: detail::result_of<F, F(BOOST_RESULT_OF_ARGS)> {};
#endif
namespace detail {
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<R (*)(BOOST_RESULT_OF_ARGS), FArgs>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<R (&)(BOOST_RESULT_OF_ARGS), FArgs>
{
typedef R type;
};
#undef BOOST_RESULT_OF_ARGS
#if BOOST_PP_ITERATION() > 1 && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
FArgs>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const,
FArgs>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
volatile,
FArgs>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const volatile,
FArgs>
{
typedef R type;
};
#endif
}

View File

@@ -1,119 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef BOOST_UTILITY_ENABLE_IF_HPP
#define BOOST_UTILITY_ENABLE_IF_HPP
#include "boost/config.hpp"
// Even the definition of enable_if causes problems on some compilers,
// so it's macroed out for all compilers that do not support SFINAE
#ifndef BOOST_NO_SFINAE
namespace boost
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace boost
#else
namespace boost {
namespace detail { typedef void enable_if_default_T; }
template <typename T>
struct enable_if_does_not_work_on_this_compiler;
template <bool B, class T = detail::enable_if_default_T>
struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct enable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct disable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
} // namespace boost
#endif // BOOST_NO_SFINAE
#endif

View File

@@ -1,65 +0,0 @@
// Boost result_of library
// Copyright Doug Gregor 2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org/libs/utility
#ifndef BOOST_RESULT_OF_HPP
#define BOOST_RESULT_OF_HPP
#include <boost/config.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/type.hpp>
#include <boost/preprocessor.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/aux_/has_xxx.hpp>
#ifndef BOOST_RESULT_OF_NUM_ARGS
# define BOOST_RESULT_OF_NUM_ARGS 10
#endif
namespace boost {
template<typename F> struct result_of;
#if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
template<typename F, typename FArgs, bool HasResultType> struct get_result_of;
template<typename F, typename FArgs>
struct get_result_of<F, FArgs, true>
{
typedef typename F::result_type type;
};
template<typename F, typename FArgs>
struct get_result_of<F, FArgs, false>
{
typedef typename F::template result<FArgs>::type type;
};
template<typename F>
struct get_result_of<F, F(void), false>
{
typedef void type;
};
template<typename F, typename FArgs>
struct result_of : get_result_of<F, FArgs, (has_result_type<F>::value)> {};
} // end namespace detail
#define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
#include BOOST_PP_ITERATE()
}
#else
# error Your compiler cannot support class template result_of
#endif
#endif // BOOST_RESULT_OF_HPP

View File

@@ -1,82 +0,0 @@
// (C) 2002, Fernando Luis Cacciola Carballal.
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this software for any purpose is hereby granted
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
//
// 21 Ago 2002 (Created) Fernando Cacciola
//
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#include "boost/detail/select_type.hpp"
#include "boost/type_traits/cv_traits.hpp"
namespace boost {
namespace vinit_detail {
template<class T>
class const_T_base
{
protected :
const_T_base() : x() {}
T x ;
} ;
template<class T>
struct non_const_T_base
{
protected :
non_const_T_base() : x() {}
mutable T x ;
} ;
template<class T>
struct select_base
{
typedef typename
detail::if_true< ::boost::is_const<T>::value >
::template then< const_T_base<T>, non_const_T_base<T> >::type type ;
} ;
} // namespace vinit_detail
template<class T>
class value_initialized : private vinit_detail::select_base<T>::type
{
public :
value_initialized() {}
operator T&() const { return this->x ; }
T& data() const { return this->x ; }
} ;
template<class T>
T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}
template<class T>
T& get ( value_initialized<T>& x )
{
return x.data() ;
}
} // namespace boost
#endif

View File

@@ -1,33 +0,0 @@
// Boost utility_fwd.hpp header file ---------------------------------------//
// Copyright 2001, 2003 Boost.org. Use, modification, and distribution are
// subject to the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
// See <http://www.boost.org/libs/utility/> for the library's home page.
#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/noncopyable.hpp> --------------------------------------------//
class noncopyable;
// Also has a few function templates
} // namespace boost
#endif // BOOST_UTILITY_FWD_HPP

View File

@@ -0,0 +1,45 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <functional>
#include <algorithm>
#include <iostream>
#include <boost/iterator_adaptors.hpp>
int
main(int, char*[])
{
// This is a simple example of using the transform_iterators class to
// generate iterators that multiply the value returned by dereferencing
// the iterator. In this case we are multiplying by 2.
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
typedef std::binder1st< std::multiplies<int> > Function;
typedef boost::transform_iterator<Function, int*,
boost::iterator<std::random_access_iterator_tag, int>
>::type doubling_iterator;
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
std::cout << "multiplying the array by 2:" << std::endl;
while (i != i_end)
std::cout << *i++ << " ";
std::cout << std::endl;
// Here is an example of counting from 0 to 5 using the integer_range class.
boost::integer_range<int> r(0,5);
std::cout << "counting to from 0 to 4:" << std::endl;
std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}

143
iterator_adaptor_test.cpp Normal file
View File

@@ -0,0 +1,143 @@
// Demonstrate and test boost/operators.hpp on std::iterators -------------//
// (C) Copyright Jeremy Siek 1999. 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.
// Revision History
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#include <iostream>
#include <algorithm>
#include <functional>
#include <boost/iterator_adaptors.hpp>
#include <boost/iterator_tests.hpp>
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
struct my_iter_traits {
typedef dummyT value_type;
typedef dummyT* pointer;
typedef dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
struct my_const_iter_traits {
typedef dummyT value_type;
typedef const dummyT* pointer;
typedef const dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
typedef boost::iterator_adaptors
<dummyT*, const dummyT*,
my_iter_traits, my_const_iter_traits> My;
struct mult_functor {
typedef int result_type;
typedef int argument_type;
// Functors used with transform_iterator must be
// DefaultConstructible, as the transform_iterator must be
// DefaultConstructible to satisfy the requirements for
// TrivialIterator.
mult_functor() { }
mult_functor(int aa) : a(aa) { }
int operator()(int b) const { return a * b; }
int a;
};
int
main()
{
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
// sanity check, if this doesn't pass the test is buggy
boost::random_access_iterator_test(array,N,array);
// Test the iterator_adaptors
{
My::iterator i = array;
boost::random_access_iterator_test(i, N, array);
My::const_iterator j = array;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test transform_iterator
{
int x[N], y[N];
for (int k = 0; k < N; ++k)
x[k] = k;
std::copy(x, x + N, y);
for (int k2 = 0; k2 < N; ++k2)
x[k2] = x[k2] * 2;
boost::transform_iterator<mult_functor, int*,
boost::iterator<std::random_access_iterator_tag,int> >::type
i(y, mult_functor(2));
boost::random_access_iterator_test(i, N, x);
}
// Test indirect_iterator
{
dummyT* ptr[N];
for (int k = 0; k < N; ++k)
ptr[k] = array + k;
typedef dummyT* DummyPtr;
typedef boost::indirect_iterators<DummyPtr*, const DummyPtr*,
boost::iterator<std::random_access_iterator_tag, DummyPtr>,
boost::iterator<std::random_access_iterator_tag, const DummyPtr>,
boost::iterator<std::random_access_iterator_tag, dummyT>
> Indirect;
Indirect::iterator i = ptr;
boost::random_access_iterator_test(i, N, array);
Indirect::const_iterator j = ptr;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterators
{
dummyT reversed[N];
std::copy(array, array + N, reversed);
std::reverse(reversed, reversed + N);
typedef boost::reverse_iterators<dummyT*, const dummyT*,
boost::iterator<std::random_access_iterator_tag,dummyT>,
boost::iterator<std::random_access_iterator_tag,const dummyT>
> Reverse;
Reverse::iterator i = reversed + N;
boost::random_access_iterator_test(i, N, array);
Reverse::const_iterator j = reversed + N;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test integer_range's iterators
{
int int_array[] = { 0, 1, 2, 3, 4, 5 };
boost::integer_range<int> r(0, 5);
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
}
std::cout << "test successful " << std::endl;
return 0;
}

631
iterator_adaptors.htm Normal file
View File

@@ -0,0 +1,631 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Header boost/iterator_adaptors.hpp Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></h1>
<p>Header <a
href="http://www.boost.org/boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
</p>
<p>The file <a
href="http://www.boost.org/boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
includes the main <tt>iterator_adaptors</tt> class and several other classes
for constructing commonly used iterator adaptors.</p>
<ul>
<li><a href="#iterator_adaptors"><tt>iterator_adaptors</tt></a>.
<li><a href="#iterator_adaptor"><tt>iterator_adaptor</tt></a>.
<li><a href="#transform_iterator"><tt>transform_iterator</tt></a>
<li><a href="#indirect_iterators"><tt>indirect_iterators</tt></a>
<li><a href="#reverse_iterators"><tt>reverse_iterators</tt></a>
<li><a href="#integer_range"><tt>integer_range</tt></a>
</ul>
<!-- put in something about Andrei Alexandrescu's contribution? -->
<p><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> started the library, coming up with the idea to use
policy classes and how to handle the const/non-const iterator
interactions. He also contributed the <tt>indirect_iterators</tt> and
<tt>reverse_iterators</tt> classes.<br>
<a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
contributed <tt>transform_iterator</tt>, <tt>integer_range</tt>,
and this documentation.
<h3><a name="iterator_adaptors">The Iterator Adaptors Class</a></h3>
Implementing standard conforming iterators is a non-trivial task.
There are some fine-points such as iterator/const_iterator
interactions and there are the myriad of operators that should be
implemented but are easily forgotten such as
<tt>operator-&gt;()</tt>. The purpose of the
<tt>iterator_adaptors</tt> class is to make it easier to implement an
iterator class, and even easier to extend and adapt existing iterator
types. The <tt>iterator_adaptors</tt> class itself is not an adaptor
class but a <i>type generator</i>. It generates a pair of adaptor classes,
one class for the mutable iterator and one class for the const
iterator. The definition of the <tt>iterator_adaptors</tt> class is as
follows:
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator,
class ConstIterator,
class Traits = std::iterator_traits&lt;Iterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;,
class Policies = default_iterator_policies&gt;
struct iterator_adaptors
{
typedef ... iterator;
typedef ... const_iterator;
};
</PRE></TD></TABLE>
<p>The <tt>Iterator</tt> and <tt>ConstIterator</tt> template parameters
are the iterator types that you want to adapt. The <tt>Traits</tt> and
<tt>ConstTraits</tt> must be iterator traits classes. The traits
parameters default to the specialization of the
<tt>std::iterator_traits</tt> class for the adapted iterators. If you
want the traits for your new iterator adaptor (<tt>value_type</tt>,
<tt>iterator_category</tt>, etc.) to be the same as the adapted
iterator then use the default, otherwise create your own traits
classes and pass them in <a href="#1">[1]</a>.
<p>The <tt>Policies</tt> class that you pass in will become the heart of
the iterator adaptor. The policy class determines how your new adaptor
class will behave. The <tt>Policies</tt> class must implement 3, 4, or
7 of the core iterator operations depending on whether you wish the
new iterator adaptor class to be a
<a href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
ForwardIterator</a>,
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
BidirectionalIterator</a>, or <a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>. Make sure that the
<tt>iterator_category</tt> type of the traits class you pass in
matches the category of iterator that you want to create. The default
policy class, <tt>default_iterator_policies</tt>, implements all 7 of
the core operations in the usual way. If you wish to create an
iterator adaptor that only changes a few of the iterator's behaviors,
then you can have your new policy class inherit from
<tt>default_iterator_policies</tt> to avoid retyping the usual
behaviours. You should also look at <tt>default_iterator_policies</tt>
as the &quot;boiler-plate&quot; for your own policy classes. The
following is definition of the <tt>default_iterator_policies</tt>
class:
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
struct default_iterator_policies
{
// required for a ForwardIterator
template &lt;class Reference, class Iterator&gt;
Reference dereference(type&lt;Reference&gt;, const Iterator& x) const
{ return *x; }
template &lt;class Iterator&gt;
void increment(Iterator& x) const
{ ++x; }
template &lt;class Iterator1, class Iterator2&gt;
bool equal(Iterator1& x, Iterator2& y) const
{ return x == y; }
// required for a BidirectionalIterator
template &lt;class Iterator&gt;
void decrement(Iterator& x) const
{ --x; }
// required for a RandomAccessIterator
template &lt;class Iterator, class DifferenceType&gt;
void advance(Iterator& x, DifferenceType n) const
{ x += n; }
template &lt;class Difference, class Iterator1, class Iterator2&gt;
Difference distance(type&lt;Difference&gt;, Iterator1& x, Iterator2& y) const
{ return y - x; }
template &lt;class Iterator1, class Iterator2&gt;
bool less(Iterator1& x, Iterator2& y) const
{ return x &lt; y; }
};
</PRE></TD></TABLE>
<p>
The generated iterator adaptor types will have the following
constructors.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
<i>iterator</i>(const Iterator& i, const Policies& p = Policies())
<i>const_iterator</i>(const ConstIterator& i, const Policies& p = Policies())
</PRE></TD></TABLE>
<h3><a name="iterator_adaptor">The Iterator Adaptor Class</a></h3>
This is the class used inside of the <tt>iterator_adaptors</tt> type
generator. Use this class directly (instead of using
<tt>iterator_adaptors</tt>) when there is no difference between the
const and non-const versions of the iterator type. Often this is
because there is only a const (read-only) version of the iterator, as
is the case for <tt>std::set</tt>'s iterators. Use the same type for
the <tt>Iterator</tt> and <tt>NonconstIterator</tt> template
arguments.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator,
class Policies = default_iterator_policies,
class NonconstIterator = Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt; &gt;
struct iterator_adaptor;
</PRE></TD></TABLE>
<p>
Next we will look at some iterator adaptors that are examples of how
to use the iterator adaptors class, and that are useful iterator
adaptors in their own right.
<h3><a name="transform_iterator">The Transform Iterator Class</a></h3>
It is often useful to automatically apply some function to the value
returned by dereferencing (<tt>operator*()</tt>) an iterator. The
<tt>transform_iterators</tt> class makes it easy to create an iterator
adaptor that does just that.
First let us consider what the <tt>Policies</tt> class for the transform
iterator should look like. We are only changing one of the iterator
behaviours, so we will inherit from
<tt>default_iterator_policies</tt>. In addition, we will need a
function object to apply, so we will have a template parameter and a
data member for the function object. The function will take one
argument (the dereferenced value) and we will need to know the
<tt>result_type</tt> of the function, so <a
href="http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">
AdaptableUnaryFunction</a> is the corrent concept to choose for the
function object type. Now for the heart of our iterator adaptor, we
implement the <tt>dereference</tt> method, applying the function
object to <tt>*i</tt>. The <tt>type&lt;Reference&gt;</tt> class is
there to tell you what the reference type of the iterator is, which is
handy when writing generic iterator adaptors such as this one <a
href="#2">[2]</a>.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction&gt;
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template &lt;class Reference, class Iterator&gt;
Reference dereference(type&lt;Reference&gt;, const Iterator& i) const
{ return m_f(*i); }
AdaptableUnaryFunction m_f;
};
</PRE></TD></TABLE>
Next we need to create the traits class for our new iterator. In some
situations you may need to create a separate traits class for the
const and non-const iterator types, but here a single traits class
will do. The <tt>value_type</tt> and <tt>reference</tt> type of our
transform iterator will be the <tt>result_type</tt> of the function
object. The <tt>difference_type</tt> and <tt>iterator_category</tt>
will be the same as the adapted iterator.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction, class IteratorTraits&gt;
struct transform_iterator_traits {
typedef typename AdaptableUnaryFunction::result_type value_type;
typedef value_type reference;
typedef value_type* pointer;
typedef typename IteratorTraits::difference_type difference_type;
typedef typename IteratorTraits::iterator_category iterator_category;
};
</PRE></TD></TABLE>
The final step is to use the <tt>iterator_adaptor</tt> class to
construct our transform iterator. We will use the single iterator
adaptor version because we will not need to create both a mutable and
const version of the transform iterator. The transform iterator is
inherently a read-only iterator. The nicest way to package up our new
transform iterator is to create a type generator similar to
<tt>iterator_adaptor</tt>. The first template parameter will be the
type of the function object. The second parameter will be the adapted
iterator type. The third parameter is the trait class for
the adapted iterator. Inside the <tt>transform_iterators</tt> class
we use the <tt>transform_iterator_traits</tt> class defined above to
create the traits class for the new transform iterator. We then use
the <tt>iterator_adaptor</tt> class to extract the generated
iterator adaptor type.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction,
class Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt;
&gt;
struct transform_iterator
{
typedef transform_iterator_traits&lt;AdaptableUnaryFunction,Traits&gt;
TransTraits;
typedef iterator_adaptor&lt;Iterator, TransTraits,
transform_iterator_policies&lt;AdaptableUnaryFunction&gt; &gt;::type type;
};
</PRE></TD></TABLE>
<p>
The following is a simple example of how to use the
<tt>transform_iterators</tt> class to iterate through a range of
numbers, multiplying each of them by 2 when they are dereferenced.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
#include &lt;functional&gt;
#include &lt;iostream&gt;
#include &lt;boost/iterator_adaptors.hpp&gt;
int
main(int, char*[])
{
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
typedef std::binder1st&lt; std::multiplies&lt;int&gt; &gt; Function;
typedef boost::transform_iterator&lt;Function, int*,
boost::iterator&lt;std::random_access_iterator_tag, int&gt;
&gt;::type doubling_iterator;
doubling_iterator i(x, std::bind1st(std::multiplies&lt;int&gt;(), 2)),
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies&lt;int&gt;(), 2));
std::cout &lt;&lt; "multiplying the array by 2:" &lt;&lt; std::endl;
while (i != i_end)
std::cout &lt;&lt; *i++ &lt;&lt; " ";
std::cout &lt;&lt; std::endl;
return 0;
}
</PRE></TD></TABLE>
<h3><a name="indirect_iterators">The Indirect Iterators Class</a></h3>
It is not all that uncommon to create data structures that consist of
pointers to pointers. For such a structure it might be nice to have an
iterator that applies a double-dereference inside the
<tt>operator*()</tt>. The implementation of this is similar to the
<tt>transform_iterators</tt><a href="#3">[3]</a>. We first create a
policies class which does a double-dereference in the
<tt>dereference()</tt> method. We then create a traits class, this
time also including a template parameter for the traits of the second
level iterators as well as the first. Lastly we wrap this up in the
type generator <tt>indirect_iterators</tt>, using
<tt>iterator_adaptors</tt> to do most of the work.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
struct indirect_iterator_policies : public default_iterator_policies
{
template &lt;class Reference, class Iterator&gt;
Reference dereference(type&lt;Reference&gt;, const Iterator& x) const
{ return **x; }
};
template &lt;class IndirectIterator,
class IndirectTraits = std::iterator_traits&lt;IndirectIterator&gt;,
class Traits =
std::iterator_traits&lt;typename IndirectTraits::value_type&gt;
&gt;
struct indirect_traits
{
typedef typename IndirectTraits::difference_type difference_type;
typedef typename Traits::value_type value_type;
typedef typename Traits::pointer pointer;
typedef typename Traits::reference reference;
typedef typename IndirectTraits::iterator_category iterator_category;
};
template &lt;class IndirectIterator, class ConstIndirectIterator,
class IndirectTraits =
std::iterator_traits&lt;IndirectIterator&gt;,
class ConstIndirectTraits =
std::iterator_traits&lt;ConstIndirectIterator&gt;,
class Traits =
std::iterator_traits&lt;typename IndirectTraits::value_type&gt;
&gt;
struct indirect_iterators
{
typedef typename IndirectTraits::value_type Iterator;
typedef typename Traits::value_type ValueType;
typedef iterator_adaptors&lt;IndirectIterator, ConstIndirectIterator,
indirect_traits&lt;IndirectIterator, IndirectTraits, Traits&gt;,
indirect_traits&lt;ConstIndirectIterator, ConstIndirectTraits, Traits&gt;,
indirect_iterator_policies
&gt; Adaptors;
typedef typename Adaptors::iterator iterator;
typedef typename Adaptors::const_iterator const_iterator;
};
</PRE></TD></TABLE>
<h3><a name="reverse_iterators">The Reverse Iterators Class</a></h3>
<p>
Yes, there is already a <tt>reverse_iterator</tt> adaptor class
defined in the C++ Standard, but using the <tt>iterator_adaptors</tt>
class we can re-implement this classic adaptor in a more succinct and
elegant fashion. Also, this makes for a good example of using
<tt>iterator_adaptors</tt> that is in familiar territory.
<p>
The first step is to create the <tt>Policies</tt> class. As in the
<tt>std::reverse_iterator</tt> class, we need to flip all the
operations of the iterator. Increment will become decrement, advancing
by <tt>n</tt> will become retreating by <tt>n</tt>, etc.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
struct reverse_iterator_policies
{
template &lt;class Reference, class Iterator&gt;
Reference dereference(type&lt;Reference&gt;, const Iterator& x) const
{ return *boost::prior(x); }
// this is equivalent to { Iterator tmp = x; return *--tmp; }
template &lt;class Iterator&gt;
void increment(Iterator& x) const
{ --x; }
template &lt;class Iterator&gt;
void decrement(Iterator& x) const
{ ++x; }
template &lt;class Iterator, class DifferenceType&gt;
void advance(Iterator& x, DifferenceType n) const
{ x -= n; }
template &lt;class Difference, class Iterator1, class Iterator2&gt;
Difference distance(type&lt;Difference&gt;, Iterator1& x, Iterator2& y) const
{ return x - y; }
template &lt;class Iterator1, class Iterator2&gt;
bool equal(Iterator1& x, Iterator2& y) const
{ return x == y; }
template &lt;class Iterator1, class Iterator2&gt;
bool less(Iterator1& x, Iterator2& y) const
{ return y &lt; x; }
};
</PRE></TD></TABLE>
Since the traits of the reverse iterator adaptor will be the same as
the adapted iterator's traits, we do not need to create new traits
classes as was the case for <tt>transform_iterator</tt>. We can skip to
the final stage of creating a type generator class for our reverse
iterators using the <tt>iterator_adaptor</tt> class.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator, class ConstIterator,
class Traits = std::iterator_traits&lt;Iterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;
&gt;
struct reverse_iterators
{
typedef iterator_adaptors&lt;Iterator,ConstIterator,Traits,ConstTraits,
reverse_iterator_policies&gt; Adaptor;
typedef typename Adaptor::iterator iterator;
typedef typename Adaptor::const_iterator const_iterator;
};
</PRE></TD></TABLE>
A typical use of the <tt>reverse_iterators</tt> class is in
user-defined container types. You can use the
<tt>reverse_iterators</tt> class to generate the reverse iterators for
your container.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
class my_container {
...
typedef ... iterator;
typedef ... const_iterator;
typedef reverse_iterators&lt;iterator, const_iterator&gt; RevIters;
typedef typename RevIters::iterator reverse_iterator;
typedef typename RevIters::const_iterator const_reverse_iterator;
...
};
</PRE></TD></TABLE>
<h3><a name="integer_range">The Integer Range Class</a></h3>
The <tt>iterator_adaptors</tt> class can not only be used for adapting
iterators, but it can also be used to take a non-iterator type and use
it to build an iterator. An especially simple example of this is
turning an integer type into an iterator, a counting iterator. The
builtin integer types of C++ are almost iterators. They have
<tt>operator++()</tt>, <tt>operator--()</tt>, etc. The one operator
they are lacking is the <tt>operator*()</tt>, which we will want to
simply return the current value of the integer. The following few
lines of code implement the policy and traits class for the counting
iterator.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
struct counting_iterator_policies : public default_iterator_policies
{
template &lt;class IntegerType&gt;
IntegerType dereference(type&lt;IntegerType&gt;, const IntegerType& i) const
{ return i; }
};
template &lt;class IntegerType&gt;
struct counting_iterator_traits {
typedef IntegerType value_type;
typedef IntegerType reference;
typedef value_type* pointer;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
};
</PRE></TD></TABLE>
Typically we will want to count the integers in some range, so a nice
interface would be to have a fake container that represents the range
of integers. The following is the definition of such a class called
<tt>integer_range</tt>.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class IntegerType&gt;
struct integer_range {
typedef typename iterator_adaptor&lt;IntegerType,
counting_iterator_traits&lt;IntegerType&gt;,
counting_iterator_policies &gt;::type iterator;
typedef iterator const_iterator;
typedef IntegerType value_type;
typedef std::ptrdiff_t difference_type;
typedef IntegerType reference;
typedef IntegerType* pointer;
typedef IntegerType size_type;
integer_range(IntegerType start, IntegerType finish)
: m_start(start), m_finish(finish) { }
iterator begin() const { return iterator(m_start); }
iterator end() const { return iterator(m_finish); }
size_type size() const { return m_finish - m_start; }
bool empty() const { return m_finish == m_start; }
void swap(integer_range& x) {
std::swap(m_start, x.m_start);
std::swap(m_finish, x.m_finish);
}
protected:
IntegerType m_start, m_finish;
};
</PRE></TD></TABLE>
<p>
The following is an example of how to use the
<tt>integer_range</tt> class to count from 0 to 4.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
boost::integer_range&lt;int&gt; r(0,5);
cout &lt;&lt; "counting to from 0 to 4:" &lt;&lt; endl;
std::copy(r.begin(), r.end(), ostream_iterator&lt;int&gt;(cout, " "));
cout &lt;&lt; endl;
</PRE></TD></TABLE>
<h3>Challenge</h3>
<p>
There is an unlimited number of ways the the
<tt>iterator_adaptors</tt> class can be used to create iterators. One
interesting exercise would be to re-implement the iterators of
<tt>std::list</tt> and <tt>std::slist</tt> using
<tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
would be node pointers.
<h3>Notes</h3>
<p>
<a name="1">[1]</a>
If your compiler does not support partial specialization and hence
does not have a working <tt>std::iterator_traits</tt> class, you will
not be able to use the defaults and will need to supply your own
<tt>Traits</tt> and <tt>ConstTraits</tt> classes.
<p>
<a name="2">[2]</a>
The reference type could also be obtained from
<tt>std::iterator_traits</tt>, but that is not portable on compilers
that do not support partial specialization.
<p>
<a name="3">[3]</a>
It would have been more elegant to implement <tt>indirect_iterators</tt>
using <tt>transform_iterators</tt>, but for subtle reasons that would require
the use of <tt>boost::remove_cv</tt> which is not portable.
<h3>Implementation Notes</h3>
The code is somewhat complicated because there are three iterator
adaptor class: <tt>forward_iterator_adaptor</tt>,
<tt>bidirectional_iterator_adaptor</tt>, and
<tt>random_access_iterator_adaptor</tt>. The alternative would be to
just have one iterator adaptor equivalent to the
<tt>random_access_iterator_adaptor</tt>. The reason for going with
the three adaptors is that according to 14.5.3p5 in the C++ Standard,
friend functions defined inside a template class body are instantiated
when the template class is instantiated. This means that if we only
used the one iterator adaptor, then if the adapted iterator did not
meet all of the requirements for a
<a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a> then a compiler error should occur. Many
current compilers in fact do not instantiate the friend functions
unless used, so we could get away with the one iterator adaptor in
most cases. However, out of respect for the standard this implementation
uses the three adaptors.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Jun 2000<!--webbot bot="Timestamp" endspan i-checksum="15055" --></p>
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot;
without express or implied warranty, and with no claim as to its suitability for
any purpose.</p>
</body>
</html>

169
iterators_test.cpp Normal file
View File

@@ -0,0 +1,169 @@
// Demonstrate and test boost/operators.hpp on std::iterators --------------//
// (C) Copyright Jeremy Siek 1999. 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.
// Revision History
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#include <string>
#include <iostream>
using namespace std;
#include <boost/operators.hpp>
using namespace boost;
template <class T, class R, class P>
struct test_iter
: public boost::random_access_iterator_helper<
test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
{
typedef test_iter self;
typedef R Reference;
typedef std::ptrdiff_t Distance;
public:
test_iter(T* i) : _i(i) { }
test_iter(const self& x) : _i(x._i) { }
self& operator=(const self& x) { _i = x._i; return *this; }
Reference operator*() const { return *_i; }
self& operator++() { ++_i; return *this; }
self& operator--() { --_i; return *this; }
self& operator+=(Distance n) { _i += n; return *this; }
self& operator-=(Distance n) { _i -= n; return *this; }
bool operator==(const self& x) const { return _i == x._i; }
bool operator<(const self& x) const { return _i < x._i; }
friend Distance operator-(const self& x, const self& y) {
return x._i - y._i;
}
protected:
T* _i;
};
int
main()
{
string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" };
{
test_iter<string,string&,string*> i = array,
ie = array + sizeof(array)/sizeof(string);
// Tests for all of the operators added by random_access_iterator_helper
// test i++
while (i != ie)
cout << *i++ << " ";
cout << endl;
i = array;
// test i--
while (ie != i) {
ie--;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
// test i->m
while (i != ie) {
cout << i->size() << " ";
++i;
}
cout << endl;
i = array;
// test i + n
while (i < ie) {
cout << *i << " ";
i = i + 2;
}
cout << endl;
i = array;
// test n + i
while (i < ie) {
cout << *i << " ";
i = ptrdiff_t(2) + i;
}
cout << endl;
i = array;
// test i - n
while (ie > i) {
ie = ie - 2;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
// test i[n]
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
cout << i[j] << " ";
cout << endl;
}
{
test_iter<string, const string&, const string*> i = array,
ie = array + sizeof(array)/sizeof(string);
// Tests for all of the operators added by random_access_iterator_helper
// test i++
while (i != ie)
cout << *i++ << " ";
cout << endl;
i = array;
// test i--
while (ie != i) {
ie--;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
// test i->m
while (i != ie) {
cout << i->size() << " ";
++i;
}
cout << endl;
i = array;
// test i + n
while (i < ie) {
cout << *i << " ";
i = i + 2;
}
cout << endl;
i = array;
// test n + i
while (i < ie) {
cout << *i << " ";
i = ptrdiff_t(2) + i;
}
cout << endl;
i = array;
// test i - n
while (ie > i) {
ie = ie - 2;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
// test i[n]
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
cout << i[j] << " ";
cout << endl;
}
return 0;
}

38
noncopyable_test.cpp Normal file
View File

@@ -0,0 +1,38 @@
// boost class noncopyable test program ------------------------------------//
// (C) Copyright boost.org 1999. 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.
// Revision History
// 9 Jun 99 Add unnamed namespace
// 2 Jun 99 Initial Version
#include <boost/utility.hpp>
#include <iostream>
// This program demonstrates compiler errors resulting from trying to copy
// construct or copy assign a class object derived from class noncopyable.
namespace
{
class DontTreadOnMe : boost::noncopyable
{
public:
DontTreadOnMe() { std::cout << "defanged!" << std::endl; }
}; // DontTreadOnMe
} // unnamed namespace
int main()
{
DontTreadOnMe object1;
DontTreadOnMe object2(object1);
object1 = object2;
return 0;
} // main

481
operators_test.cpp Normal file
View File

@@ -0,0 +1,481 @@
// Demonstrate and test boost/operators.hpp -------------------------------//
// (C) Copyright Beman Dawes 1999. 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.
// Revision History
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
// wrapping integral types and comparing the results of operations to
// the results for the raw types (David Abrahams)
// 12 Dec 99 Minor update, output confirmation message.
// 15 Nov 99 Initial version
#include <boost/operators.hpp>
#include <cassert>
#include <iostream>
#include <boost/min_rand.hpp>
namespace
{
// avoiding a template version of true_value so as to not confuse VC++
int true_value(int x) { return x; }
long true_value(long x) { return x; }
signed char true_value(signed char x) { return x; }
unsigned int true_value(unsigned int x) { return x; }
unsigned long true_value(unsigned long x) { return x; }
unsigned char true_value(unsigned char x) { return x; }
// The use of operators<> here tended to obscure interactions with certain
// compiler bugs
template <class T>
class Wrapped1 : boost::operators<Wrapped1<T> >
{
public:
explicit Wrapped1( T v = T() ) : _value(v) {}
T value() const { return _value; }
bool operator<(const Wrapped1& x) const { return _value < x._value; }
bool operator==(const Wrapped1& x) const { return _value == x._value; }
Wrapped1& operator+=(const Wrapped1& x)
{ _value += x._value; return *this; }
Wrapped1& operator-=(const Wrapped1& x)
{ _value -= x._value; return *this; }
Wrapped1& operator*=(const Wrapped1& x)
{ _value *= x._value; return *this; }
Wrapped1& operator/=(const Wrapped1& x)
{ _value /= x._value; return *this; }
Wrapped1& operator%=(const Wrapped1& x)
{ _value %= x._value; return *this; }
Wrapped1& operator|=(const Wrapped1& x)
{ _value |= x._value; return *this; }
Wrapped1& operator&=(const Wrapped1& x)
{ _value &= x._value; return *this; }
Wrapped1& operator^=(const Wrapped1& x)
{ _value ^= x._value; return *this; }
Wrapped1& operator++() { ++_value; return *this; }
Wrapped1& operator--() { --_value; return *this; }
private:
T _value;
};
template <class T>
T true_value(Wrapped1<T> x) { return x.value(); }
template <class T, class U>
class Wrapped2 :
boost::operators<Wrapped2<T, U> >,
boost::operators2<Wrapped2<T, U>, U>
{
public:
explicit Wrapped2( T v = T() ) : _value(v) {}
T value() const { return _value; }
bool operator<(const Wrapped2& x) const { return _value < x._value; }
bool operator==(const Wrapped2& x) const { return _value == x._value; }
Wrapped2& operator+=(const Wrapped2& x)
{ _value += x._value; return *this; }
Wrapped2& operator-=(const Wrapped2& x)
{ _value -= x._value; return *this; }
Wrapped2& operator*=(const Wrapped2& x)
{ _value *= x._value; return *this; }
Wrapped2& operator/=(const Wrapped2& x)
{ _value /= x._value; return *this; }
Wrapped2& operator%=(const Wrapped2& x)
{ _value %= x._value; return *this; }
Wrapped2& operator|=(const Wrapped2& x)
{ _value |= x._value; return *this; }
Wrapped2& operator&=(const Wrapped2& x)
{ _value &= x._value; return *this; }
Wrapped2& operator^=(const Wrapped2& x)
{ _value ^= x._value; return *this; }
Wrapped2& operator++() { ++_value; return *this; }
Wrapped2& operator--() { --_value; return *this; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
bool operator==(U u) const { return _value == u; }
Wrapped2& operator+=(U u) { _value += u; return *this; }
Wrapped2& operator-=(U u) { _value -= u; return *this; }
Wrapped2& operator*=(U u) { _value *= u; return *this; }
Wrapped2& operator/=(U u) { _value /= u; return *this; }
Wrapped2& operator%=(U u) { _value %= u; return *this; }
Wrapped2& operator|=(U u) { _value |= u; return *this; }
Wrapped2& operator&=(U u) { _value &= u; return *this; }
Wrapped2& operator^=(U u) { _value ^= u; return *this; }
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped2<T,U> x) { return x.value(); }
// MyInt uses only the single template-argument form of all_operators<>
typedef Wrapped1<int> MyInt;
typedef Wrapped2<long, long> MyLong;
template <class X1, class Y1, class X2, class Y2>
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert(true_value(y1) == true_value(y2));
assert(true_value(x1) == true_value(x2));
}
template <class X1, class Y1, class X2, class Y2>
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 < y1) == (x2 < y2));
assert((x1 <= y1) == (x2 <= y2));
assert((x1 >= y1) == (x2 >= y2));
assert((x1 > y1) == (x2 > y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_less_than_comparable_aux(x1, y1, x2, y2);
test_less_than_comparable_aux(y1, x1, y2, x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 == y1) == (x2 == y2));
assert((x1 != y1) == (x2 != y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_equality_comparable_aux(x1, y1, x2, y2);
test_equality_comparable_aux(y1, x1, y2, x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 * y1).value() == (x2 * y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_multipliable_aux(x1, y1, x2, y2);
test_multipliable_aux(y1, x1, y2, x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 + y1).value() == (x2 + y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_addable_aux(x1, y1, x2, y2);
test_addable_aux(y1, x1, y2, x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
assert((x1 - y1).value() == x2 - y2);
}
template <class X1, class Y1, class X2, class Y2>
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
if (y2 != 0)
assert((x1 / y1).value() == x2 / y2);
}
template <class X1, class Y1, class X2, class Y2>
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
if (y2 != 0)
assert((x1 / y1).value() == x2 / y2);
}
template <class X1, class Y1, class X2, class Y2>
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 ^ y1).value() == (x2 ^ y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_xorable_aux(x1, y1, x2, y2);
test_xorable_aux(y1, x1, y2, x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 & y1).value() == (x2 & y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_andable_aux(x1, y1, x2, y2);
test_andable_aux(y1, x1, y2, x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 | y1).value() == (x2 | y2));
}
template <class X1, class Y1, class X2, class Y2>
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
test_orable_aux(x1, y1, x2, y2);
test_orable_aux(y1, x1, y2, x2);
}
template <class X1, class X2>
void test_incrementable(X1 x1, X2 x2)
{
sanity_check(x1, x1, x2, x2);
assert(x1++.value() == x2++);
assert(x1.value() == x2);
}
template <class X1, class X2>
void test_decrementable(X1 x1, X2 x2)
{
sanity_check(x1, x1, x2, x2);
assert(x1--.value() == x2--);
assert(x1.value() == x2);
}
template <class X1, class Y1, class X2, class Y2>
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
test_less_than_comparable(x1, y1, x2, y2);
test_equality_comparable(x1, y1, x2, y2);
test_multipliable(x1, y1, x2, y2);
test_addable(x1, y1, x2, y2);
test_subtractable(x1, y1, x2, y2);
test_dividable(x1, y1, x2, y2);
test_modable(x1, y1, x2, y2);
test_xorable(x1, y1, x2, y2);
test_andable(x1, y1, x2, y2);
test_orable(x1, y1, x2, y2);
test_incrementable(x1, x2);
test_decrementable(x1, x2);
}
template <class Big, class Small>
struct tester
{
void operator()(boost::min_rand& randomizer) const
{
Big b1 = Big(randomizer());
Big b2 = Big(randomizer());
Small s = Small(randomizer());
test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2);
test_all(Wrapped2<Big, Small>(b1), s, b1, s);
}
};
// added as a regression test. We had a bug which this uncovered.
struct Point
: boost::addable<Point,
boost::subtractable<Point> >
{
Point( int h, int v ) : h(h), v(v) {}
Point() :h(0), v(0) {}
const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; }
const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; }
int h;
int v;
};
} // unnamed namespace
// workaround for MSVC bug; for some reasons the compiler doesn't instantiate
// inherited operator templates at the moment it must, so the following
// explicit instantiations force it to do that.
#if defined(BOOST_MSVC) && (_MSC_VER <= 1200)
template Wrapped1<int>;
template Wrapped1<long>;
template Wrapped1<unsigned int>;
template Wrapped1<unsigned long>;
template Wrapped2<int, int>;
template Wrapped2<int, signed char>;
template Wrapped2<long, signed char>;
template Wrapped2<long, int>;
template Wrapped2<long, long>;
template Wrapped2<unsigned int, unsigned int>;
template Wrapped2<unsigned int, unsigned char>;
template Wrapped2<unsigned long, unsigned int>;
template Wrapped2<unsigned long, unsigned char>;
template Wrapped2<unsigned long, unsigned long>;
#endif
#ifdef NDEBUG
#error This program is pointless when NDEBUG disables assert()!
#endif
int main()
{
// Regression test.
Point x;
x = x + Point(3, 4);
x = x - Point(3, 4);
for (int n = 0; n < 10000; ++n)
{
boost::min_rand r;
tester<long, int>()(r);
tester<long, signed char>()(r);
tester<long, long>()(r);
tester<int, int>()(r);
tester<int, signed char>()(r);
tester<unsigned long, unsigned int>()(r);
tester<unsigned long, unsigned char>()(r);
tester<unsigned long, unsigned long>()(r);
tester<unsigned int, unsigned int>()(r);
tester<unsigned int, unsigned char>()(r);
}
MyInt i1(1);
MyInt i2(2);
MyInt i;
assert( i1.value() == 1 );
assert( i2.value() == 2 );
assert( i.value() == 0 );
i = i2;
assert( i.value() == 2 );
assert( i2 == i );
assert( i1 != i2 );
assert( i1 < i2 );
assert( i1 <= i2 );
assert( i <= i2 );
assert( i2 > i1 );
assert( i2 >= i1 );
assert( i2 >= i );
i = i1 + i2; assert( i.value() == 3 );
i = i + i2; assert( i.value() == 5 );
i = i - i1; assert( i.value() == 4 );
i = i * i2; assert( i.value() == 8 );
i = i / i2; assert( i.value() == 4 );
i = i % (i - i1); assert( i.value() == 1 );
i = i2 + i2; assert( i.value() == 4 );
i = i1 | i2 | i; assert( i.value() == 7 );
i = i & i2; assert( i.value() == 2 );
i = i + i1; assert( i.value() == 3 );
i = i ^ i1; assert( i.value() == 2 );
i = (i+i1)*(i2|i1); assert( i.value() == 9 );
MyLong j1(1);
MyLong j2(2);
MyLong j;
assert( j1.value() == 1 );
assert( j2.value() == 2 );
assert( j.value() == 0 );
j = j2;
assert( j.value() == 2 );
assert( j2 == j );
assert( 2 == j );
assert( j2 == 2 );
assert( j == j2 );
assert( j1 != j2 );
assert( j1 != 2 );
assert( 1 != j2 );
assert( j1 < j2 );
assert( 1 < j2 );
assert( j1 < 2 );
assert( j1 <= j2 );
assert( 1 <= j2 );
assert( j1 <= j );
assert( j <= j2 );
assert( 2 <= j2 );
assert( j <= 2 );
assert( j2 > j1 );
assert( 2 > j1 );
assert( j2 > 1 );
assert( j2 >= j1 );
assert( 2 >= j1 );
assert( j2 >= 1 );
assert( j2 >= j );
assert( 2 >= j );
assert( j2 >= 2 );
assert( (j1 + 2) == 3 );
assert( (1 + j2) == 3 );
j = j1 + j2; assert( j.value() == 3 );
assert( (j + 2) == 5 );
assert( (3 + j2) == 5 );
j = j + j2; assert( j.value() == 5 );
assert( (j - 1) == 4 );
j = j - j1; assert( j.value() == 4 );
assert( (j * 2) == 8 );
assert( (4 * j2) == 8 );
j = j * j2; assert( j.value() == 8 );
assert( (j / 2) == 4 );
j = j / j2; assert( j.value() == 4 );
assert( (j % 3) == 1 );
j = j % (j - j1); assert( j.value() == 1 );
j = j2 + j2; assert( j.value() == 4 );
assert( (1 | j2 | j) == 7 );
assert( (j1 | 2 | j) == 7 );
assert( (j1 | j2 | 4) == 7 );
j = j1 | j2 | j; assert( j.value() == 7 );
assert( (7 & j2) == 2 );
assert( (j & 2) == 2 );
j = j & j2; assert( j.value() == 2 );
j = j | j1; assert( j.value() == 3 );
assert( (3 ^ j1) == 2 );
assert( (j ^ 1) == 2 );
j = j ^ j1; assert( j.value() == 2 );
j = (j+j1)*(j2|j1); assert( j.value() == 9 );
std::cout << "0 errors detected\n";
return 0;
}

534
type_traits_test.cpp Normal file
View File

@@ -0,0 +1,534 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
/* Release notes:
23rd July 2000:
Removed all call_traits tests to call_traits_test.cpp
Removed all compressed_pair tests to compressed_pair_tests.cpp
Improved tests macros
Tidied up specialistions of type_types classes for test cases.
*/
#include <iostream>
#include <typeinfo>
#include <boost/type_traits.hpp>
using namespace boost;
#ifdef __BORLANDC__
#pragma option -w-ccc -w-rch -w-eff -w-aus
#endif
//
// define tests here
unsigned failures = 0;
unsigned test_count = 0;
#define value_test(v, x) ++test_count;\
if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#define type_test(v, x) ++test_count;\
if(is_same<v, x>::value == false){\
++failures; \
std::cout << "checking type of " << #x << "...failed" << std::endl; \
std::cout << " expected type was " << #v << std::endl; \
std::cout << " " << typeid(is_same<v, x>).name() << "::value is false" << std::endl; }
#else
#define type_test(v, x) ++test_count;\
if(typeid(v) != typeid(x)){\
++failures; \
std::cout << "checking type of " << #x << "...failed" << std::endl; \
std::cout << " expected type was " << #v << std::endl; \
std::cout << " " << "typeid(" #v ") != typeid(" #x ")" << std::endl; }
#endif
// Since there is no compiler support, we should specialize:
// is_enum for all enumerations (is_enum implies is_POD)
// is_union for all unions
// is_empty for all empty composites
// is_POD for all PODs (except enums) (is_POD implies has_*)
// has_* for any UDT that has that trait and is not POD
enum enum_UDT{ one, two, three };
struct UDT
{
UDT();
~UDT();
UDT(const UDT&);
UDT& operator=(const UDT&);
int i;
void f1();
int f2();
int f3(int);
int f4(int, float);
};
struct POD_UDT { int x; };
struct empty_UDT{ ~empty_UDT(){}; };
struct empty_POD_UDT{};
union union_UDT
{
int x;
double y;
~union_UDT();
};
union POD_union_UDT
{
int x;
double y;
};
union empty_union_UDT
{
~empty_union_UDT();
};
union empty_POD_union_UDT{};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
namespace boost {
template <> struct is_enum<enum_UDT>
{ static const bool value = true; };
template <> struct is_POD<POD_UDT>
{ static const bool value = true; };
// this type is not POD, so we have to specialize the has_* individually
template <> struct has_trivial_constructor<empty_UDT>
{ static const bool value = true; };
template <> struct has_trivial_copy<empty_UDT>
{ static const bool value = true; };
template <> struct has_trivial_assign<empty_UDT>
{ static const bool value = true; };
template <> struct is_POD<empty_POD_UDT>
{ static const bool value = true; };
template <> struct is_union<union_UDT>
{ static const bool value = true; };
template <> struct is_union<POD_union_UDT>
{ static const bool value = true; };
template <> struct is_POD<POD_union_UDT>
{ static const bool value = true; };
template <> struct is_union<empty_union_UDT>
{ static const bool value = true; };
// this type is not POD, so we have to specialize the has_* individually
template <> struct has_trivial_constructor<empty_union_UDT>
{ static const bool value = true; };
template <> struct has_trivial_copy<empty_union_UDT>
{ static const bool value = true; };
template <> struct has_trivial_assign<empty_union_UDT>
{ static const bool value = true; };
template <> struct is_union<empty_POD_union_UDT>
{ static const bool value = true; };
template <> struct is_POD<empty_POD_union_UDT>
{ static const bool value = true; };
}
#else
namespace boost {
template <> struct is_enum<enum_UDT>
{ enum{ value = true }; };
template <> struct is_POD<POD_UDT>
{ enum{ value = true }; };
// this type is not POD, so we have to specialize the has_* individually
template <> struct has_trivial_constructor<empty_UDT>
{ enum{ value = true }; };
template <> struct has_trivial_copy<empty_UDT>
{ enum{ value = true }; };
template <> struct has_trivial_assign<empty_UDT>
{ enum{ value = true }; };
template <> struct is_POD<empty_POD_UDT>
{ enum{ value = true }; };
template <> struct is_union<union_UDT>
{ enum{ value = true }; };
template <> struct is_union<POD_union_UDT>
{ enum{ value = true }; };
template <> struct is_POD<POD_union_UDT>
{ enum{ value = true }; };
template <> struct is_union<empty_union_UDT>
{ enum{ value = true }; };
// this type is not POD, so we have to specialize the has_* individually
template <> struct has_trivial_constructor<empty_union_UDT>
{ enum{ value = true }; };
template <> struct has_trivial_copy<empty_union_UDT>
{ enum{ value = true }; };
template <> struct has_trivial_assign<empty_union_UDT>
{ enum{ value = true }; };
template <> struct is_union<empty_POD_union_UDT>
{ enum{ value = true }; };
template <> struct is_POD<empty_POD_union_UDT>
{ enum{ value = true }; };
}
#endif
// Steve: All comments that I (Steve Cleary) have added below are prefixed with
// "Steve:" The failures that BCB4 has on the tests are due to Borland's
// not considering cv-qual's as a part of the type -- they are considered
// compiler hints only. These failures should be fixed before long.
int main()
{
std::cout << "Checking type operations..." << std::endl << std::endl;
// cv-qualifiers applied to reference types should have no effect
// declare these here for later use with is_reference and remove_reference:
typedef int& r_type;
typedef const r_type cr_type;
type_test(int, remove_reference<int>::type)
type_test(const int, remove_reference<const int>::type)
type_test(int, remove_reference<int&>::type)
type_test(const int, remove_reference<const int&>::type)
type_test(volatile int, remove_reference<volatile int&>::type)
type_test(int, remove_reference<cr_type>::type)
type_test(int, remove_const<const int>::type)
// Steve: fails on BCB4
type_test(volatile int, remove_const<volatile int>::type)
// Steve: fails on BCB4
type_test(volatile int, remove_const<const volatile int>::type)
type_test(int, remove_const<int>::type)
type_test(int*, remove_const<int* const>::type)
type_test(int, remove_volatile<volatile int>::type)
// Steve: fails on BCB4
type_test(const int, remove_volatile<const int>::type)
// Steve: fails on BCB4
type_test(const int, remove_volatile<const volatile int>::type)
type_test(int, remove_volatile<int>::type)
type_test(int*, remove_volatile<int* volatile>::type)
type_test(int, remove_cv<volatile int>::type)
type_test(int, remove_cv<const int>::type)
type_test(int, remove_cv<const volatile int>::type)
type_test(int, remove_cv<int>::type)
type_test(int*, remove_cv<int* volatile>::type)
type_test(int*, remove_cv<int* const>::type)
type_test(int*, remove_cv<int* const volatile>::type)
type_test(const int *, remove_cv<const int * const>::type)
type_test(int, remove_bounds<int>::type)
type_test(int*, remove_bounds<int*>::type)
type_test(int, remove_bounds<int[3]>::type)
type_test(int[3], remove_bounds<int[2][3]>::type)
std::cout << std::endl << "Checking type properties..." << std::endl << std::endl;
value_test(true, (is_same<int, int>::value))
value_test(false, (is_same<int, const int>::value))
value_test(false, (is_same<int, int&>::value))
value_test(false, (is_same<int*, const int*>::value))
value_test(false, (is_same<int*, int*const>::value))
value_test(false, (is_same<int, int[2]>::value))
value_test(false, is_const<int>::value)
value_test(true, is_const<const int>::value)
value_test(false, is_const<volatile int>::value)
value_test(true, is_const<const volatile int>::value)
value_test(false, is_volatile<int>::value)
value_test(false, is_volatile<const int>::value)
value_test(true, is_volatile<volatile int>::value)
value_test(true, is_volatile<const volatile int>::value)
value_test(true, is_void<void>::value)
// Steve: fails on BCB4
// JM: but looks as though it should according to [3.9.3p1]?
//value_test(false, is_void<const void>::value)
value_test(false, is_void<int>::value)
value_test(false, is_standard_unsigned_integral<UDT>::value)
value_test(false, is_standard_unsigned_integral<void>::value)
value_test(false, is_standard_unsigned_integral<bool>::value)
value_test(false, is_standard_unsigned_integral<char>::value)
value_test(false, is_standard_unsigned_integral<signed char>::value)
value_test(true, is_standard_unsigned_integral<unsigned char>::value)
value_test(false, is_standard_unsigned_integral<wchar_t>::value)
value_test(false, is_standard_unsigned_integral<short>::value)
value_test(true, is_standard_unsigned_integral<unsigned short>::value)
value_test(false, is_standard_unsigned_integral<int>::value)
value_test(true, is_standard_unsigned_integral<unsigned int>::value)
value_test(false, is_standard_unsigned_integral<long>::value)
value_test(true, is_standard_unsigned_integral<unsigned long>::value)
value_test(false, is_standard_unsigned_integral<float>::value)
value_test(false, is_standard_unsigned_integral<double>::value)
value_test(false, is_standard_unsigned_integral<long double>::value)
#ifdef ULLONG_MAX
value_test(false, is_standard_unsigned_integral<long long>::value)
value_test(false, is_standard_unsigned_integral<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(false, is_standard_unsigned_integral<__int64>::value)
value_test(false, is_standard_unsigned_integral<unsigned __int64>::value)
#endif
value_test(false, is_standard_signed_integral<UDT>::value)
value_test(false, is_standard_signed_integral<void>::value)
value_test(false, is_standard_signed_integral<bool>::value)
value_test(false, is_standard_signed_integral<char>::value)
value_test(true, is_standard_signed_integral<signed char>::value)
value_test(false, is_standard_signed_integral<unsigned char>::value)
value_test(false, is_standard_signed_integral<wchar_t>::value)
value_test(true, is_standard_signed_integral<short>::value)
value_test(false, is_standard_signed_integral<unsigned short>::value)
value_test(true, is_standard_signed_integral<int>::value)
value_test(false, is_standard_signed_integral<unsigned int>::value)
value_test(true, is_standard_signed_integral<long>::value)
value_test(false, is_standard_signed_integral<unsigned long>::value)
value_test(false, is_standard_signed_integral<float>::value)
value_test(false, is_standard_signed_integral<double>::value)
value_test(false, is_standard_signed_integral<long double>::value)
#ifdef ULLONG_MAX
value_test(false, is_standard_signed_integral<long long>::value)
value_test(false, is_standard_signed_integral<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(false, is_standard_signed_integral<__int64>::value)
value_test(false, is_standard_signed_integral<unsigned __int64>::value)
#endif
value_test(false, is_standard_arithmetic<UDT>::value)
value_test(false, is_standard_arithmetic<void>::value)
value_test(true, is_standard_arithmetic<bool>::value)
value_test(true, is_standard_arithmetic<char>::value)
value_test(true, is_standard_arithmetic<signed char>::value)
value_test(true, is_standard_arithmetic<unsigned char>::value)
value_test(true, is_standard_arithmetic<wchar_t>::value)
value_test(true, is_standard_arithmetic<short>::value)
value_test(true, is_standard_arithmetic<unsigned short>::value)
value_test(true, is_standard_arithmetic<int>::value)
value_test(true, is_standard_arithmetic<unsigned int>::value)
value_test(true, is_standard_arithmetic<long>::value)
value_test(true, is_standard_arithmetic<unsigned long>::value)
value_test(true, is_standard_arithmetic<float>::value)
value_test(true, is_standard_arithmetic<double>::value)
value_test(true, is_standard_arithmetic<long double>::value)
#ifdef ULLONG_MAX
value_test(false, is_standard_arithmetic<long long>::value)
value_test(false, is_standard_arithmetic<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(false, is_standard_arithmetic<__int64>::value)
value_test(false, is_standard_arithmetic<unsigned __int64>::value)
#endif
value_test(false, is_standard_fundamental<UDT>::value)
value_test(true, is_standard_fundamental<void>::value)
value_test(true, is_standard_fundamental<bool>::value)
value_test(true, is_standard_fundamental<char>::value)
value_test(true, is_standard_fundamental<signed char>::value)
value_test(true, is_standard_fundamental<unsigned char>::value)
value_test(true, is_standard_fundamental<wchar_t>::value)
value_test(true, is_standard_fundamental<short>::value)
value_test(true, is_standard_fundamental<unsigned short>::value)
value_test(true, is_standard_fundamental<int>::value)
value_test(true, is_standard_fundamental<unsigned int>::value)
value_test(true, is_standard_fundamental<long>::value)
value_test(true, is_standard_fundamental<unsigned long>::value)
value_test(true, is_standard_fundamental<float>::value)
value_test(true, is_standard_fundamental<double>::value)
value_test(true, is_standard_fundamental<long double>::value)
#ifdef ULLONG_MAX
value_test(false, is_standard_fundamental<long long>::value)
value_test(false, is_standard_fundamental<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(false, is_standard_fundamental<__int64>::value)
value_test(false, is_standard_fundamental<unsigned __int64>::value)
#endif
value_test(false, is_arithmetic<UDT>::value)
value_test(true, is_arithmetic<char>::value)
value_test(true, is_arithmetic<signed char>::value)
value_test(true, is_arithmetic<unsigned char>::value)
value_test(true, is_arithmetic<wchar_t>::value)
value_test(true, is_arithmetic<short>::value)
value_test(true, is_arithmetic<unsigned short>::value)
value_test(true, is_arithmetic<int>::value)
value_test(true, is_arithmetic<unsigned int>::value)
value_test(true, is_arithmetic<long>::value)
value_test(true, is_arithmetic<unsigned long>::value)
value_test(true, is_arithmetic<float>::value)
value_test(true, is_arithmetic<double>::value)
value_test(true, is_arithmetic<long double>::value)
value_test(true, is_arithmetic<bool>::value)
#ifdef ULLONG_MAX
value_test(true, is_arithmetic<long long>::value)
value_test(true, is_arithmetic<unsigned long long>::value)
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
value_test(true, is_arithmetic<__int64>::value)
value_test(true, is_arithmetic<unsigned __int64>::value)
#endif
value_test(false, is_array<int>::value)
value_test(false, is_array<int*>::value)
value_test(true, is_array<int[2]>::value)
value_test(true, is_array<int[2][3]>::value)
value_test(true, is_array<UDT[2]>::value)
typedef void(*f1)();
typedef int(*f2)(int);
typedef int(*f3)(int, bool);
typedef void (UDT::*mf1)();
typedef int (UDT::*mf2)();
typedef int (UDT::*mf3)(int);
typedef int (UDT::*mf4)(int, float);
value_test(false, is_pointer<int>::value)
value_test(false, is_pointer<int&>::value)
value_test(true, is_pointer<int*>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1
value_test(false, is_pointer<int*const>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1
value_test(false, is_pointer<int*volatile>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1
value_test(false, is_pointer<int*const volatile>::value)
value_test(true, is_pointer<f1>::value)
value_test(true, is_pointer<f2>::value)
value_test(true, is_pointer<f3>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3
value_test(false, is_pointer<mf1>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3
value_test(false, is_pointer<mf2>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3
value_test(false, is_pointer<mf3>::value)
// Steve: was 'true', should be 'false', via 3.9.2p3
value_test(false, is_pointer<mf4>::value)
value_test(false, is_reference<bool>::value)
value_test(true, is_reference<int&>::value)
value_test(true, is_reference<const int&>::value)
value_test(true, is_reference<volatile int &>::value)
value_test(true, is_reference<r_type>::value)
value_test(true, is_reference<cr_type>::value)
value_test(false, is_class<int>::value)
value_test(false, is_class<const int>::value)
value_test(false, is_class<volatile int>::value)
value_test(false, is_class<int*>::value)
value_test(false, is_class<int* const>::value)
value_test(false, is_class<int[2]>::value)
value_test(false, is_class<int&>::value)
value_test(false, is_class<mf4>::value)
value_test(false, is_class<f1>::value)
value_test(false, is_class<enum_UDT>::value)
value_test(true, is_class<UDT>::value)
value_test(true, is_class<UDT const>::value)
value_test(true, is_class<UDT volatile>::value)
value_test(true, is_class<empty_UDT>::value)
value_test(true, is_class<std::iostream>::value)
value_test(false, is_class<UDT*>::value)
value_test(false, is_class<UDT[2]>::value)
value_test(false, is_class<UDT&>::value)
value_test(true, is_object<int>::value)
value_test(true, is_object<UDT>::value)
value_test(false, is_object<int&>::value)
value_test(false, is_object<void>::value)
value_test(true, is_standard_scalar<int>::value)
value_test(true, is_extension_scalar<void*>::value)
value_test(false, is_enum<int>::value)
value_test(true, is_enum<enum_UDT>::value)
value_test(false, is_member_pointer<f1>::value)
value_test(false, is_member_pointer<f2>::value)
value_test(false, is_member_pointer<f3>::value)
value_test(true, is_member_pointer<mf1>::value)
value_test(true, is_member_pointer<mf2>::value)
value_test(true, is_member_pointer<mf3>::value)
value_test(true, is_member_pointer<mf4>::value)
value_test(false, is_empty<int>::value)
value_test(false, is_empty<int*>::value)
value_test(false, is_empty<int&>::value)
value_test(false, is_empty<int[2]>::value)
value_test(false, is_empty<f1>::value)
value_test(false, is_empty<mf1>::value)
value_test(false, is_empty<UDT>::value)
value_test(true, is_empty<empty_UDT>::value)
value_test(true, is_empty<empty_POD_UDT>::value)
value_test(true, is_empty<empty_union_UDT>::value)
value_test(false, is_empty<enum_UDT>::value)
value_test(true, has_trivial_constructor<int>::value)
value_test(true, has_trivial_constructor<int*>::value)
value_test(true, has_trivial_constructor<int*const>::value)
value_test(true, has_trivial_constructor<const int>::value)
value_test(true, has_trivial_constructor<volatile int>::value)
value_test(true, has_trivial_constructor<int[2]>::value)
value_test(true, has_trivial_constructor<int[3][2]>::value)
value_test(true, has_trivial_constructor<int[2][4][5][6][3]>::value)
value_test(true, has_trivial_constructor<f1>::value)
value_test(true, has_trivial_constructor<mf2>::value)
value_test(false, has_trivial_constructor<UDT>::value)
value_test(true, has_trivial_constructor<empty_UDT>::value)
value_test(true, has_trivial_constructor<enum_UDT>::value)
value_test(true, has_trivial_copy<int>::value)
value_test(true, has_trivial_copy<int*>::value)
value_test(true, has_trivial_copy<int*const>::value)
value_test(true, has_trivial_copy<const int>::value)
// Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
value_test(true, has_trivial_copy<volatile int>::value)
value_test(true, has_trivial_copy<int[2]>::value)
value_test(true, has_trivial_copy<int[3][2]>::value)
value_test(true, has_trivial_copy<int[2][4][5][6][3]>::value)
value_test(true, has_trivial_copy<f1>::value)
value_test(true, has_trivial_copy<mf2>::value)
value_test(false, has_trivial_copy<UDT>::value)
value_test(true, has_trivial_copy<empty_UDT>::value)
value_test(true, has_trivial_copy<enum_UDT>::value)
value_test(true, has_trivial_assign<int>::value)
value_test(true, has_trivial_assign<int*>::value)
value_test(true, has_trivial_assign<int*const>::value)
value_test(true, has_trivial_assign<const int>::value)
// Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
value_test(true, has_trivial_assign<volatile int>::value)
value_test(true, has_trivial_assign<int[2]>::value)
value_test(true, has_trivial_assign<int[3][2]>::value)
value_test(true, has_trivial_assign<int[2][4][5][6][3]>::value)
value_test(true, has_trivial_assign<f1>::value)
value_test(true, has_trivial_assign<mf2>::value)
value_test(false, has_trivial_assign<UDT>::value)
value_test(true, has_trivial_assign<empty_UDT>::value)
value_test(true, has_trivial_assign<enum_UDT>::value)
value_test(true, has_trivial_destructor<int>::value)
value_test(true, has_trivial_destructor<int*>::value)
value_test(true, has_trivial_destructor<int*const>::value)
value_test(true, has_trivial_destructor<const int>::value)
value_test(true, has_trivial_destructor<volatile int>::value)
value_test(true, has_trivial_destructor<int[2]>::value)
value_test(true, has_trivial_destructor<int[3][2]>::value)
value_test(true, has_trivial_destructor<int[2][4][5][6][3]>::value)
value_test(true, has_trivial_destructor<f1>::value)
value_test(true, has_trivial_destructor<mf2>::value)
value_test(false, has_trivial_destructor<UDT>::value)
value_test(false, has_trivial_destructor<empty_UDT>::value)
value_test(true, has_trivial_destructor<enum_UDT>::value)
value_test(true, is_POD<int>::value)
value_test(true, is_POD<int*>::value)
// Steve: was 'true', should be 'false', via 3.9p10
value_test(false, is_POD<int&>::value)
value_test(true, is_POD<int*const>::value)
value_test(true, is_POD<const int>::value)
// Steve: was 'false', should be 'true', via 3.9p10
value_test(true, is_POD<volatile int>::value)
// Steve: was 'true', should be 'false', via 3.9p10
value_test(false, is_POD<const int&>::value)
value_test(true, is_POD<int[2]>::value)
value_test(true, is_POD<int[3][2]>::value)
value_test(true, is_POD<int[2][4][5][6][3]>::value)
value_test(true, is_POD<f1>::value)
value_test(true, is_POD<mf2>::value)
value_test(false, is_POD<UDT>::value)
value_test(false, is_POD<empty_UDT>::value)
value_test(true, is_POD<enum_UDT>::value)
std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
std::cin.get();
return failures;
}