From 06adfe9658d30b448a52aa950b5125a61c0d0002 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 7 Jul 2000 16:04:40 +0000 Subject: [PATCH 1/2] 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 + + From a005f03cc2d40c8397daba55d44d85c146c3b22b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 24 Jul 2000 17:59:52 +0000 Subject: [PATCH 2/2] Fixes for various compilers from John Maddock [SVN r7629] --- algo_opt_examples.cpp | 91 +++--- call_traits_test.cpp | 254 +++++++++++++--- include/boost/detail/call_traits.hpp | 42 ++- include/boost/detail/ob_compressed_pair.hpp | 12 +- type_traits_test.cpp | 303 +++++++------------- 5 files changed, 418 insertions(+), 284 deletions(-) diff --git a/algo_opt_examples.cpp b/algo_opt_examples.cpp index 6b795e7..759a0ed 100644 --- a/algo_opt_examples.cpp +++ b/algo_opt_examples.cpp @@ -24,6 +24,13 @@ * */ +/* Release notes: + 23rd July 2000: + Added explicit failure for broken compilers that don't support these examples. + Fixed broken gcc support (broken using directive). + Reordered tests slightly. +*/ + #include #include #include @@ -39,6 +46,10 @@ using std::cout; using std::endl; using std::cin; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#error "Sorry, without template partial specialisation support there isn't anything to test here..." +#endif + namespace opt{ // @@ -221,6 +232,10 @@ struct swapper } }; +#ifdef __GNUC__ +using std::swap; +#endif + template <> struct swapper { @@ -295,6 +310,44 @@ int main() result = t.elapsed(); cout << "destroy_array(unoptimised#2): " << 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; + 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); @@ -347,43 +400,6 @@ int main() 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 @@ -404,3 +420,4 @@ int main() + diff --git a/call_traits_test.cpp b/call_traits_test.cpp index c615013..c89169f 100644 --- a/call_traits_test.cpp +++ b/call_traits_test.cpp @@ -6,6 +6,12 @@ #include #include +#ifdef __BORLANDC__ +// turn off some warnings, the way we do the tests will generate a *lot* of these +// this is a result of the tests not call_traits itself.... +#pragma option -w-8004 -w-ccc -w-rch -w-eff -w-aus +#endif + // // struct contained models a type that contains a type (for example std::pair) // arrays are contained by value, and have to be treated as a special case: @@ -28,7 +34,7 @@ struct contained contained() {} contained(param_type p) : v_(p){} // return byval: - result_type value() { return v_; } + result_type value()const { return v_; } // return by_ref: reference get() { return v_; } const_reference const_get()const { return v_; } @@ -37,6 +43,7 @@ struct contained }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct contained { @@ -53,30 +60,36 @@ struct contained std::copy(p, p+N, v_); } // return byval: - result_type value() { return v_; } + result_type value()const { return v_; } // return by_ref: reference get() { return v_; } const_reference const_get()const { return v_; } void call(param_type p){} }; +#endif template contained::value_type> wrap(const T& t) { - return contained::value_type>(t); + typedef typename boost::call_traits::value_type ct; + return contained(t); } +namespace test{ + template std::pair< - typename boost::call_traits::value_type, - typename boost::call_traits::value_type> + 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, typename boost::call_traits::value_type>(t1, t2); } +} // namespace test + using namespace std; // @@ -108,51 +121,40 @@ void checker::operator()(param_type p) cout << endl; } +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct checker { typedef typename boost::call_traits::param_type param_type; - void operator()(param_type); + void 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; + } }; - -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; -} +#endif // // check_wrap: -// verifies behaviour of "wrap": -// -template -void check_wrap(T c, U u, const V& v) +template +void check_wrap(const contained& w, const U& u) { - 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; + cout << "checking contained<" << typeid(T).name() << ">..." << endl; + assert(w.value() == u); } // @@ -176,6 +178,29 @@ struct UDT bool operator == (const UDT& v){ return v.i_ == i_; } }; +// +// define tests here +unsigned failures = 0; +unsigned test_count = 0; + +#define value_test(v, x) ++test_count;\ + if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#define type_test(v, x) ++test_count;\ + if(boost::is_same::value == false){\ + ++failures; \ + std::cout << "checking type of " << #x << "...failed" << std::endl; \ + std::cout << " expected type was " << #v << std::endl; \ + std::cout << " " << typeid(boost::is_same).name() << "::value is false" << std::endl; } +#else +#define type_test(v, x) ++test_count;\ + if(typeid(v) != typeid(x)){\ + ++failures; \ + std::cout << "checking type of " << #x << "...failed" << std::endl; \ + std::cout << " expected type was " << #v << std::endl; \ + std::cout << " " << "typeid(" #v ") != typeid(" #x ")" << std::endl; } +#endif int main() { @@ -188,6 +213,7 @@ int main() int* pi = &i; checker c3; c3(pi); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION checker c4; c4(i); checker c5; @@ -196,13 +222,147 @@ int main() int a[2] = {1,2}; checker c6; c6(a); +#endif - check_wrap(wrap(2), 2, 2); + check_wrap(wrap(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); + //check_wrap(wrap(ca), ca); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + check_wrap(wrap(a), a); + check_make_pair(test::make_pair(a, a), a, a); +#endif - return 0; + // cv-qualifiers applied to reference types should have no effect + // declare these here for later use with is_reference and remove_reference: + typedef int& r_type; + typedef const r_type cr_type; + + type_test(UDT, boost::call_traits::value_type) + type_test(UDT&, boost::call_traits::reference) + type_test(const UDT&, boost::call_traits::const_reference) + type_test(const UDT&, boost::call_traits::param_type) + type_test(int, boost::call_traits::value_type) + type_test(int&, boost::call_traits::reference) + type_test(const int&, boost::call_traits::const_reference) + type_test(const int, boost::call_traits::param_type) + type_test(int*, boost::call_traits::value_type) + type_test(int*&, boost::call_traits::reference) + type_test(int*const&, boost::call_traits::const_reference) + type_test(int*const, boost::call_traits::param_type) +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + type_test(int&, boost::call_traits::value_type) + type_test(int&, boost::call_traits::reference) + type_test(const int&, boost::call_traits::const_reference) + type_test(int&, boost::call_traits::param_type) +#if !(defined(__GNUC__) && (__GNUC__ < 3)) + type_test(int&, boost::call_traits::value_type) + type_test(int&, boost::call_traits::reference) + type_test(const int&, boost::call_traits::const_reference) + type_test(int&, boost::call_traits::param_type) +#else + std::cout << "GNU C++ cannot instantiate call_traits, skipping four tests (4 errors)" << std::endl; + failures += 4; + test_count += 4; +#endif + type_test(const int&, boost::call_traits::value_type) + type_test(const int&, boost::call_traits::reference) + type_test(const int&, boost::call_traits::const_reference) + type_test(const int&, boost::call_traits::param_type) + type_test(const int*, boost::call_traits::value_type) + type_test(int(&)[3], boost::call_traits::reference) + type_test(const int(&)[3], boost::call_traits::const_reference) + type_test(const int*const, boost::call_traits::param_type) + type_test(const int*, boost::call_traits::value_type) + type_test(const int(&)[3], boost::call_traits::reference) + type_test(const int(&)[3], boost::call_traits::const_reference) + type_test(const int*const, boost::call_traits::param_type) +#else + std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl; + failures += 20; + test_count += 20; +#endif + + std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit"; + std::cin.get(); + return failures; } + +// +// define call_traits tests to check that the assertions in the docs do actually work +// this is an instantiate only set of tests: +// +template +struct call_traits_test +{ + static void assert_construct(boost::call_traits::param_type val); +}; + +template +void call_traits_test::assert_construct(boost::call_traits::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t(val); + boost::call_traits::value_type v(t); + boost::call_traits::reference r(t); + boost::call_traits::const_reference cr(t); + boost::call_traits::param_type p(t); + boost::call_traits::value_type v2(v); + boost::call_traits::value_type v3(r); + boost::call_traits::value_type v4(p); + boost::call_traits::reference r2(v); + boost::call_traits::reference r3(r); + boost::call_traits::const_reference cr2(v); + boost::call_traits::const_reference cr3(r); + boost::call_traits::const_reference cr4(cr); + boost::call_traits::const_reference cr5(p); + boost::call_traits::param_type p2(v); + boost::call_traits::param_type p3(r); + boost::call_traits::param_type p4(p); +} +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct call_traits_test +{ + static void assert_construct(boost::call_traits::param_type val); +}; + +template +void call_traits_test::assert_construct(boost::call_traits::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t; + boost::call_traits::value_type v(t); + boost::call_traits::value_type v5(val); + boost::call_traits::reference r = t; + boost::call_traits::const_reference cr = t; + boost::call_traits::reference r2 = r; + #ifndef __BORLANDC__ + // C++ Builder buglet: + boost::call_traits::const_reference cr2 = r; + #endif + boost::call_traits::param_type p(t); + boost::call_traits::value_type v2(v); + boost::call_traits::const_reference cr3 = cr; + boost::call_traits::value_type v3(r); + boost::call_traits::value_type v4(p); + boost::call_traits::param_type p2(v); + boost::call_traits::param_type p3(r); + boost::call_traits::param_type p4(p); +} +#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +// +// now check call_traits assertions by instantiating call_traits_test: +template struct call_traits_test; +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; +template struct call_traits_test; +#endif + + diff --git a/include/boost/detail/call_traits.hpp b/include/boost/detail/call_traits.hpp index 07ed4ec..93dc7b1 100644 --- a/include/boost/detail/call_traits.hpp +++ b/include/boost/detail/call_traits.hpp @@ -6,6 +6,13 @@ // See http://www.boost.org for most recent version including documentation. +/* Release notes: + 23rd July 2000: + Fixed array specialization. (JM) + Added Borland specific fixes for reference types + (issue raised by Steve Cleary). +*/ + #ifndef BOOST_DETAIL_CALL_TRAITS_HPP #define BOOST_DETAIL_CALL_TRAITS_HPP @@ -66,6 +73,37 @@ struct call_traits typedef T& param_type; // hh removed const }; +#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x550) +// these are illegal specialisations; cv-qualifies applied to +// references have no effect according to [8.3.2p1], +// C++ Builder requires them though as it treats cv-qualified +// references as distinct types... +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 +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; +#endif + template struct call_traits { @@ -76,7 +114,7 @@ public: typedef const T* value_type; typedef array_type& reference; typedef const array_type& const_reference; - typedef const T* param_type; + typedef const T* const param_type; }; template @@ -89,7 +127,7 @@ public: typedef const T* value_type; typedef array_type& reference; typedef const array_type& const_reference; - typedef const T* param_type; + typedef const T* const param_type; }; } diff --git a/include/boost/detail/ob_compressed_pair.hpp b/include/boost/detail/ob_compressed_pair.hpp index f5f5664..ce7e064 100644 --- a/include/boost/detail/ob_compressed_pair.hpp +++ b/include/boost/detail/ob_compressed_pair.hpp @@ -6,7 +6,14 @@ // See http://www.boost.org for most recent version including documentation. // -// this version crippled for use with crippled compilers - John Maddock Jan 2000. +/* Release notes: + 23rd July 2000: + Additional comments added. (JM) + Jan 2000: + Original version: this version crippled for use with crippled compilers + - John Maddock Jan 2000. +*/ + #ifndef BOOST_OB_COMPRESSED_PAIR_HPP #define BOOST_OB_COMPRESSED_PAIR_HPP @@ -41,7 +48,8 @@ public: 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) {} + // can't define this in case T1 == T2: + // explicit compressed_pair(second_param_type y) : _first(), _second(y) {} first_reference first() { return _first; } first_const_reference first() const { return _first; } diff --git a/type_traits_test.cpp b/type_traits_test.cpp index ffea91d..b50892a 100644 --- a/type_traits_test.cpp +++ b/type_traits_test.cpp @@ -4,12 +4,18 @@ // in all copies. This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. +/* Release notes: + 23rd July 2000: + Removed all call_traits tests to call_traits_test.cpp + Removed all compressed_pair tests to compressed_pair_tests.cpp + Improved tests macros + Tidied up specialistions of type_types classes for test cases. +*/ + #include #include #include -#include -#include using namespace boost; @@ -20,73 +26,25 @@ using namespace boost; // // define tests here unsigned failures = 0; +unsigned test_count = 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); -} +#define value_test(v, x) ++test_count;\ + if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -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 +#define type_test(v, x) ++test_count;\ + if(is_same::value == false){\ + ++failures; \ + std::cout << "checking type of " << #x << "...failed" << std::endl; \ + std::cout << " expected type was " << #v << std::endl; \ + std::cout << " " << typeid(is_same).name() << "::value is false" << std::endl; } +#else +#define type_test(v, x) ++test_count;\ + if(typeid(v) != typeid(x)){\ + ++failures; \ + std::cout << "checking type of " << #x << "...failed" << std::endl; \ + std::cout << " expected type was " << #v << std::endl; \ + std::cout << " " << "typeid(" #v ") != typeid(" #x ")" << std::endl; } +#endif // Since there is no compiler support, we should specialize: // is_enum for all enumerations (is_enum implies is_POD) @@ -96,12 +54,6 @@ void call_traits_test::assert_construct(call_traits::param_type val) // 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(); @@ -116,74 +68,47 @@ struct UDT 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_UDT{ ~empty_UDT(){}; }; 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 +union empty_POD_union_UDT{}; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION namespace boost { -template <> struct is_union +template <> struct is_enum { static const bool value = true; }; -template <> struct is_empty +template <> struct is_POD +{ 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; }; +template <> struct is_POD +{ static const bool value = true; }; +template <> struct is_union +{ static const bool value = true; }; +template <> struct is_union +{ static const bool value = true; }; +template <> struct is_POD +{ static const bool value = true; }; +template <> struct is_union { static const bool value = true; }; // this type is not POD, so we have to specialize the has_* individually template <> struct has_trivial_constructor @@ -192,19 +117,48 @@ 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 } +#else +namespace boost { +template <> struct is_enum +{ enum{ value = true }; }; +template <> struct is_POD +{ enum{ value = true }; }; +// this type is not POD, so we have to specialize the has_* individually +template <> struct has_trivial_constructor +{ enum{ value = true }; }; +template <> struct has_trivial_copy +{ enum{ value = true }; }; +template <> struct has_trivial_assign +{ enum{ value = true }; }; +template <> struct is_POD +{ enum{ value = true }; }; +template <> struct is_union +{ enum{ value = true }; }; +template <> struct is_union +{ enum{ value = true }; }; +template <> struct is_POD +{ enum{ value = true }; }; +template <> struct is_union +{ enum{ value = true }; }; +// this type is not POD, so we have to specialize the has_* individually +template <> struct has_trivial_constructor +{ enum{ value = true }; }; +template <> struct has_trivial_copy +{ enum{ value = true }; }; +template <> struct has_trivial_assign +{ enum{ value = true }; }; +template <> struct is_union +{ enum{ value = true }; }; +template <> struct is_POD +{ enum{ value = true }; }; +} +#endif + // Steve: All comments that I (Steve Cleary) have added below are prefixed with // "Steve:" The failures that BCB4 has on the tests are due to Borland's // not considering cv-qual's as a part of the type -- they are considered @@ -214,11 +168,18 @@ int main() { std::cout << "Checking type operations..." << std::endl << std::endl; + // cv-qualifiers applied to reference types should have no effect + // declare these here for later use with is_reference and remove_reference: + typedef int& r_type; + typedef const r_type cr_type; + type_test(int, remove_reference::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_reference::type) + type_test(int, remove_const::type) // Steve: fails on BCB4 type_test(volatile int, remove_const::type) @@ -246,14 +207,15 @@ int main() 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(true, (is_same::value)) + value_test(false, (is_same::value)) + value_test(false, (is_same::value)) + value_test(false, (is_same::value)) + value_test(false, (is_same::value)) + value_test(false, (is_same::value)) + value_test(false, is_const::value) value_test(true, is_const::value) value_test(false, is_const::value) @@ -266,7 +228,8 @@ int main() value_test(true, is_void::value) // Steve: fails on BCB4 - value_test(false, is_void::value) + // JM: but looks as though it should according to [3.9.3p1]? + //value_test(false, is_void::value) value_test(false, is_void::value) value_test(false, is_standard_unsigned_integral::value) @@ -432,6 +395,8 @@ int main() value_test(true, is_reference::value) value_test(true, 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) @@ -477,8 +442,9 @@ int main() 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(true, is_empty::value) + value_test(true, is_empty::value) value_test(false, is_empty::value) value_test(true, has_trivial_constructor::value) @@ -558,66 +524,11 @@ int main() 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::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit"; std::cin.get(); - return 0; + return failures; } -// -// 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 +