From 06adfe9658d30b448a52aa950b5125a61c0d0002 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 7 Jul 2000 16:04:40 +0000 Subject: [PATCH] This commit was generated by cvs2svn to compensate for changes in r4, which included commits to RCS files with non-trunk default branches. [SVN r7621] --- .gitattributes | 96 +++ algo_opt_examples.cpp | 406 +++++++++++++ call_traits_test.cpp | 208 +++++++ cast_test.cpp | 149 +++++ include/boost/call_traits.hpp | 23 + include/boost/compressed_pair.hpp | 23 + include/boost/detail/call_traits.hpp | 97 +++ include/boost/detail/compressed_pair.hpp | 420 +++++++++++++ include/boost/detail/ob_call_traits.hpp | 35 ++ include/boost/detail/ob_compressed_pair.hpp | 69 +++ include/boost/operators.hpp | 559 ++++++++++++++++++ include/boost/utility.hpp | 69 +++ iterators_test.cpp | 169 ++++++ noncopyable_test.cpp | 38 ++ operators_test.cpp | 481 +++++++++++++++ type_traits_test.cpp | 623 ++++++++++++++++++++ 16 files changed, 3465 insertions(+) create mode 100644 .gitattributes create mode 100644 algo_opt_examples.cpp create mode 100644 call_traits_test.cpp create mode 100644 cast_test.cpp create mode 100644 include/boost/call_traits.hpp create mode 100644 include/boost/compressed_pair.hpp create mode 100644 include/boost/detail/call_traits.hpp create mode 100644 include/boost/detail/compressed_pair.hpp create mode 100644 include/boost/detail/ob_call_traits.hpp create mode 100644 include/boost/detail/ob_compressed_pair.hpp create mode 100644 include/boost/operators.hpp create mode 100644 include/boost/utility.hpp create mode 100644 iterators_test.cpp create mode 100644 noncopyable_test.cpp create mode 100644 operators_test.cpp create mode 100644 type_traits_test.cpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/algo_opt_examples.cpp b/algo_opt_examples.cpp new file mode 100644 index 0000000..6b795e7 --- /dev/null +++ b/algo_opt_examples.cpp @@ -0,0 +1,406 @@ + +/* + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::cout; +using std::endl; +using std::cin; + +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 +struct array_destroyer +{ + template + static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } +}; + +template <> +struct array_destroyer +{ + template + static void destroy_array(T*, T*){} +}; + +template +void do_destroy_array(T* first, T* last) +{ + while(first != last) + { + first->~T(); + ++first; + } +} + +}; // namespace detail + +template +inline void destroy_array(T* p1, T* p2) +{ + detail::array_destroyer::value>::destroy_array(p1, p2); +} + +// +// unoptimised versions of destroy_array: +// +template +void destroy_array1(T* first, T* last) +{ + while(first != last) + { + first->~T(); + ++first; + } +} +template +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 +struct copier +{ + template + static I2 do_copy(I1 first, I1 last, I2 out); +}; + +template +template +I2 copier::do_copy(I1 first, I1 last, I2 out) +{ + while(first != last) + { + *out = *first; + ++out; + ++first; + } + return out; +} + +template <> +struct copier +{ + template + static I2* do_copy(I1* first, I1* last, I2* out) + { + memcpy(out, first, (last-first)*sizeof(I2)); + return out+(last-first); + } +}; + + +} + +template +inline I2 copy(I1 first, I1 last, I2 out) +{ + typedef typename boost::remove_cv::value_type>::type v1_t; + typedef typename boost::remove_cv::value_type>::type v2_t; + enum{ can_opt = boost::is_same::value + && boost::is_pointer::value + && boost::is_pointer::value + && boost::has_trivial_assign::value }; + return detail::copier::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 +struct filler +{ + template + static void do_fill(I first, I last, typename boost::call_traits::param_type val); + }; + +template +template +void filler::do_fill(I first, I last, typename boost::call_traits::param_type val) +{ + while(first != last) + { + *first = val; + ++first; + } +} + +template <> +struct filler +{ + template + static void do_fill(I first, I last, T val) + { + memset(first, val, last-first); + } +}; + +} + +template +inline void fill(I first, I last, const T& val) +{ + enum{ can_opt = boost::is_pointer::value + && boost::is_arithmetic::value + && (sizeof(T) == 1) }; + typedef detail::filler filler_t; + filler_t::template do_fill(first, last, val); +} + +// +// iter_swap: +// tests whether iterator is a proxying iterator or not, and +// uses optimal form accordingly: +// +namespace detail{ + +template +struct swapper +{ + template + static void do_swap(I one, I two) + { + typedef typename std::iterator_traits::value_type v_t; + v_t v = *one; + *one = *two; + *two = v; + } +}; + +template <> +struct swapper +{ + template + static void do_swap(I one, I two) + { + using std::swap; + swap(*one, *two); + } +}; + +} + +template +inline void iter_swap(I1 one, I2 two) +{ + typedef typename std::iterator_traits::reference r1_t; + typedef typename std::iterator_traits::reference r2_t; + enum{ can_opt = boost::is_reference::value && boost::is_reference::value && boost::is_same::value }; + detail::swapper::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: " << 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(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(unoptimised#2): " << result << endl << endl; + + cout << "testing copy...\n" + "[Some standard library versions may already perform this optimisation.]" << endl; + /*cache load*/ opt::copy(ci_array, ci_array + array_size, i_array); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::copy(ci_array, ci_array + array_size, i_array); + } + result = t.elapsed(); + cout << "opt::copy: " << result << endl; + /*cache load*/ std::copy(ci_array, ci_array + array_size, i_array); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + std::copy(ci_array, ci_array + array_size, i_array); + } + result = t.elapsed(); + cout << "std::copy: " << result << endl; + /*cache load*/ opt::detail::copier::template do_copy(ci_array, ci_array + array_size, i_array); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::detail::copier::template do_copy(ci_array, ci_array + array_size, i_array); + } + result = t.elapsed(); + cout << "standard \"unoptimised\" copy: " << result << endl << endl; + + /*cache load*/ opt::copy(cc_array, cc_array + array_size, c_array); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::copy(cc_array, cc_array + array_size, c_array); + } + result = t.elapsed(); + cout << "opt::copy: " << result << endl; + /*cache load*/ std::copy(cc_array, cc_array + array_size, c_array); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + std::copy(cc_array, cc_array + array_size, c_array); + } + result = t.elapsed(); + cout << "std::copy: " << result << endl; + /*cache load*/ opt::detail::copier::template do_copy(cc_array, cc_array + array_size, c_array); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::detail::copier::template do_copy(cc_array, cc_array + array_size, c_array); + } + result = t.elapsed(); + cout << "standard \"unoptimised\" copy: " << result << endl << endl; + + cout << "testing fill(char)...\n" + "[Some standard library versions may already perform this optimisation.]" << endl; + /*cache load*/ opt::fill(c_array, c_array + array_size, (char)3); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::fill(c_array, c_array + array_size, (char)3); + } + result = t.elapsed(); + cout << "opt::fill: " << 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: " << result << endl << endl; + + cout << "testing fill(int)...\n" + "[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl; + /*cache load*/ opt::fill(i_array, i_array + array_size, 3); + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::fill(i_array, i_array + array_size, 3); + } + result = t.elapsed(); + cout << "opt::fill: " << 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: " << result << endl << endl; + + // + // testing iter_swap + // really just a check that it does in fact compile... + std::vector v1; + v1.push_back(0); + v1.push_back(1); + std::vector 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(); +} + + + + diff --git a/call_traits_test.cpp b/call_traits_test.cpp new file mode 100644 index 0000000..c615013 --- /dev/null +++ b/call_traits_test.cpp @@ -0,0 +1,208 @@ + +#include +#include +#include +#include +#include +#include + +// +// 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 +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::param_type param_type; + typedef typename boost::call_traits::reference reference; + typedef typename boost::call_traits::const_reference const_reference; + typedef T value_type; + typedef typename boost::call_traits::value_type result_type; + + // stored value: + value_type v_; + + // constructors: + contained() {} + contained(param_type p) : v_(p){} + // return byval: + result_type value() { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + // pass value: + void call(param_type p){} + +}; + +template +struct contained +{ + typedef typename boost::call_traits::param_type param_type; + typedef typename boost::call_traits::reference reference; + typedef typename boost::call_traits::const_reference const_reference; + typedef T value_type[N]; + typedef typename boost::call_traits::value_type result_type; + + value_type v_; + + contained(param_type p) + { + std::copy(p, p+N, v_); + } + // return byval: + result_type value() { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + void call(param_type p){} +}; + +template +contained::value_type> wrap(const T& t) +{ + return contained::value_type>(t); +} + +template +std::pair< + typename boost::call_traits::value_type, + typename boost::call_traits::value_type> + make_pair(const T1& t1, const T2& t2) +{ + return std::pair< + typename boost::call_traits::value_type, + typename boost::call_traits::value_type>(t1, t2); +} + +using namespace std; + +// +// struct checker: +// verifies behaviour of contained example: +// +template +struct checker +{ + typedef typename boost::call_traits::param_type param_type; + void operator()(param_type); +}; + +template +void checker::operator()(param_type p) +{ + T t(p); + contained 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::v_).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained::value).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained::get).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained::const_get).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained::call).name() << endl; + cout << endl; +} + +template +struct checker +{ + typedef typename boost::call_traits::param_type param_type; + void operator()(param_type); +}; + +template +void checker::operator()(param_type t) +{ + contained 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::v_).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained::value).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained::get).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained::const_get).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained::call).name() << endl; + cout << endl; +} + +// +// check_wrap: +// verifies behaviour of "wrap": +// +template +void check_wrap(T c, U u, const V& v) +{ + cout << "checking contained<" << typeid(T::value_type).name() << ">..." << endl; + assert(c.get() == u); + cout << "typeof deduced argument was: " << typeid(V).name() << endl; + cout << "typeof deduced parameter after adjustment was: " << typeid(v).name() << endl; + cout << "typeof contained<" << typeid(T::value_type).name() << ">::v_ is: " << typeid(&T::v_).name() << endl; + cout << "typeof contained<" << typeid(T::value_type).name() << ">::value is: " << typeid(&T::value).name() << endl; + cout << "typeof contained<" << typeid(T::value_type).name() << ">::get is: " << typeid(&T::get).name() << endl; + cout << "typeof contained<" << typeid(T::value_type).name() << ">::const_get is: " << typeid(&T::const_get).name() << endl; + cout << "typeof contained<" << typeid(T::value_type).name() << ">::call is: " << typeid(&T::call).name() << endl; + cout << endl; +} + +// +// check_make_pair: +// verifies behaviour of "make_pair": +// +template +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_; } +}; + + +int main() +{ + checker c1; + UDT u; + c1(u); + checker c2; + int i = 2; + c2(i); + int* pi = &i; + checker c3; + c3(pi); + checker c4; + c4(i); + checker c5; + c5(i); + + int a[2] = {1,2}; + checker c6; + c6(a); + + check_wrap(wrap(2), 2, 2); + const char ca[4] = "abc"; + // compiler can't deduce this for some reason: + //check_wrap(wrap(ca), ca, ca); + check_wrap(wrap(a), a, a); + check_make_pair(::make_pair(a, a), a, a); + + return 0; +} diff --git a/cast_test.cpp b/cast_test.cpp new file mode 100644 index 0000000..66ff462 --- /dev/null +++ b/cast_test.cpp @@ -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 +#include +#include +#include + +# 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( base ); // downcast + assert( derived->kind() == 'D' ); + + derived = 0; + derived = polymorphic_cast( base ); // downcast, throw on error + assert( derived->kind() == 'D' ); + + base2 = polymorphic_cast( 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( base ); } // #1 assert failure + + bool caught_exception = false; + try { derived = polymorphic_cast( 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::max(); + long large_negative_value = std::numeric_limits::min(); + signed char c = 0; + + c = large_value; // see if compiler generates warning + + c = numeric_cast( small_value ); + assert( c == 1 ); + c = 0; + c = numeric_cast( small_value ); + assert( c == 1 ); + c = 0; + c = numeric_cast( small_negative_value ); + assert( c == -1 ); + + // tests which should result in errors being detected + + caught_exception = false; + try { c = numeric_cast( 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( 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( 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( 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( std::numeric_limits::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 diff --git a/include/boost/call_traits.hpp b/include/boost/call_traits.hpp new file mode 100644 index 0000000..345a440 --- /dev/null +++ b/include/boost/call_traits.hpp @@ -0,0 +1,23 @@ +// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. +// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp +// for full copyright notices. + +#ifndef BOOST_CALL_TRAITS_HPP +#define BOOST_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#include +#else +#include +#endif + +#endif // BOOST_CALL_TRAITS_HPP diff --git a/include/boost/compressed_pair.hpp b/include/boost/compressed_pair.hpp new file mode 100644 index 0000000..c55ca2d --- /dev/null +++ b/include/boost/compressed_pair.hpp @@ -0,0 +1,23 @@ +// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. +// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp +// for full copyright notices. + +#ifndef BOOST_COMPRESSED_PAIR_HPP +#define BOOST_COMPRESSED_PAIR_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#include +#else +#include +#endif + +#endif // BOOST_COMPRESSED_PAIR_HPP diff --git a/include/boost/detail/call_traits.hpp b/include/boost/detail/call_traits.hpp new file mode 100644 index 0000000..07ed4ec --- /dev/null +++ b/include/boost/detail/call_traits.hpp @@ -0,0 +1,97 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + +#ifndef BOOST_DETAIL_CALL_TRAITS_HPP +#define BOOST_DETAIL_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifndef BOOST_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +namespace detail{ + +template +struct ct_imp +{ + typedef const T& param_type; +}; + +template +struct ct_imp +{ + typedef T const param_type; +}; + +template +struct ct_imp +{ + typedef T const param_type; +}; + +} + +template +struct call_traits +{ +public: + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + // + // C++ Builder workaround: we should be able to define a compile time + // constant and pass that as a single template parameter to ct_imp, + // however compiler bugs prevent this - instead pass three bool's to + // ct_imp and add an extra partial specialisation + // of ct_imp to handle the logic. (JM) + typedef typename detail::ct_imp::type>::value, ::boost::is_arithmetic::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type; +}; + +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; + +template +struct call_traits +{ +private: + typedef T array_type[N]; +public: + // degrades array to pointer: + typedef const T* value_type; + typedef array_type& reference; + typedef const array_type& const_reference; + typedef const T* param_type; +}; + +template +struct call_traits +{ +private: + typedef const T array_type[N]; +public: + // degrades array to pointer: + typedef const T* value_type; + typedef array_type& reference; + typedef const array_type& const_reference; + typedef const T* param_type; +}; + +} + +#endif // BOOST_DETAIL_CALL_TRAITS_HPP diff --git a/include/boost/detail/compressed_pair.hpp b/include/boost/detail/compressed_pair.hpp new file mode 100644 index 0000000..a4b3390 --- /dev/null +++ b/include/boost/detail/compressed_pair.hpp @@ -0,0 +1,420 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + +// +// JM changes 25 Jan 2000: +// Removed default arguments from compressed_pair_switch to get +// C++ Builder 4 to accept them +// rewriten swap to get gcc and C++ builder to compile. +// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. + +#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP +#define BOOST_DETAIL_COMPRESSED_PAIR_HPP + +#include +#ifndef BOOST_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_CALL_TRAITS_HPP +#include +#endif + +namespace boost +{ + +// compressed_pair + +namespace details +{ + // JM altered 26 Jan 2000: + template + struct compressed_pair_switch; + + template + struct compressed_pair_switch + {static const int value = 0;}; + + template + struct compressed_pair_switch + {static const int value = 3;}; + + template + struct compressed_pair_switch + {static const int value = 1;}; + + template + struct compressed_pair_switch + {static const int value = 2;}; + + template + struct compressed_pair_switch + {static const int value = 4;}; + + template + struct compressed_pair_switch + {static const int value = 5;}; + + template class compressed_pair_imp; + +#ifdef __GNUC__ + // workaround for GCC (JM): + using std::swap; +#endif + // + // can't call unqualified swap from within classname::swap + // as Koenig lookup rules will find only the classname::swap + // member function not the global declaration, so use cp_swap + // as a forwarding function (JM): + template + inline void cp_swap(T& t1, T& t2) + { + using std::swap; + swap(t1, t2); + } + + // 0 derive from neither + + template + class compressed_pair_imp + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_(x), second_(y) {} + + explicit compressed_pair_imp(first_param_type x) + : first_(x) {} + + explicit compressed_pair_imp(second_param_type y) + : second_(y) {} + + 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_imp& y) + { + cp_swap(first_, y.first_); + cp_swap(second_, y.second_); + } + private: + first_type first_; + second_type second_; + }; + + // 1 derive from T1 + + template + class compressed_pair_imp + : private T1 + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), second_(y) {} + + explicit compressed_pair_imp(first_param_type x) + : first_type(x) {} + + explicit compressed_pair_imp(second_param_type y) + : second_(y) {} + + 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_imp& y) + { + // no need to swap empty base class: + cp_swap(second_, y.second_); + } + private: + second_type second_; + }; + + // 2 derive from T2 + + template + class compressed_pair_imp + : private T2 + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : second_type(y), first_(x) {} + + explicit compressed_pair_imp(first_param_type x) + : first_(x) {} + + explicit compressed_pair_imp(second_param_type y) + : second_type(y) {} + + 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_imp& y) + { + // no need to swap empty base class: + cp_swap(first_, y.first_); + } + + private: + first_type first_; + }; + + // 3 derive from T1 and T2 + + template + class compressed_pair_imp + : private T1, + private T2 + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), second_type(y) {} + + explicit compressed_pair_imp(first_param_type x) + : first_type(x) {} + + explicit compressed_pair_imp(second_param_type y) + : second_type(y) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return *this;} + second_const_reference second() const {return *this;} + // + // no need to swap empty bases: + void swap(compressed_pair_imp&) {} + }; + + // JM + // 4 T1 == T2, T1 and T2 both empty + // Note does not actually store an instance of T2 at all - + // but reuses T1 base class for both first() and second(). + template + class compressed_pair_imp + : private T1 + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type) + : first_type(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 *this;} + second_const_reference second() const {return *this;} + + void swap(compressed_pair_imp&) {} + private: + }; + + // 5 T1 == T2 and are not empty: //JM + + template + class compressed_pair_imp + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_(x), second_(y) {} + + explicit compressed_pair_imp(first_param_type x) + : first_(x), second_(x) {} + + 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_imp& y) + { + cp_swap(first_, y.first_); + cp_swap(second_, y.second_); + } + private: + first_type first_; + second_type second_; + }; + +} // details + +template +class compressed_pair + : private ::boost::details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> +{ +private: + typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> base; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} + explicit compressed_pair(first_param_type x) : base(x) {} + explicit compressed_pair(second_param_type y) : base(y) {} + + first_reference first() {return base::first();} + first_const_reference first() const {return base::first();} + + second_reference second() {return base::second();} + second_const_reference second() const {return base::second();} + + void swap(compressed_pair& y) { base::swap(y); } +}; + +// JM +// Partial specialisation for case where T1 == T2: +// +template +class compressed_pair + : private details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> +{ +private: + typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> base; +public: + typedef T first_type; + typedef T second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} + explicit compressed_pair(first_param_type x) : base(x) {} + + first_reference first() {return base::first();} + first_const_reference first() const {return base::first();} + + second_reference second() {return base::second();} + second_const_reference second() const {return base::second();} + + void swap(compressed_pair& y) { base::swap(y); } +}; + +template +inline +void +swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +} // boost + +#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP + + diff --git a/include/boost/detail/ob_call_traits.hpp b/include/boost/detail/ob_call_traits.hpp new file mode 100644 index 0000000..332931e --- /dev/null +++ b/include/boost/detail/ob_call_traits.hpp @@ -0,0 +1,35 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. +// +// Crippled version for crippled compilers: +// +#ifndef BOOST_OB_CALL_TRAITS_HPP +#define BOOST_OB_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifndef BOOST_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +template +struct call_traits +{ + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef const T& param_type; +}; + +} + +#endif // BOOST_OB_CALL_TRAITS_HPP diff --git a/include/boost/detail/ob_compressed_pair.hpp b/include/boost/detail/ob_compressed_pair.hpp new file mode 100644 index 0000000..f5f5664 --- /dev/null +++ b/include/boost/detail/ob_compressed_pair.hpp @@ -0,0 +1,69 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. +// +// this version crippled for use with crippled compilers - John Maddock Jan 2000. + +#ifndef BOOST_OB_COMPRESSED_PAIR_HPP +#define BOOST_OB_COMPRESSED_PAIR_HPP + +#include +#ifndef BOOST_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_CALL_TRAITS_HPP +#include +#endif + +namespace boost +{ + +template +class compressed_pair +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : _first(), _second() {} + compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} + explicit compressed_pair(first_param_type x) : _first(x), _second() {} + //explicit compressed_pair(second_param_type y) : _first(), _second(y) {} + + 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& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +template +inline void swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +} // boost + +#endif // BOOST_OB_COMPRESSED_PAIR_HPP + diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp new file mode 100644 index 0000000..8144c7c --- /dev/null +++ b/include/boost/operators.hpp @@ -0,0 +1,559 @@ +// Boost operators.hpp header file ----------------------------------------// + +// (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. + +// (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 +// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and +// refactoring of compiler workarounds, additional documentation +// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from +// Dave Abrahams) +// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and +// Jeremy Siek (Dave Abrahams) +// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 +// (Mark Rodgers) +// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) +// 10 Jun 00 Support for the base class chaining technique was added +// (Aleksey Gurtovoy). See documentation and the comments below +// for the details. +// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) +// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary +// specializations of dividable, subtractable, modable (Ed Brey) +// 17 Nov 99 Add comments (Beman Dawes) +// Remove unnecessary specialization of operators<> (Ed Brey) +// 15 Nov 99 Fix less_than_comparable second operand type for first two +// operators.(Beman Dawes) +// 12 Nov 99 Add operators templates (Ed Brey) +// 11 Nov 99 Add single template parameter version for compilers without +// partial specialization (Beman Dawes) +// 10 Nov 99 Initial version + +// 10 Jun 00: +// An additional optional template parameter was added to most of +// operator templates to support the base class chaining technique (see +// documentation for the details). Unfortunately, a straightforward +// implementation of this change would have broken compatibility with the +// previous version of the library by making it impossible to use the same +// template name (e.g. 'addable') for both the 1- and 2-argument versions of +// an operator template. This implementation solves the backward-compatibility +// issue at the cost of some simplicity. +// +// One of the complications is an existence of special auxiliary class template +// 'is_chained_base<>' (see 'detail' namespace below), which is used +// to determine whether its template parameter is a library's operator template +// or not. You have to specialize 'is_chained_base<>' for each new +// operator template you add to the library. +// +// However, most of the non-trivial implementation details are hidden behind +// several local macros defined below, and as soon as you understand them, +// you understand the whole library implementation. + +#ifndef BOOST_OPERATORS_HPP +#define BOOST_OPERATORS_HPP + +#include +#include + +#if defined(__sgi) && !defined(__GNUC__) +#pragma set woff 1234 +#endif + +namespace boost { +namespace detail { + +class empty_base {}; + +} // namespace detail +} // namespace boost + +// In this section we supply the xxxx1 and xxxx2 forms of the operator +// templates, which are explicitly targeted at the 1-type-argument and +// 2-type-argument operator forms, respectively. Some compilers get confused +// when inline friend functions are overloaded in namespaces other than the +// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of +// these templates must go in the global namespace. + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +namespace boost +{ +#endif + +// Basic operator classes (contributed by Dave Abrahams) ------------------// + +// Note that friend functions defined in a class are implicitly inline. +// See the C++ std, 11.4 [class.friend] paragraph 5 + +template +struct less_than_comparable2 : B +{ + friend bool operator<=(const T& x, const U& y) { return !(x > y); } + friend bool operator>=(const T& x, const U& y) { return !(x < y); } + friend bool operator>(const U& x, const T& y) { return y < x; } + friend bool operator<(const U& x, const T& y) { return y > x; } + friend bool operator<=(const U& x, const T& y) { return !(y < x); } + friend bool operator>=(const U& x, const T& y) { return !(y > x); } +}; + +template +struct less_than_comparable1 : B +{ + friend bool operator>(const T& x, const T& y) { return y < x; } + friend bool operator<=(const T& x, const T& y) { return !(y < x); } + friend bool operator>=(const T& x, const T& y) { return !(x < y); } +}; + +template +struct equality_comparable2 : B +{ + friend bool operator==(const U& y, const T& x) { return x == y; } + friend bool operator!=(const U& y, const T& x) { return !(x == y); } + friend bool operator!=(const T& y, const U& x) { return !(y == x); } +}; + +template +struct equality_comparable1 : B +{ + friend bool operator!=(const T& x, const T& y) { return !(x == y); } +}; + +template +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; } +}; + +template +struct multipliable1 : B +{ + friend T operator*(T x, const T& y) { return x *= y; } +}; + +template +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; } +}; + +template +struct addable1 : B +{ + friend T operator+(T x, const T& y) { return x += y; } +}; + +template +struct subtractable2 : B +{ + friend T operator-(T x, const U& y) { return x -= y; } +}; + +template +struct subtractable1 : B +{ + friend T operator-(T x, const T& y) { return x -= y; } +}; + +template +struct dividable2 : B +{ + friend T operator/(T x, const U& y) { return x /= y; } +}; + +template +struct dividable1 : B +{ + friend T operator/(T x, const T& y) { return x /= y; } +}; + +template +struct modable2 : B +{ + friend T operator%(T x, const U& y) { return x %= y; } +}; + +template +struct modable1 : B +{ + friend T operator%(T x, const T& y) { return x %= y; } +}; + +template +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 +struct xorable1 : B +{ + friend T operator^(T x, const T& y) { return x ^= y; } +}; + +template +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 +struct andable1 : B +{ + friend T operator&(T x, const T& y) { return x &= y; } +}; + +template +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 +struct orable1 : B +{ + friend T operator|(T x, const T& y) { return x |= y; } +}; + +// incrementable and decrementable contributed by Jeremy Siek + +template +struct incrementable : B +{ + friend T operator++(T& x, int) + { + incrementable_type tmp(x); + ++x; + return tmp; + } +private: // The use of this typedef works around a Borland bug + typedef T incrementable_type; +}; + +template +struct decrementable : B +{ + friend T operator--(T& x, int) + { + decrementable_type tmp(x); + --x; + return tmp; + } +private: // The use of this typedef works around a Borland bug + typedef T decrementable_type; +}; + +// Iterator operator classes (contributed by Jeremy Siek) ------------------// + +template +struct dereferenceable : B +{ + P operator->() const + { + return &*static_cast(*this); + } +}; + +template +struct indexable : B +{ + R operator[](I n) const + { + return *(static_cast(*this) + n); + } +}; + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +} // namespace boost +#endif // BOOST_NO_OPERATORS_IN_NAMESPACE + + +// 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 +// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for +// two-argument forms. Note that these macros expect to be invoked from within +// boost. + +#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) + +# 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 \ + struct template_name : ::template_name {}; + +# define BOOST_IMPORT_TEMPLATE1(template_name) \ + template \ + struct template_name : ::template_name {}; + +# 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 + +// +// Here's where we put it all together, defining the xxxx forms of the templates +// in namespace boost. We also define specializations of is_chained_base<> for +// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as +// neccessary. +// +#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 +// 2nd argument type. + +namespace boost { +// A type parameter is used instead of a plain bool because Borland's compiler +// didn't cope well with the more obvious non-type template parameter. +namespace detail { + struct true_t {}; + struct false_t {}; +} // namespace detail + +// Unspecialized version assumes that most types are not being used for base +// class chaining. We specialize for the operator templates defined in this +// library. +template struct is_chained_base { + typedef ::boost::detail::false_t value; +}; + +} // namespace boost + +// Import a 2-type-argument operator template into boost (if neccessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ + BOOST_IMPORT_TEMPLATE2(template_name2) \ + template \ + struct is_chained_base< ::boost::template_name2 > { \ + typedef ::boost::detail::true_t value; \ + }; + +// Import a 1-type-argument operator template into boost (if neccessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ + BOOST_IMPORT_TEMPLATE1(template_name1) \ + template \ + struct is_chained_base< ::boost::template_name1 > { \ + typedef ::boost::detail::true_t value; \ + }; + +// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it +// can be used for specifying both 1-argument and 2-argument forms. Requires the +// existence of two previously defined class templates named '1' +// and '2' which must implement the corresponding 1- and 2- +// argument forms. +// +// The template type parameter O == is_chained_base::value is used to +// distinguish whether the 2nd argument to is being used for +// base class chaining from another boost operator template or is describing a +// 2nd operand type. O == true_t only when U is actually an another operator +// template from the library. Partial specialization is used to select an +// implementation in terms of either '1' or '2'. +// + +# define BOOST_OPERATOR_TEMPLATE(template_name) \ +template ::value \ + > \ +struct template_name : template_name##2 {}; \ + \ +template \ +struct template_name \ + : template_name##1 {}; \ + \ +template \ +struct template_name \ + : template_name##1 {}; \ + \ +template \ +struct is_chained_base< ::boost::template_name > { \ + typedef ::boost::detail::true_t value; \ +}; \ + \ +BOOST_OPERATOR_TEMPLATE2(template_name##2) \ +BOOST_OPERATOR_TEMPLATE1(template_name##1) + + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ + BOOST_IMPORT_TEMPLATE2(template_name2) +# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ + BOOST_IMPORT_TEMPLATE1(template_name1) + + // In this case we can only assume that template_name<> is equivalent to the + // more commonly needed template_name1<> form. +# define BOOST_OPERATOR_TEMPLATE(template_name) \ + template \ + struct template_name : template_name##1 {}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +namespace boost { + +BOOST_OPERATOR_TEMPLATE(less_than_comparable) +BOOST_OPERATOR_TEMPLATE(equality_comparable) +BOOST_OPERATOR_TEMPLATE(multipliable) +BOOST_OPERATOR_TEMPLATE(addable) +BOOST_OPERATOR_TEMPLATE(subtractable) +BOOST_OPERATOR_TEMPLATE(dividable) +BOOST_OPERATOR_TEMPLATE(modable) +BOOST_OPERATOR_TEMPLATE(xorable) +BOOST_OPERATOR_TEMPLATE(andable) +BOOST_OPERATOR_TEMPLATE(orable) + +BOOST_OPERATOR_TEMPLATE1(incrementable) +BOOST_OPERATOR_TEMPLATE1(decrementable) +BOOST_OPERATOR_TEMPLATE2(dereferenceable) + +// 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 + struct indexable : ::indexable {}; +# else + using ::indexable; +# endif +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_chained_base< ::boost::indexable > { + typedef ::boost::detail::true_t operator_template_type; +}; +#endif + +#undef BOOST_OPERATOR_TEMPLATE +#undef BOOST_OPERATOR_TEMPLATE2 +#undef BOOST_OPERATOR_TEMPLATE1 +#undef BOOST_IMPORT_TEMPLATE1 +#undef BOOST_IMPORT_TEMPLATE2 + +// The following 'operators' classes can only be used portably if the derived class +// declares ALL of the required member operators. +template +struct operators2 + : less_than_comparable2 > > > > > > > > > {}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct operators : operators2 {}; + +template struct operators +#else +template struct operators +#endif + : less_than_comparable > > > > > > > > > > > {}; + +// Iterator helper classes (contributed by Jeremy Siek) -------------------// +template +struct forward_iterator_helper + : equality_comparable > > > {}; + +template +struct bidirectional_iterator_helper + : equality_comparable > > > > {}; + +template +struct random_access_iterator_helper + : equality_comparable > > > > > > > > +{ +#ifndef __BORLANDC__ + friend D requires_difference_operator(const T& x, const T& y) { + return x - y; + } +#endif +}; // random_access_iterator_helper + +} // namespace boost + +#if defined(__sgi) && !defined(__GNUC__) +#pragma reset woff 1234 +#endif + +#endif // BOOST_OPERATORS_HPP diff --git a/include/boost/utility.hpp b/include/boost/utility.hpp new file mode 100644 index 0000000..44dd5d8 --- /dev/null +++ b/include/boost/utility.hpp @@ -0,0 +1,69 @@ +// boost utility.hpp header file -------------------------------------------// + +// (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. + +// 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 +#include // 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::iterator p = get_some_iterator(); + // const std::list::iterator prev = boost::prior(p); + + // Contributed by Dave Abrahams + + template + T next(T x) { return ++x; } + + template + 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 + diff --git a/iterators_test.cpp b/iterators_test.cpp new file mode 100644 index 0000000..e264aff --- /dev/null +++ b/iterators_test.cpp @@ -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 +#include +using namespace std; + +#include +using namespace boost; + + +template +struct test_iter + : public boost::random_access_iterator_helper< + test_iter, 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 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 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; +} diff --git a/noncopyable_test.cpp b/noncopyable_test.cpp new file mode 100644 index 0000000..e5103fb --- /dev/null +++ b/noncopyable_test.cpp @@ -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 +#include + +// 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 + \ No newline at end of file diff --git a/operators_test.cpp b/operators_test.cpp new file mode 100644 index 0000000..a194521 --- /dev/null +++ b/operators_test.cpp @@ -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 +#include +#include +#include + + +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 Wrapped1 : boost::operators > + { + 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 + T true_value(Wrapped1 x) { return x.value(); } + + template + class Wrapped2 : + boost::operators >, + boost::operators2, 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 + T true_value(Wrapped2 x) { return x.value(); } + + // MyInt uses only the single template-argument form of all_operators<> + typedef Wrapped1 MyInt; + + typedef Wrapped2 MyLong; + + template + 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 + 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 + 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 + void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + assert((x1 == y1) == (x2 == y2)); + assert((x1 != y1) == (x2 != y2)); + } + + template + 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 + void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + assert((x1 * y1).value() == (x2 * y2)); + } + + template + 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 + void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + assert((x1 + y1).value() == (x2 + y2)); + } + + template + 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 + void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check(x1, y1, x2, y2); + assert((x1 - y1).value() == x2 - y2); + } + + template + 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 + 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 + void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + assert((x1 ^ y1).value() == (x2 ^ y2)); + } + + template + 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 + void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + assert((x1 & y1).value() == (x2 & y2)); + } + + template + 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 + void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + assert((x1 | y1).value() == (x2 | y2)); + } + + template + 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 + void test_incrementable(X1 x1, X2 x2) + { + sanity_check(x1, x1, x2, x2); + assert(x1++.value() == x2++); + assert(x1.value() == x2); + } + + template + void test_decrementable(X1 x1, X2 x2) + { + sanity_check(x1, x1, x2, x2); + assert(x1--.value() == x2--); + assert(x1.value() == x2); + } + + template + 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 + struct tester + { + void operator()(boost::min_rand& randomizer) const + { + Big b1 = Big(randomizer()); + Big b2 = Big(randomizer()); + Small s = Small(randomizer()); + + test_all(Wrapped1(b1), Wrapped1(b2), b1, b2); + test_all(Wrapped2(b1), s, b1, s); + } + }; + + // added as a regression test. We had a bug which this uncovered. + struct Point + : boost::addable > + { + 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; +template Wrapped1; +template Wrapped1; +template Wrapped1; + +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +#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()(r); + tester()(r); + tester()(r); + tester()(r); + tester()(r); + + tester()(r); + tester()(r); + tester()(r); + tester()(r); + tester()(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; +} diff --git a/type_traits_test.cpp b/type_traits_test.cpp new file mode 100644 index 0000000..ffea91d --- /dev/null +++ b/type_traits_test.cpp @@ -0,0 +1,623 @@ +// (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. + +#include +#include + +#include +#include +#include + +using namespace boost; + +#ifdef __BORLANDC__ +#pragma option -w-ccc -w-rch -w-eff -w-aus +#endif + +// +// define tests here +unsigned failures = 0; + +#define value_test(v, x) if(v == x) /*std::cout << "checking value of " << #x << "...OK" << std::endl*/;\ + else{++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} + +#define type_test(v, x) if(is_same::value) /*std::cout << "checking type of " << #x << "...OK" << std::endl*/;\ + else{++failures; std::cout << "checking type of " << #x << "...failed (type was: " << typeid(is_same).name() << ")" << std::endl;} + +template +struct call_traits_test +{ + static void assert_construct(call_traits::param_type val); +}; + +template +void call_traits_test::assert_construct(call_traits::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t(val); + call_traits::value_type v(t); + call_traits::reference r(t); + call_traits::const_reference cr(t); + call_traits::param_type p(t); + call_traits::value_type v2(v); + call_traits::value_type v3(r); + call_traits::value_type v4(p); + call_traits::reference r2(v); + call_traits::reference r3(r); + call_traits::const_reference cr2(v); + call_traits::const_reference cr3(r); + call_traits::const_reference cr4(cr); + call_traits::const_reference cr5(p); + call_traits::param_type p2(v); + call_traits::param_type p3(r); + call_traits::param_type p4(p); +} +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct call_traits_test +{ + static void assert_construct(call_traits::param_type val); +}; + +template +void call_traits_test::assert_construct(call_traits::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t; + call_traits::value_type v(t); + call_traits::reference r(t); + call_traits::const_reference cr(t); + call_traits::param_type p(t); + call_traits::value_type v2(v); + call_traits::value_type v3(r); + call_traits::value_type v4(p); + call_traits::reference r2(v); + call_traits::reference r3(r); + call_traits::const_reference cr2(v); + call_traits::const_reference cr3(r); + call_traits::const_reference cr4(cr); + call_traits::const_reference cr5(p); + call_traits::param_type p2(v); + call_traits::param_type p3(r); + call_traits::param_type p4(p); +} +#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +// 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 }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { +template <> struct is_enum +{ static const bool value = true; }; +} +#endif +struct UDT +{ + UDT(); + ~UDT(); + UDT(const UDT&); + UDT& operator=(const UDT&); + int i; + + void f1(); + int f2(); + int f3(int); + int f4(int, float); +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +struct POD_UDT { int x; }; +namespace boost { +template <> struct is_POD +{ static const bool value = true; }; +} +#endif +struct empty_UDT +{ + ~empty_UDT(){}; +}; +namespace boost { +//template <> struct is_empty +//{ static const bool value = true; }; +// this type is not POD, so we have to specialize the has_* individually +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <> struct has_trivial_constructor +{ static const bool value = true; }; +template <> struct has_trivial_copy +{ static const bool value = true; }; +template <> struct has_trivial_assign +{ static const bool value = true; }; +} +#endif + +struct empty_POD_UDT{}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { +template <> struct is_empty +{ static const bool value = true; }; +template <> struct is_POD +{ static const bool value = true; }; +} +#endif +union union_UDT +{ + int x; + double y; + ~union_UDT(); +}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { +template <> struct is_union +{ static const bool value = true; }; +} +#endif +union POD_union_UDT +{ + int x; + double y; +}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { +template <> struct is_union +{ static const bool value = true; }; +template <> struct is_POD +{ static const bool value = true; }; +} +#endif +union empty_union_UDT +{ + ~empty_union_UDT(); +}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { +template <> struct is_union +{ static const bool value = true; }; +template <> struct is_empty +{ static const bool value = true; }; +// this type is not POD, so we have to specialize the has_* individually +template <> struct has_trivial_constructor +{ static const bool value = true; }; +template <> struct has_trivial_copy +{ static const bool value = true; }; +template <> struct has_trivial_assign +{ static const bool value = true; }; +} +#endif +union empty_POD_union_UDT{}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { +template <> struct is_union +{ static const bool value = true; }; +template <> struct is_empty +{ static const bool value = true; }; +template <> struct is_POD +{ static const bool 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; + + type_test(int, remove_reference::type) + type_test(const int, remove_reference::type) + type_test(int, remove_reference::type) + type_test(const int, remove_reference::type) + type_test(volatile int, remove_reference::type) + type_test(int, remove_const::type) + // Steve: fails on BCB4 + type_test(volatile int, remove_const::type) + // Steve: fails on BCB4 + type_test(volatile int, remove_const::type) + type_test(int, remove_const::type) + type_test(int*, remove_const::type) + type_test(int, remove_volatile::type) + // Steve: fails on BCB4 + type_test(const int, remove_volatile::type) + // Steve: fails on BCB4 + type_test(const int, remove_volatile::type) + type_test(int, remove_volatile::type) + type_test(int*, remove_volatile::type) + type_test(int, remove_cv::type) + type_test(int, remove_cv::type) + type_test(int, remove_cv::type) + type_test(int, remove_cv::type) + type_test(int*, remove_cv::type) + type_test(int*, remove_cv::type) + type_test(int*, remove_cv::type) + type_test(const int *, remove_cv::type) + type_test(int, remove_bounds::type) + type_test(int*, remove_bounds::type) + type_test(int, remove_bounds::type) + type_test(int[3], remove_bounds::type) + + type_test(const int, call_traits::param_type) + type_test(const char, call_traits::param_type) +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + type_test(char&, call_traits::param_type) + type_test(const char&, call_traits::param_type) +#endif + std::cout << std::endl << "Checking type properties..." << std::endl << std::endl; + + value_test(false, is_const::value) + value_test(true, is_const::value) + value_test(false, is_const::value) + value_test(true, is_const::value) + + value_test(false, is_volatile::value) + value_test(false, is_volatile::value) + value_test(true, is_volatile::value) + value_test(true, is_volatile::value) + + value_test(true, is_void::value) + // Steve: fails on BCB4 + value_test(false, is_void::value) + value_test(false, is_void::value) + + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(true, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(true, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(true, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(true, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + #ifdef ULLONG_MAX + value_test(false, is_standard_unsigned_integral::value) + value_test(false, is_standard_unsigned_integral::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(false, is_standard_unsigned_integral<__int64>::value) + value_test(false, is_standard_unsigned_integral::value) + #endif + + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(true, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(true, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(true, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(true, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + #ifdef ULLONG_MAX + value_test(false, is_standard_signed_integral::value) + value_test(false, is_standard_signed_integral::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(false, is_standard_signed_integral<__int64>::value) + value_test(false, is_standard_signed_integral::value) + #endif + + value_test(false, is_standard_arithmetic::value) + value_test(false, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + value_test(true, is_standard_arithmetic::value) + #ifdef ULLONG_MAX + value_test(false, is_standard_arithmetic::value) + value_test(false, is_standard_arithmetic::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(false, is_standard_arithmetic<__int64>::value) + value_test(false, is_standard_arithmetic::value) + #endif + + value_test(false, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + value_test(true, is_standard_fundamental::value) + #ifdef ULLONG_MAX + value_test(false, is_standard_fundamental::value) + value_test(false, is_standard_fundamental::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(false, is_standard_fundamental<__int64>::value) + value_test(false, is_standard_fundamental::value) + #endif + + value_test(false, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + #ifdef ULLONG_MAX + value_test(true, is_arithmetic::value) + value_test(true, is_arithmetic::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, is_arithmetic<__int64>::value) + value_test(true, is_arithmetic::value) + #endif + + value_test(false, is_array::value) + value_test(false, is_array::value) + value_test(true, is_array::value) + value_test(true, is_array::value) + value_test(true, is_array::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::value) + value_test(false, is_pointer::value) + value_test(true, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 + value_test(false, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 + value_test(false, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 + value_test(false, is_pointer::value) + value_test(true, is_pointer::value) + value_test(true, is_pointer::value) + value_test(true, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3 + value_test(false, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3 + value_test(false, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3 + value_test(false, is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3 + value_test(false, is_pointer::value) + + value_test(false, is_reference::value) + value_test(true, is_reference::value) + value_test(true, is_reference::value) + value_test(true, is_reference::value) + + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(true, is_class::value) + value_test(true, is_class::value) + value_test(true, is_class::value) + value_test(true, is_class::value) + value_test(true, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + value_test(false, is_class::value) + + value_test(true, is_object::value) + value_test(true, is_object::value) + value_test(false, is_object::value) + value_test(false, is_object::value) + value_test(true, is_standard_scalar::value) + value_test(true, is_extension_scalar::value) + + value_test(false, is_enum::value) + value_test(true, is_enum::value) + + value_test(false, is_member_pointer::value) + value_test(false, is_member_pointer::value) + value_test(false, is_member_pointer::value) + value_test(true, is_member_pointer::value) + value_test(true, is_member_pointer::value) + value_test(true, is_member_pointer::value) + value_test(true, is_member_pointer::value) + + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(false, is_empty::value) + value_test(true, is_empty::value) + value_test(false, is_empty::value) + + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(false, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + value_test(true, has_trivial_constructor::value) + + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(false, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + value_test(true, has_trivial_copy::value) + + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(false, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + value_test(true, has_trivial_assign::value) + + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + value_test(false, has_trivial_destructor::value) + value_test(false, has_trivial_destructor::value) + value_test(true, has_trivial_destructor::value) + + value_test(true, is_POD::value) + value_test(true, is_POD::value) + // Steve: was 'true', should be 'false', via 3.9p10 + value_test(false, is_POD::value) + value_test(true, is_POD::value) + value_test(true, is_POD::value) + // Steve: was 'false', should be 'true', via 3.9p10 + value_test(true, is_POD::value) + // Steve: was 'true', should be 'false', via 3.9p10 + value_test(false, is_POD::value) + value_test(true, is_POD::value) + value_test(true, is_POD::value) + value_test(true, is_POD::value) + value_test(true, is_POD::value) + value_test(true, is_POD::value) + value_test(false, is_POD::value) + value_test(false, is_POD::value) + value_test(true, is_POD::value) + + compressed_pair cp1; + compressed_pair cp1b; + swap(cp1, cp1b); + compressed_pair cp2; + compressed_pair cp3; + compressed_pair cp4; + compressed_pair cp5; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + int i; + compressed_pair cp6(i,i); + compressed_pair cp7; + cp7.first(); + double* pd = cp7.second(); +#endif + value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) + value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) + value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) + value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) + + std::cout << std::endl << "Tests completed (" << failures << " failures)... press any key to exit"; + std::cin.get(); + return 0; +} + +// +// instanciate some compressed pairs: +template class boost::compressed_pair; +template class boost::compressed_pair; +template class boost::compressed_pair; +template class boost::compressed_pair; +template class boost::compressed_pair; +template class boost::compressed_pair; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// +// now some for which only a few specific members can be instantiated, +// first references: +template double& compressed_pair::first(); +template int& compressed_pair::second(); +template compressed_pair::compressed_pair(int&); +template compressed_pair::compressed_pair(call_traits::param_type,int&); +// +// and then arrays: +#ifndef __BORLANDC__ +template call_traits::reference compressed_pair::second(); +#endif +template call_traits::reference compressed_pair::first(); +template compressed_pair::compressed_pair(const double&); +template compressed_pair::compressed_pair(); +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// +// now check call_traits assertions by instantiating call_traits_test: +template struct call_traits_test; +template struct call_traits_test; +template struct call_traits_test; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template struct call_traits_test; +template struct call_traits_test; +// this doesn't work (yet) (JM): +template struct call_traits_test; +#endif + +