From b38bc8d848395b484873e000ec6e3da7d72630ce Mon Sep 17 00:00:00 2001 From: nobody Date: Wed, 6 Jun 2001 19:08:52 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'tmpw2001-paper'. [SVN r10279] --- include/boost/call_traits.hpp | 23 - include/boost/compressed_pair.hpp | 23 - include/boost/detail/call_traits.hpp | 141 -- include/boost/detail/compressed_pair.hpp | 428 ------ include/boost/detail/ob_call_traits.hpp | 128 -- include/boost/detail/ob_compressed_pair.hpp | 509 ------- include/boost/operators.hpp | 764 ---------- include/boost/utility.hpp | 119 -- iterators_test.cpp | 368 ++--- operators.htm | 1513 ++++++------------- operators_test.cpp | 522 +++---- 11 files changed, 779 insertions(+), 3759 deletions(-) delete mode 100644 include/boost/call_traits.hpp delete mode 100644 include/boost/compressed_pair.hpp delete mode 100644 include/boost/detail/call_traits.hpp delete mode 100644 include/boost/detail/compressed_pair.hpp delete mode 100644 include/boost/detail/ob_call_traits.hpp delete mode 100644 include/boost/detail/ob_compressed_pair.hpp delete mode 100644 include/boost/operators.hpp delete mode 100644 include/boost/utility.hpp diff --git a/include/boost/call_traits.hpp b/include/boost/call_traits.hpp deleted file mode 100644 index 345a440..0000000 --- a/include/boost/call_traits.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// (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 deleted file mode 100644 index c55ca2d..0000000 --- a/include/boost/compressed_pair.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// (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 deleted file mode 100644 index ec161c6..0000000 --- a/include/boost/detail/call_traits.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// (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. - -// call_traits: defines typedefs for function usage -// (see libs/utility/call_traits.htm) - -/* 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 - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_COMPOSITE_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 -}; - -#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551) -// 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 -{ -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* const 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* const param_type; -}; - -} - -#endif // BOOST_DETAIL_CALL_TRAITS_HPP diff --git a/include/boost/detail/compressed_pair.hpp b/include/boost/detail/compressed_pair.hpp deleted file mode 100644 index 621a677..0000000 --- a/include/boost/detail/compressed_pair.hpp +++ /dev/null @@ -1,428 +0,0 @@ -// (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. - -// compressed_pair: pair that "compresses" empty members -// (see libs/utility/compressed_pair.htm) -// -// 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_OBJECT_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_SAME_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) - { -#ifndef __GNUC__ - using std::swap; -#endif - 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 deleted file mode 100644 index 091eea3..0000000 --- a/include/boost/detail/ob_call_traits.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// (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: -// see libs/utility/call_traits.htm -// - -/* Release notes: - 01st October 2000: - Fixed call_traits on VC6, using "poor man's partial specialisation", - using ideas taken from "Generative programming" by Krzysztof Czarnecki - & Ulrich Eisenecker. -*/ - -#ifndef BOOST_OB_CALL_TRAITS_HPP -#define BOOST_OB_CALL_TRAITS_HPP - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP -#include -#endif - -namespace boost{ - -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) -// -// use member templates to emulate -// partial specialisation: -// -namespace detail{ - -template -struct standard_call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T& param_type; -}; -template -struct simple_call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T param_type; -}; -template -struct reference_call_traits -{ - typedef T value_type; - typedef T reference; - typedef T const_reference; - typedef T param_type; -}; -template -struct call_traits_chooser -{ - template - struct rebind - { - typedef standard_call_traits type; - }; -}; -template <> -struct call_traits_chooser -{ - template - struct rebind - { - typedef simple_call_traits type; - }; -}; -template <> -struct call_traits_chooser -{ - template - struct rebind - { - typedef reference_call_traits type; - }; -}; -} // namespace detail -template -struct call_traits -{ -private: - typedef detail::call_traits_chooser<(is_pointer::value || is_arithmetic::value) && sizeof(T) <= sizeof(void*), is_reference::value> chooser; - typedef typename chooser::template rebind bound_type; - typedef typename bound_type::type call_traits_type; -public: - typedef typename call_traits_type::value_type value_type; - typedef typename call_traits_type::reference reference; - typedef typename call_traits_type::const_reference const_reference; - typedef typename call_traits_type::param_type param_type; -}; - -#else -// -// sorry call_traits is completely non-functional -// blame your broken compiler: -// - -template -struct call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T& param_type; -}; - -#endif // member templates - -} - -#endif // BOOST_OB_CALL_TRAITS_HPP diff --git a/include/boost/detail/ob_compressed_pair.hpp b/include/boost/detail/ob_compressed_pair.hpp deleted file mode 100644 index c8293ec..0000000 --- a/include/boost/detail/ob_compressed_pair.hpp +++ /dev/null @@ -1,509 +0,0 @@ -// (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. -// see libs/utility/compressed_pair.hpp -// -/* Release notes: - 20 Jan 2001: - Fixed obvious bugs (David Abrahams) - 07 Oct 2000: - Added better single argument constructor support. - 03 Oct 2000: - Added VC6 support (JM). - 23rd July 2000: - Additional comments added. (JM) - Jan 2000: - 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 - -#include -#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_SAME_TRAITS_HPP -#include -#endif -#ifndef BOOST_CALL_TRAITS_HPP -#include -#endif - -namespace boost -{ -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) -// -// use member templates to emulate -// partial specialisation. Note that due to -// problems with overload resolution with VC6 -// each of the compressed_pair versions that follow -// have one template single-argument constructor -// in place of two specific constructors: -// - -template -class compressed_pair; - -namespace detail{ - -template -struct best_conversion_traits -{ - typedef char one; - typedef char (&two)[2]; - static A a; - static one test(T1); - static two test(T2); - - enum { value = sizeof(test(a)) }; -}; - -template -struct init_one; - -template <> -struct init_one<1> -{ - template - static void init(const A& a, T1* p1, T2*) - { - *p1 = a; - } -}; - -template <> -struct init_one<2> -{ - template - static void init(const A& a, T1*, T2* p2) - { - *p2 = a; - } -}; - - -// T1 != T2, both non-empty -template -class compressed_pair_0 -{ -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_0() : _first(), _second() {} - compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} - template - explicit compressed_pair_0(const A& val) - { - init_one::value>::init(val, &_first, &_second); - } - compressed_pair_0(const ::boost::compressed_pair& x) - : _first(x.first()), _second(x.second()) {} - -#if 0 - compressed_pair_0& operator=(const compressed_pair_0& x) { - cout << "assigning compressed pair 0" << endl; - _first = x._first; - _second = x._second; - cout << "finished assigning compressed pair 0" << endl; - return *this; - } -#endif - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair_0& y) - { - using std::swap; - swap(_first, y._first); - swap(_second, y._second); - } -}; - -// T1 != T2, T2 empty -template -class compressed_pair_1 : T2 -{ -private: - T1 _first; -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_1() : T2(), _first() {} - compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} - - template - explicit compressed_pair_1(const A& val) - { - init_one::value>::init(val, &_first, static_cast(this)); - } - - compressed_pair_1(const ::boost::compressed_pair& x) - : T2(x.second()), _first(x.first()) {} - -#ifdef BOOST_MSVC - // Total weirdness. If the assignment to _first is moved after - // the call to the inherited operator=, then this breaks graph/test/graph.cpp - // by way of iterator_adaptor. - compressed_pair_1& operator=(const compressed_pair_1& x) { - _first = x._first; - T2::operator=(x); - return *this; - } -#endif - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return *this; } - second_const_reference second() const { return *this; } - - void swap(compressed_pair_1& y) - { - // no need to swap empty base class: - using std::swap; - swap(_first, y._first); - } -}; - -// T1 != T2, T1 empty -template -class compressed_pair_2 : T1 -{ -private: - 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_2() : T1(), _second() {} - compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} - template - explicit compressed_pair_2(const A& val) - { - init_one::value>::init(val, static_cast(this), &_second); - } - compressed_pair_2(const ::boost::compressed_pair& x) - : T1(x.first()), _second(x.second()) {} - -#if 0 - compressed_pair_2& operator=(const compressed_pair_2& x) { - cout << "assigning compressed pair 2" << endl; - T1::operator=(x); - _second = x._second; - cout << "finished assigning compressed pair 2" << endl; - return *this; - } -#endif - first_reference first() { return *this; } - first_const_reference first() const { return *this; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair_2& y) - { - // no need to swap empty base class: - using std::swap; - swap(_second, y._second); - } -}; - -// T1 != T2, both empty -template -class compressed_pair_3 : T1, 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_3() : T1(), T2() {} - compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} - template - explicit compressed_pair_3(const A& val) - { - init_one::value>::init(val, static_cast(this), static_cast(this)); - } - compressed_pair_3(const ::boost::compressed_pair& x) - : T1(x.first()), T2(x.second()) {} - - first_reference first() { return *this; } - first_const_reference first() const { return *this; } - - second_reference second() { return *this; } - second_const_reference second() const { return *this; } - - void swap(compressed_pair_3& y) - { - // no need to swap empty base classes: - } -}; - -// T1 == T2, and empty -template -class compressed_pair_4 : 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_4() : T1() {} - compressed_pair_4(first_param_type x, second_param_type) : T1(x) {} - // only one single argument constructor since T1 == T2 - explicit compressed_pair_4(first_param_type x) : T1(x) {} - compressed_pair_4(const ::boost::compressed_pair& x) - : T1(x.first()){} - - 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_4& y) - { - // no need to swap empty base classes: - } -}; - -// T1 == T2, not empty -template -class compressed_pair_5 -{ -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_5() : _first(), _second() {} - compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} - // only one single argument constructor since T1 == T2 - explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} - compressed_pair_5(const ::boost::compressed_pair& c) - : _first(c.first()), _second(c.second()) {} - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair_5& y) - { - using std::swap; - swap(_first, y._first); - swap(_second, y._second); - } -}; - -template -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_0 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_1 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_2 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_3 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_4 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_5 type; - }; -}; - -template -struct compressed_pair_traits -{ -private: - typedef compressed_pair_chooser::value, is_empty::value, is_same::value> chooser; - typedef typename chooser::template rebind bound_type; -public: - typedef typename bound_type::type type; -}; - -} // namespace detail - -template -class compressed_pair : public detail::compressed_pair_traits::type -{ -private: - typedef typename detail::compressed_pair_traits::type base_type; -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_type() {} - compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} - template - explicit compressed_pair(const A& x) : base_type(x){} - - first_reference first() { return base_type::first(); } - first_const_reference first() const { return base_type::first(); } - - second_reference second() { return base_type::second(); } - second_const_reference second() const { return base_type::second(); } -}; - -template -inline void swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -#else -// no partial specialisation, no member templates: - -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() {} - // 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; } - - 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); -} - -#endif - -} // boost - -#endif // BOOST_OB_COMPRESSED_PAIR_HPP - - - diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp deleted file mode 100644 index 14d4c31..0000000 --- a/include/boost/operators.hpp +++ /dev/null @@ -1,764 +0,0 @@ -// Boost operators.hpp header file ----------------------------------------// - -// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001. -// Permission to copy, use, modify, sell and distribute this software is -// granted provided this copyright notice appears in all copies. This -// software is provided "as is" without express or implied warranty, and -// with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 29 May 01 Added operator classes for << and >>. Added input and output -// iterator helper classes. Added classes to connect equality and -// relational operators. Added classes for groups of related -// operators. Reimplemented example operator and iterator helper -// classes in terms of the new groups. (Daryle Walker, with help -// from Alexy Gurtovoy) -// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly -// supplied arguments from actually being used (Dave Abrahams) -// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and -// refactoring of compiler workarounds, additional documentation -// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from -// Dave Abrahams) -// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and -// Jeremy Siek (Dave Abrahams) -// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 -// (Mark Rodgers) -// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) -// 10 Jun 00 Support for the base class chaining technique was added -// (Aleksey Gurtovoy). See documentation and the comments below -// for the details. -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) -// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary -// specializations of dividable, subtractable, modable (Ed Brey) -// 17 Nov 99 Add comments (Beman Dawes) -// Remove unnecessary specialization of operators<> (Ed Brey) -// 15 Nov 99 Fix less_than_comparable 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 - -#if defined(BOOST_MSVC) -# pragma warning( disable : 4284 ) // complaint about return type of -#endif // operator-> not begin a UDT - -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); - } -}; - -// More operator classes (contributed by Daryle Walker) --------------------// - -template -struct left_shiftable2 : B -{ - friend T operator<<(T x, const U& y) { return x <<= y; } -}; - -template -struct left_shiftable1 : B -{ - friend T operator<<(T x, const T& y) { return x <<= y; } -}; - -template -struct right_shiftable2 : B -{ - friend T operator>>(T x, const U& y) { return x >>= y; } -}; - -template -struct right_shiftable1 : B -{ - friend T operator>>(T x, const T& y) { return x >>= y; } -}; - -template -struct equivalent2 : B -{ - friend bool operator==(const T& x, const U& y) - { - return !(x < y) && !(x > y); - } -}; - -template -struct equivalent1 : B -{ - friend bool operator==(const T&x, const T&y) - { - return !(x < y) && !(y < x); - } -}; - -template -struct partially_ordered2 : B -{ - friend bool operator<=(const T& x, const U& y) - { return (x < y) || (x == y); } - friend bool operator>=(const T& x, const U& y) - { return (x > y) || (x == y); } - friend bool operator>(const U& x, const T& y) - { return y < x; } - friend bool operator<(const U& x, const T& y) - { return y > x; } - friend bool operator<=(const U& x, const T& y) - { return (y > x) || (y == x); } - friend bool operator>=(const U& x, const T& y) - { return (y < x) || (y == x); } -}; - -template -struct partially_ordered1 : B -{ - friend bool operator>(const T& x, const T& y) - { return y < x; } - friend bool operator<=(const T& x, const T& y) - { return (x < y) || (x == y); } - friend bool operator>=(const T& x, const T& y) - { return (y < x) || (x == y); } -}; - -// Combined operator classes (contributed by Daryle Walker) ----------------// - -template -struct totally_ordered2 - : less_than_comparable2 > {}; - -template -struct totally_ordered1 - : less_than_comparable1 > {}; - -template -struct additive2 - : addable2 > {}; - -template -struct additive1 - : addable1 > {}; - -template -struct multiplicative2 - : multipliable2 > {}; - -template -struct multiplicative1 - : multipliable1 > {}; - -template -struct integer_multiplicative2 - : multiplicative2 > {}; - -template -struct integer_multiplicative1 - : multiplicative1 > {}; - -template -struct arithmetic2 - : additive2 > {}; - -template -struct arithmetic1 - : additive1 > {}; - -template -struct integer_arithmetic2 - : additive2 > {}; - -template -struct integer_arithmetic1 - : additive1 > {}; - -template -struct bitwise2 - : xorable2 > > {}; - -template -struct bitwise1 - : xorable1 > > {}; - -template -struct unit_steppable - : incrementable > {}; - -template -struct shiftable2 - : left_shiftable2 > {}; - -template -struct shiftable1 - : left_shiftable1 > {}; - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE -} // namespace boost -#endif // BOOST_NO_OPERATORS_IN_NAMESPACE - - -// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 - -// -// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an -// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used -// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for -// two-argument forms. Note that these macros expect to be invoked from within -// boost. - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - - // The template is already in boost so we have nothing to do. -# define BOOST_IMPORT_TEMPLATE3(template_name) -# define BOOST_IMPORT_TEMPLATE2(template_name) -# define BOOST_IMPORT_TEMPLATE1(template_name) - -#else // BOOST_NO_OPERATORS_IN_NAMESPACE - -# ifndef BOOST_NO_USING_TEMPLATE - - // Bring the names in with a using-declaration - // to avoid stressing the compiler. -# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name; -# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; -# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; - -# else - - // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration - // from working, we are forced to use inheritance for that compiler. -# define BOOST_IMPORT_TEMPLATE3(template_name) \ - template \ - struct template_name : ::template_name {}; - -# define BOOST_IMPORT_TEMPLATE2(template_name) \ - template \ - struct template_name : ::template_name {}; - -# define BOOST_IMPORT_TEMPLATE1(template_name) \ - template \ - struct template_name : ::template_name {}; - -# endif // BOOST_NO_USING_TEMPLATE - -#endif // BOOST_NO_OPERATORS_IN_NAMESPACE - -// -// Here's where we put it all together, defining the xxxx forms of the templates -// in namespace boost. We also define specializations of is_chained_base<> for -// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as -// neccessary. -// -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -// is_chained_base<> - a traits class used to distinguish whether an operator -// template argument is being used for base class chaining, or is specifying a -// 2nd argument type. - -namespace boost { -// A type parameter is used instead of a plain bool because Borland's compiler -// didn't cope well with the more obvious non-type template parameter. -namespace detail { - struct true_t {}; - struct false_t {}; -} // namespace detail - -// Unspecialized version assumes that most types are not being used for base -// class chaining. We specialize for the operator templates defined in this -// library. -template struct is_chained_base { - typedef ::boost::detail::false_t value; -}; - -} // namespace boost - -// Import a 3-type-argument operator template into boost (if neccessary) and -// provide a specialization of 'is_chained_base<>' for it. -# define BOOST_OPERATOR_TEMPLATE3(template_name3) \ - BOOST_IMPORT_TEMPLATE3(template_name3) \ - template \ - struct is_chained_base< ::boost::template_name3 > { \ - typedef ::boost::detail::true_t value; \ - }; - -// Import a 2-type-argument operator template into boost (if neccessary) and -// provide a specialization of 'is_chained_base<>' for it. -# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ - BOOST_IMPORT_TEMPLATE2(template_name2) \ - template \ - 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_TEMPLATE3(template_name3) \ - BOOST_IMPORT_TEMPLATE3(template_name3) -# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ - BOOST_IMPORT_TEMPLATE2(template_name2) -# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ - BOOST_IMPORT_TEMPLATE1(template_name1) - - // In this case we can only assume that template_name<> is equivalent to the - // more commonly needed template_name1<> form. -# define BOOST_OPERATOR_TEMPLATE(template_name) \ - template \ - 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) -BOOST_OPERATOR_TEMPLATE3(indexable) - -BOOST_OPERATOR_TEMPLATE(left_shiftable) -BOOST_OPERATOR_TEMPLATE(right_shiftable) -BOOST_OPERATOR_TEMPLATE(equivalent) -BOOST_OPERATOR_TEMPLATE(partially_ordered) - -BOOST_OPERATOR_TEMPLATE(totally_ordered) -BOOST_OPERATOR_TEMPLATE(additive) -BOOST_OPERATOR_TEMPLATE(multiplicative) -BOOST_OPERATOR_TEMPLATE(integer_multiplicative) -BOOST_OPERATOR_TEMPLATE(arithmetic) -BOOST_OPERATOR_TEMPLATE(integer_arithmetic) -BOOST_OPERATOR_TEMPLATE(bitwise) -BOOST_OPERATOR_TEMPLATE1(unit_steppable) -BOOST_OPERATOR_TEMPLATE(shiftable) - -#undef BOOST_OPERATOR_TEMPLATE -#undef BOOST_OPERATOR_TEMPLATE3 -#undef BOOST_OPERATOR_TEMPLATE2 -#undef BOOST_OPERATOR_TEMPLATE1 -#undef BOOST_IMPORT_TEMPLATE1 -#undef BOOST_IMPORT_TEMPLATE2 -#undef BOOST_IMPORT_TEMPLATE3 - -// The following 'operators' classes can only be used portably if the derived class -// declares ALL of the required member operators. -template -struct operators2 - : totally_ordered2 > > {}; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct operators : operators2 {}; - -template struct operators -#else -template struct operators -#endif - : totally_ordered > > > {}; - -// Iterator helper classes (contributed by Jeremy Siek) -------------------// -// (Input and output iterator helpers contributed by Daryle Walker) -------// -// (Changed to use combined operator classes by Daryle Walker) ------------// -template -struct input_iterator_helper - : equality_comparable1 > > > {}; - -template -struct output_iterator_helper - : incrementable > {}; - -template -struct forward_iterator_helper - : equality_comparable1 > > > {}; - -template -struct bidirectional_iterator_helper - : equality_comparable1 > > > {}; - -template -struct random_access_iterator_helper - : totally_ordered1 > > > > > -{ - friend D requires_difference_operator(const T& x, const T& y) { - return x - y; - } -}; // random_access_iterator_helper - -} // namespace boost - -#if defined(__sgi) && !defined(__GNUC__) -#pragma reset woff 1234 -#endif - -#endif // BOOST_OPERATORS_HPP diff --git a/include/boost/utility.hpp b/include/boost/utility.hpp deleted file mode 100644 index f1a6389..0000000 --- a/include/boost/utility.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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 -// 21 May 01 checked_delete() and checked_array_delete() added (Beman Dawes, -// suggested by Dave Abrahams, generalizing idea from Vladimir Prus) -// 21 May 01 made next() and prior() inline (Beman Dawes) -// 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 // broken compiler workarounds -#include -#include // for size_t -#include // for std::pair - -namespace boost -{ -// checked_delete() and checked_array_delete() -----------------------------// - - // verify that types are complete for increased safety - - template< typename T > - inline void checked_delete(T * x) - { - BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point - // of instantiation - delete x; - } - - template< typename T > - inline void checked_array_delete(T * x) - { - BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point - // of instantiation - delete [] x; - } - -// 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 - inline T next(T x) { return ++x; } - - template - inline 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 - -// class tied -------------------------------------------------------// - - // A helper for conveniently assigning the two values from a pair - // into separate variables. The idea for this comes from Jaakko J„rvi's - // Binder/Lambda Library. - - // Constributed by Jeremy Siek - - template - class tied { - public: - inline tied(A& a, B& b) : _a(a), _b(b) { } - template - inline tied& operator=(const std::pair& p) { - _a = p.first; - _b = p.second; - return *this; - } - protected: - A& _a; - B& _b; - }; - - template - inline tied tie(A& a, B& b) { return tied(a, b); } - -} // namespace boost - -#endif // BOOST_UTILITY_HPP - diff --git a/iterators_test.cpp b/iterators_test.cpp index 852bf09..e264aff 100644 --- a/iterators_test.cpp +++ b/iterators_test.cpp @@ -9,25 +9,16 @@ // See http://www.boost.org for most recent version including documentation. // Revision History -// 29 May 01 Factored implementation, added comparison tests, use Test Tools -// library (Daryle Walker) // 12 Dec 99 Initial version with iterator operators (Jeremy Siek) -#define BOOST_INCLUDE_MAIN -#include // for main +#include +#include +using namespace std; -#include // for BOOST_STATIC_CONSTANT -#include // for boost::exit_success -#include // for boost::random_access_iterator_helper - -#include // for std::ptrdiff_t, std::size_t -#include // for std::strcmp -#include // for std::cout (std::endl, ends, and flush indirectly) -#include // for std::string -#include // for std::ostrstream +#include +using namespace boost; -// Iterator test class template struct test_iter : public boost::random_access_iterator_helper< @@ -38,7 +29,7 @@ struct test_iter typedef std::ptrdiff_t Distance; public: - explicit test_iter(T* i =0) : _i(i) { } + 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; } @@ -52,280 +43,127 @@ public: return x._i - y._i; } protected: - P _i; + T* _i; }; -// Iterator operator testing classes -class test_opr_base -{ -protected: - // Test data and types - BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u ); - BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u ); - typedef std::string fruit_array_type[ fruit_length ]; - typedef char scratch_array_type[ scratch_length ]; - - static fruit_array_type fruit; - static scratch_array_type scratch; - -}; // test_opr_base - -template -class test_opr - : public test_opr_base -{ - typedef test_opr self_type; - -public: - // Types - typedef T value_type; - typedef R reference; - typedef P pointer; - - typedef test_iter iter_type; - - // Test controller - static void master_test( char const name[] ); - -private: - // Test data - static iter_type const fruit_begin, fruit_end; - - // Test parts - static void post_increment_test(); - static void post_decrement_test(); - static void indirect_referral_test(); - static void offset_addition_test(); - static void reverse_offset_addition_test(); - static void offset_subtraction_test(); - static void comparison_test(); - static void indexing_test(); - -}; // test_opr - - -// Class-static data definitions -typename test_opr_base::fruit_array_type - test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" }; - -typename test_opr_base::scratch_array_type - test_opr_base::scratch = ""; - -template -typename test_opr::iter_type const - test_opr::fruit_begin( fruit ); - -template -typename test_opr::iter_type const - test_opr::fruit_end( fruit + fruit_length ); - - -// Main testing function int -test_main( int , char * [] ) +main() { - using std::string; + string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" }; + { + test_iter i = array, + ie = array + sizeof(array)/sizeof(string); - typedef test_opr test1_type; - typedef test_opr test2_type; + // Tests for all of the operators added by random_access_iterator_helper - test1_type::master_test( "non-const string" ); - test2_type::master_test( "const string" ); + // test i++ + while (i != ie) + cout << *i++ << " "; + cout << endl; + i = array; - return boost::exit_success; -} - -// Tests for all of the operators added by random_access_iterator_helper -template -void -test_opr::master_test -( - char const name[] -) -{ - std::cout << "Doing test run for " << name << '.' << std::endl; - - post_increment_test(); - post_decrement_test(); - indirect_referral_test(); - offset_addition_test(); - reverse_offset_addition_test(); - offset_subtraction_test(); - comparison_test(); - indexing_test(); -} - -// Test post-increment -template -void -test_opr::post_increment_test -( -) -{ - std::cout << "\tDoing post-increment test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; ) - { - oss << *i++ << ' '; + // test i-- + while (ie != i) { + ie--; + cout << *ie << " "; } + cout << endl; + ie = array + sizeof(array)/sizeof(string); - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ") - == 0 ); -} - -// Test post-decrement -template -void -test_opr::post_decrement_test -( -) -{ - std::cout << "\tDoing post-decrement test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_end ; i != fruit_begin ; ) - { - i--; - oss << *i << ' '; + // test i->m + while (i != ie) { + cout << i->size() << " "; + ++i; } + cout << endl; + i = array; - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ") - == 0 ); -} - -// Test indirect structure referral -template -void -test_opr::indirect_referral_test -( -) -{ - std::cout << "\tDoing indirect reference test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) - { - oss << i->size() << ' '; + // test i + n + while (i < ie) { + cout << *i << " "; + i = i + 2; } + cout << endl; + i = array; - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 ); -} - -// Test offset addition -template -void -test_opr::offset_addition_test -( -) -{ - std::cout << "\tDoing offset addition test." << std::endl; - - std::ptrdiff_t const two = 2; - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) - { - oss << *i << ' '; + // test n + i + while (i < ie) { + cout << *i << " "; + i = ptrdiff_t(2) + i; } + cout << endl; + i = array; - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 ); -} - -// Test offset addition, in reverse order -template -void -test_opr::reverse_offset_addition_test -( -) -{ - std::cout << "\tDoing reverse offset addition test." << std::endl; - - std::ptrdiff_t const two = 2; - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) - { - oss << *i << ' '; + // test i - n + while (ie > i) { + ie = ie - 2; + cout << *ie << " "; } + cout << endl; + ie = array + sizeof(array)/sizeof(string); - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 ); -} + // 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); -// Test offset subtraction -template -void -test_opr::offset_subtraction_test -( -) -{ - std::cout << "\tDoing offset subtraction test." << std::endl; + // Tests for all of the operators added by random_access_iterator_helper - std::ptrdiff_t const two = 2; - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_end ; fruit_begin < i ; ) - { - i = i - two; - if ( (fruit_begin < i) || (fruit_begin == i) ) - { - oss << *i << ' '; - } + // 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); - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 ); -} - -// Test comparisons -template -void -test_opr::comparison_test -( -) -{ - using std::cout; - using std::ptrdiff_t; - - cout << "\tDoing comparison tests.\n\t\tPass:"; - - for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) - { - ptrdiff_t const i_offset = i - fruit_begin; - - cout << ' ' << *i << std::flush; - for ( iter_type j = fruit_begin ; j != fruit_end ; ++j ) - { - ptrdiff_t const j_offset = j - fruit_begin; - - BOOST_TEST( (i != j) == (i_offset != j_offset) ); - BOOST_TEST( (i > j) == (i_offset > j_offset) ); - BOOST_TEST( (i <= j) == (i_offset <= j_offset) ); - BOOST_TEST( (i >= j) == (i_offset >= j_offset) ); - } + // test i->m + while (i != ie) { + cout << i->size() << " "; + ++i; } - cout << std::endl; -} + cout << endl; + i = array; -// Test indexing -template -void -test_opr::indexing_test -( -) -{ - std::cout << "\tDoing indexing test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( std::size_t k = 0u ; k < fruit_length ; ++k ) - { - oss << fruit_begin[ k ] << ' '; + // test i + n + while (i < ie) { + cout << *i << " "; + i = i + 2; } + cout << endl; + i = array; - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ") - == 0 ); + // 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/operators.htm b/operators.htm index 8f78f51..3e9e7bc 100644 --- a/operators.htm +++ b/operators.htm @@ -1,81 +1,28 @@ - - -Header <boost/operators.hpp> Documentation + + + +Header boost/operators.hpp Documentation - - -

c++boost.gif (8819 bytes)Header <boost/operators.hpp>

- -

The header <boost/operators.hpp> -supplies several sets of class templates (in namespace -boost). These templates define operators at namespace -scope in terms of a minimal number of fundamental operators -provided by the class.

- -

Contents

+ +

c++boost.gif (8819 bytes)Header +boost/operators.hpp

+

Header boost/operators.hpp supplies +(in namespace boost) several sets of templates:

- -

Rationale

- -

Overloaded operators for class types typically occur in groups. If -you can write x + y, you probably also want to be able to -write x += y. If you can write x < y, you -also want x > y, x >= y, and x <= y. -Moreover, unless your class has really surprising behavior, some of -these related operators can be defined in terms of others (e.g. x ->= y <=> !(x < y)). Replicating this boilerplate for -multiple classes is both tedious and error-prone. The boost/operators.hpp -templates help by generating operators for you at namespace scope based -on other operators you've defined in your class.

- +

These templates define many global operators in terms of a minimal number of +fundamental operators.

+

Arithmetic Operators

If, for example, you declare a class like this:

-
-
class MyInt
-    : boost::operators<MyInt>
+  
class MyInt : boost::operators<MyInt>
 {
     bool operator<(const MyInt& x) const; 
     bool operator==(const MyInt& x) const;
@@ -91,172 +38,279 @@ on other operators you've defined in your class.

MyInt& operator--(); };
- -

then the operators<> -template adds more than a dozen additional operators, such as -operator>, <=, >=, and -(binary) +. Two-argument forms of -the templates are also provided to allow interaction with other types.

- -

Summary of Template Semantics

- -
    -
  1. Each operator template completes the concept(s) it describes by - defining overloaded operators for its target class.
  2. - -
  3. The name of an operator class template indicates the concept that its target class will - model.
  4. - -
  5. Usually, the target class uses an instantation of the operator class - template as a base class. Some operator templates support an - alternate method.
  6. - -
  7. The concept can be compound, i.e. it may represent a - common combination of other, simpler concepts.
  8. - -
  9. Most operator templates require their target class to support - operations related to the operators supplied by the template. In - accordance with widely accepted coding style - recommendations, the target class is often required to - supply the assignment counterpart operator of the concept's - "main operator." For example, the addable - template requires operator+=(T const&) and - in turn supplies operator+(T const&, T - const&).
  10. -
- -

Use of concepts

- -

The discussed concepts are not necessarily the standard library's -concepts (CopyConstructible, etc.), although some of them could -be; they are what we call concepts with a small 'c'. In -particular, they are different from the former ones in that they do -not describe precise semantics of the operators they require to -be defined, except the requirements that (a) the semantics of the -operators grouped in one concept should be consistent (e.g. -effects of evaluating of a += b and a = a + b -expressions should be the same), and (b) that the return types of the -operators should follow semantics of return types of corresponding -operators for built-in types (e.g. operator< -should return a type convertible to bool, and -T::operator-= should return type convertible to -T). Such "loose" requirements make operators -library applicable to broader set of target classes from different -domains, i.e. eventually more useful.

- -

Usage

- -

Two-Argument Template Forms

- -

The arguments to a binary operator commonly have identical types, but -it is not unusual to want to define operators which combine different -types. For example, one might want to multiply a -mathematical vector by a scalar. The two-argument template forms of the -arithmetic operator templates are supplied for this purpose. When -applying the two-argument form of a template, the desired return type of -the operators typically determines which of the two types in question -should be derived from the operator template. For example, if the -result of T + U is of type T, then -T (not U) should be derived from addable<T, U>. The comparison -templates (less_than_comparable<T, -U>, equality_comparable<T, -U>, equivalent<T, U>, -and partially_ordered<T, U>) -are exceptions to this guideline, since the return type of the operators -they define is bool.

- -

On compilers which do not support partial specialization, the -two-argument forms must be specified by using the names shown below with -the trailing '2'. The single-argument forms with the -trailing '1' are provided for symmetry and to enable -certain applications of the base class chaining -technique.

- -

Base Class Chaining and Object Size

- -

Every operator class template, except the arithmetic -examples and the iterator helpers, has an -additional, but optional, template type parameter B. This -parameter will be a publicly-derived base class of the instantiated template. -This means it must be a class type. It can be used to avoid the bloating of -object sizes that is commonly associated with multiple-inheritance from -several empty base classes (see the note for users of -older versions for more details). To provide support for a group of -operators, use the B parameter to chain operator templates -into a single-base class hierarchy, demostrated in the usage -example. The technique is also used by the composite operator templates -to group operator definitions. If a chain becomes too long for the compiler to -support, try replacing some of the operator templates with a single grouped -operator template that chains the old templates together; the length limit only -applies to the number of templates directly in the chain, not those hidden in -group templates.

- -

Caveat: to chain to a base class which is -not a Boost operator template when using the single-argument form of a Boost operator template, -you must specify the operator template with the trailing -'1' in its name. Otherwise the library will assume you -mean to define a binary operation combining the class you intend to use -as a base class and the class you're deriving.

- -

Separate, Explicit Instantiation

- -

On some compilers (e.g. Borland, GCC) even single-inheritance seems -to cause an increase in object size in some cases. If you are not defining -a class template, you may get better object-size performance by avoiding -derivation altogether, and instead explicitly instantiating the operator -template as follows:

- -
+

then the operators<> template adds more than a dozen +additional operators, such as operator>, <=, >=, and +.  Two-argument +forms of the templates are also provided to allow interaction with other +types.

+

Dave Abrahams +started the library and contributed the arithmetic operators in boost/operators.hpp.
+Jeremy Siek +contributed the dereference operators and iterator +helpers in boost/operators.hpp.
+Aleksey Gurtovoy +contributed the code to support base class chaining +while remaining backward-compatible with old versions of the library.
+Beman Dawes +contributed test_operators.cpp.

+

Rationale

+

Overloaded operators for class types typically occur in groups. If you can +write x + y, you probably also want to be able to write x += +y. If you can write x < y, you also want x > y, +x >= y, and x <= y. Moreover, unless your class has +really surprising behavior, some of these related operators can be defined in +terms of others (e.g. x >= y <=> !(x < y)). +Replicating this boilerplate for multiple classes is both tedious and +error-prone. The boost/operators.hpp +templates help by generating operators for you at namespace scope based on other +operators you've defined in your class.

+ +

Two-Argument Template Forms

+
+

The arguments to a binary operator commonly have identical types, but it is +not unusual to want to define operators which combine different types. For example, +one might want to multiply a mathematical vector by a scalar. The two-argument +template forms of the arithmetic operator templates are supplied for this +purpose. When applying the two-argument form of a template, the desired return +type of the operators typically determines which of the two types in question +should be derived from the operator template. For example, if the result of T + U +is of type T, then T (not U) should be +derived from addable<T,U>. The comparison templates less_than_comparable<> +and equality_comparable<> +are exceptions to this guideline, since the return type of the operators they +define is bool.

+

On compilers which do not support partial specialization, the two-argument +forms must be specified by using the names shown below with the trailing '2'. +The single-argument forms with the trailing '1' are provided for +symmetry and to enable certain applications of the base +class chaining technique.

+

Arithmetic operators table

+

The requirements for the types used to instantiate operator templates are +specified in terms of expressions which must be valid and by the return type of +the expression. In the following table t and t1 are +values of type T, and u is a value of type U. +Every template in the library other than operators<> +and operators2<> has an additional +optional template parameter B which is not shown in the table, but +is explained below

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
templatetemplate will supplyRequirements
operators<T>All the other <T> templates in this table.All the <T> requirements in this table.
operators<T,U>
+ operators2<T,U>
All the other <T,U> templates in this table, plus incrementable<T> + and decrementable<T>.All the <T,U> requirements in this table*, + plus incrementable<T> and decrementable<T>.
less_than_comparable<T>
+ less_than_comparable1<T>
bool operator>(const T&, const T&) 
+ bool operator<=(const T&, const T&)
+ bool operator>=(const T&, const T&)
t<t1. Return convertible to bool
less_than_comparable<T,U>
+ less_than_comparable2<T,U>
bool operator<=(const T&, const U&)
+ bool operator>=(const T&, const U&)
+ bool operator>(const U&, const T&) 
+ bool operator<(const U&, const T&) 
+ bool operator<=(const U&, const T&)
+ bool operator>=(const U&, const T&)
t<u. Return convertible to bool
+ t>u. Return convertible to bool
equality_comparable<T>
+ equality_comparable1<T>
bool operator!=(const T&, const T&)t==t1. Return convertible to bool
equality_comparable<T,U>
+ equality_comparable2<T,U>
friend bool operator==(const U&, const T&)
+ friend bool operator!=(const U&, const T&)
+ friend bool operator!=( const T&, const U&)
t==u. Return convertible to bool
addable<T>
+ addable1<T>
T operator+(T, const T&)t+=t1. Return convertible to T
addable<T,U>
+ addable2<T,U>
T operator+(T, const U&)
+ T operator+(const U&, T )
t+=u. Return convertible to T
subtractable<T>
+ subtractable1<T>
T operator-(T, const T&)t-=t1. Return convertible to T
subtractable<T,U>
+ subtractable2<T,U>
T operator-(T, const U&)t-=u. Return convertible to T
multipliable<T>
+ multipliable1<T>
T operator*(T, const T&)t*=t1. Return convertible to T
multipliable<T,U>
+ multipliable2<T,U>
T operator*(T, const U&)
+ T operator*(const U&, T )
t*=u. Return convertible to T
dividable<T>
+ dividable1<T>
T operator/(T, const T&)t/=t1. Return convertible to T
dividable<T,U>
+ dividable2<T,U>
T operator/(T, const U&)t/=u. Return convertible to T
modable<T>
+ modable1<T>
T operator%(T, const T&)t%=t1. Return convertible to T
modable<T,U>
+ modable2<T,U>
T operator%(T, const U&)t%=u. Return convertible to T
orable<T>
+ orable1<T>
T operator|(T, const T&)t|=t1. Return convertible to T
orable<T,U>
+ orable2<T,U>
T operator|(T, const U&)
+ T operator|(const U&, T )
t|=u. Return convertible to T
andable<T>
+ andable1<T>
T operator&(T, const T&)t&=t1. Return convertible to T
andable<T,U>
+ andable2<T,U>
T operator&(T, const U&)
+ T operator&(const U&, T)
t&=u. Return convertible to T
xorable<T>
+ xorable1<T>
T operator^(T, const T&)t^=t1. Return convertible to T
xorable<T,U>
+ xorable2<T,U>
T operator^(T, const U&)
+ T operator^(const U&, T )
t^=u. Return convertible to T
incrementable<T>
+ incrementable1<T>
T operator++(T& x, int)T temp(x); ++x; return temp;
+ Return convertible to T
decrementable<T>
+ decrementable1<T>
T operator--(T& x, int)T temp(x); --x; return temp;
+ Return convertible to T
+
+Portability Note: many compilers (e.g. MSVC6.3, +GCC 2.95.2) will not enforce the requirements in this table unless the +operations which depend on them are actually used. This is not +standard-conforming behavior. If you are trying to write portable code it is +important not to rely on this bug. In particular, it would be convenient to +derive all your classes which need binary operators from the operators<> +and operators2<> templates, +regardless of whether they implement all the requirements in the table. Even if +this works with your compiler today, it may not work tomorrow. +

Base Class Chaining and Object Size

+

Every template listed in the table except operators<> +and operators2<> has an additional +optional template parameter B.  If supplied, B +must be a class type; the resulting class will be publicly derived from B. This +can be used to avoid the object size bloat commonly associated with multiple +empty base classes (see the note for users of older +versions below for more details). To provide support for several groups of +operators, use the additional parameter to chain operator templates into a +single-base class hierarchy, as in the following example.

+

Caveat: to chain to a base class which is not a boost operator +template when using the single-argument form of a +boost operator template, you must specify the operator template with the +trailing '1' in its name. Otherwise the library will assume you +mean to define a binary operation combining the class you intend to use as a +base class and the class you're deriving.

+

Borland users: even single-inheritance seems to cause an increase in +object size in some cases. If you are not defining a template, you may get +better object-size performance by avoiding derivation altogether, and instead +explicitly instantiating the operator template as follows: +

     class myclass // lose the inheritance...
     {
         //...
     };
-
     // explicitly instantiate the operators I need.
-    template struct less_than_comparable<myclass>;
-    template struct equality_comparable<myclass>;
-    template struct incrementable<myclass>;
-    template struct decrementable<myclass>;
-    template struct addable<myclass,long>;
-    template struct subtractable<myclass,long>;
-
- -

Note that some operator templates cannot use this workaround and must -be a base class of their primary operand type. Those templates define -operators which must be member functions, and the workaround needs the -operators to be independent friend functions. The relevant templates are:

- -
- -

Requirement Portability

- -

Many compilers (e.g. MSVC 6.3, GCC 2.95.2) will not enforce -the requirements in the operator template tables unless the operations -which depend on them are actually used. This is not standard-conforming -behavior. In particular, although it would be convenient to derive all -your classes which need binary operators from the -operators<> -and operators2<> -templates, regardless of whether they implement all the requirements -of those templates, this shortcut is not portable. Even if this currently -works with your compiler, it may not work later.

- -

Example

- -

This example shows how some of the arithmetic -operator templates can be used with a geometric point class (template).

- -
-template <class T>
+    template class less_than_comparable<myclass>;
+    template class equality_comparable<myclass>;
+    template class incrementable<myclass>;
+    template class decrementable<myclass>;
+    template class addable<myclass,long>;
+    template class subtractable<myclass,long>;
+
+ +

Usage example

+
+
template <class T>
 class point    // note: private inheritance is OK here!
     : boost::addable< point<T>          // point + point
     , boost::subtractable< point<T>     // point - point
@@ -301,692 +355,165 @@ T length(const point<T> p)
 const point<float> right(0, 1);
 const point<float> up(1, 0);
 const point<float> pi_over_4 = up + right;
-const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);
-
- -

Arithmetic Operators

- -

The arithmetic operator templates ease the task of creating a custom -numeric type. Given a core set of operators, the templates add related -operators to the numeric class. These operations are like the ones the -standard arithmetic types have, and may include comparisons, adding, -incrementing, logical and bitwise manipulations, etc. Further, since -most numeric types need more than one of these operators, some -templates are provided to combine several of the basic operator -templates in one declaration.

- -

The requirements for the types used to instantiate the simple operator -templates are specified in terms of expressions which must be valid and -the expression's return type. The composite operator templates only list -what other templates they use. The supplied operations and requirements -of the composite operator templates can be inferred from the operations and -requirements of the listed components.

- -

Simple Arithmetic Operators

- -

These templates are "simple" since they provide operators -based on a single operation the base type has to provide. They have an -additional optional template parameter B, which is not shown, -for the base class chaining technique. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); +

Arithmetic operators demonstration and test program

+

The operators_test.cpp +program demonstrates the use of the arithmetic operator templates, and can also +be used to verify correct operation.

+

The test program has been compiled and run successfully with: 

+
    +
  • GCC 2.95.2 +
  • GCC 2.95.2 / STLport 4.0b8. +
  • Metrowerks Codewarrior 5.3 +
  • KAI C++ 3.3 +
  • Microsoft Visual C++ 6.0 SP3. +
  • Microsoft Visual C++ 6.0 SP3 / STLport 4.0b8.
  • +
+

Dereference operators and iterator helpers

+

The iterator helper templates ease the task +of creating a custom iterator. Similar to arithmetic types, a complete iterator +has many operators that are "redundant" and can be implemented in +terms of the core set of operators.

+

The dereference operators were motivated by the iterator +helpers, but are often useful in non-iterator contexts as well. Many of the +redundant iterator operators are also arithmetic operators, so the iterator +helper classes borrow many of the operators defined above. In fact, only two new +operators need to be defined! (the pointer-to-member operator-> +and the subscript operator[]). +

Notation

+
Simple Arithmetic Operator Template Classes
- - - - - - - - - -
Key
T: primary operand typeU: alternate operand type
t, t1: values of type - Tu: value of type U
TemplateSupplied OperationsRequirements
less_than_comparable<T>
- less_than_comparable1<T>
bool operator>(const T&, const T&)
- bool operator<=(const T&, const T&)
- bool operator>=(const T&, const T&)
t < t1.
- Return convertible to bool. See the Ordering Note.
less_than_comparable<T, U>
- less_than_comparable2<T, U>
bool operator<=(const T&, const U&)
- bool operator>=(const T&, const U&)
- bool operator>(const U&, const T&)
- bool operator<(const U&, const T&)
- bool operator<=(const U&, const T&)
- bool operator>=(const U&, const T&)
t < u. t > u.
- Returns convertible to bool. See the Ordering Note.
equality_comparable<T>
- equality_comparable1<T>
bool operator!=(const T&, const T&)t == t1.
- Return convertible to bool.
equality_comparable<T, U>
- equality_comparable2<T, U>
friend bool operator==(const U&, const T&)
- friend bool operator!=(const U&, const T&)
- friend bool operator!=( const T&, const U&)
t == u.
- Return convertible to bool.
addable<T>
- addable1<T>
T operator+(T, const T&)t += t1.
- Return convertible to T.
addable<T, U>
- addable2<T, U>
T operator+(T, const U&)
- T operator+(const U&, T )
t += u.
- Return convertible to T.
subtractable<T>
- subtractable1<T>
T operator-(T, const T&)t -= t1.
- Return convertible to T.
subtractable<T, U>
- subtractable2<T, U>
T operator-(T, const U&)t -= u.
- Return convertible to T.
multipliable<T>
- multipliable1<T>
T operator*(T, const T&)t *= t1.
- Return convertible to T.
multipliable<T, U>
- multipliable2<T, U>
T operator*(T, const U&)
- T operator*(const U&, T )
t *= u.
- Return convertible to T.
dividable<T>
- dividable1<T>
T operator/(T, const T&)t /= t1.
- Return convertible to T.
dividable<T, U>
- dividable2<T, U>
T operator/(T, const U&)t /= u.
- Return convertible to T.
modable<T>
- modable1<T>
T operator%(T, const T&)t %= t1.
- Return convertible to T.
modable<T, U>
- modable2<T, U>
T operator%(T, const U&)t %= u.
- Return convertible to T.
orable<T>
- orable1<T>
T operator|(T, const T&)t |= t1.
- Return convertible to T.
orable<T, U>
- orable2<T, U>
T operator|(T, const U&)
- T operator|(const U&, T )
t |= u.
- Return convertible to T.
andable<T>
- andable1<T>
T operator&(T, const T&)t &= t1.
- Return convertible to T.
andable<T, U>
- andable2<T, U>
T operator&(T, const U&)
- T operator&(const U&, T)
t &= u.
- Return convertible to T.
xorable<T>
- xorable1<T>
T operator^(T, const T&)t ^= t1.
- Return convertible to T.
xorable<T, U>
- xorable2<T, U>
T operator^(T, const U&)
- T operator^(const U&, T )
t ^= u.
- Return convertible to T.
incrementable<T>T operator++(T& x, int)T temp(x); ++x; return temp;
- Return convertible to T.
decrementable<T>T operator--(T& x, int)T temp(x); --x; return temp;
- Return convertible to T.
left_shiftable<T>
- left_shiftable1<T>
T operator<<(T, const T&)t <<= t1.
- Return convertible to T.
left_shiftable<T, U>
- left_shiftable2<T, U>
T operator<<(T, const U&)t <<= u.
- Return convertible to T.
right_shiftable<T>
- right_shiftable1<T>
T operator>>(T, const T&)t >>= t1.
- Return convertible to T.
right_shiftable<T, U>
- right_shiftable2<T, U>
T operator>>(T, const U&)t >>= u.
- Return convertible to T.
equivalent<T>
- equivalent1<T>
bool operator==(const T&, const T&)t < t1.
- Return convertible to bool. See the Ordering Note.
equivalent<T, U>
- equivalent2<T, U>
bool operator==(const T&, const U&)t < u. t > u.
- Returns convertible to bool. See the Ordering Note.
partially_ordered<T>
- partially_ordered1<T>
bool operator>(const T&, const T&)
- bool operator<=(const T&, const T&)
- bool operator>=(const T&, const T&)
t < t1. t == t1.
- Returns convertible to bool. See the Ordering Note.
partially_ordered<T, U>
- partially_ordered2<T, U>
bool operator<=(const T&, const U&)
- bool operator>=(const T&, const U&)
- bool operator>(const U&, const T&)
- bool operator<(const U&, const T&)
- bool operator<=(const U&, const T&)
- bool operator>=(const U&, const T&)
t < u. t > u. t == u.
- Returns convertible to bool. See the Ordering Note.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tis the user-defined type for which the operations are + being supplied.
Vis the type which the resulting dereferenceable + type "points to", or the value_type of the custom + iterator.
Dis the type used to index the resulting indexable + type or the difference_type of the custom iterator.
Pis a type which can be dereferenced to access V, + or the pointer type of the custom iterator.
Ris the type returned by indexing the indexable + type or the reference type of the custom iterator.
iis short for static_cast<const T&>(*this), + where this is a pointer to the helper class.
+ Another words, i should be an object of the custom iterator + type.
x,x1,x2are objects of type T.
nis an object of type D.
- -

Ordering Note
-The less_than_comparable<T> -and partially_ordered<T> -templates provide the same set of operations. However, the workings of -less_than_comparable<T> -assume that all values of type T can be placed in a total order. If -that is not true (e.g. Not-a-Number values in IEEE floating point -arithmetic), then -partially_ordered<T> -should be used. The -partially_ordered<T> -template can be used for a totally-ordered type, but it is not as efficient as -less_than_comparable<T>. -This rule also applies for -less_than_comparable<T, -U> and partially_ordered<T, -U> with respect to the ordering of all T and -U values, and for both versions of -equivalent<>. The solution for -equivalent<> is to write a -custom operator== for the target class.

- -

Grouped Arithmetic Operators

- -

The following templates provide common groups of related operations. -For example, since a type which is addable is usually also subractable, the -additive template provides the combined -operators of both. The grouped operator templates have an additional -optional template parameter B, which is not shown, for the -base class chaining technique.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +

The requirements for the types used to instantiate the dereference operators +and iterator helpers are specified in terms of expressions which must be valid +and their return type. 

+

Dereference operators

+

The dereference operator templates in this table all accept an optional +template parameter (not shown) to be used for base class +chaining. +

Grouped Arithmetic Operator Template Classes
- - - - - -
Key
T: primary operand typeU: alternate operand type
TemplateComponent Operator Templates
totally_ordered<T>
- totally_ordered1<T>
totally_ordered<T, U>
- totally_ordered2<T, U>
additive<T>
- additive1<T>
additive<T, U>
- additive2<T, U>
multiplicative<T>
- multiplicative1<T>
multiplicative<T, U>
- multiplicative2<T, U>
integer_multiplicative<T>
- integer_multiplicative1<T>
integer_multiplicative<T, U>
- integer_multiplicative2<T, U>
arithmetic<T>
- arithmetic1<T>
arithmetic<T, U>
- arithmetic2<T, U>
integer_arithmetic<T>
- integer_arithmetic1<T>
integer_arithmetic<T, U>
- integer_arithmetic2<T, U>
bitwise<T>
- bitwise1<T>
bitwise<T, U>
- bitwise2<T, U>
unit_steppable<T>
shiftable<T>
- shiftable1<T>
shiftable<T, U>
- shiftable2<T, U>
+ + + + + + + + + + + + + + + + +
templatetemplate will supplyRequirements
dereferenceable<T,P>P operator->() const(&*i.). Return convertible to P.
indexable<T,D,R>R operator[](D n) const*(i + n). Return of type R.
- -

Example Templates

- -

The arithmetic operator class templates operators<> and operators2<> are examples of -non-extensible operator grouping classes. These legacy class templates, -from previous versions of the header, cannot be used for -base class chaining.

- - - - - - - - - - - - - - - - - - +

Iterator helpers

+

There are three separate iterator helper classes, each for a different +category of iterator. Here is a summary of the core set of operators that the +custom iterator must define, and the extra operators that are created by the +helper classes. For convenience, the helper classes also fill in all of the +typedef's required of iterators by the C++ standard (iterator_category, +value_type, etc.).

+
Final Arithmetic Operator Template Classes
- - - - - -
Key
T: primary operand typeU: alternate operand type
TemplateComponent Operator Templates
operators<T>
operators<T, U>
- operators2<T, U>
+ + + + + + + + + + + + + + + + + + + + + +
templatetemplate will supplyRequirements
forward_iterator_helper
+ <T,V,D,P,R>
bool operator!=(const T& x1, const T& x2)
+ T operator++(T& x, int)
+ V* operator->() const
+
x1==x2. Return convertible to bool
+ T temp(x); ++x; return temp;
+ (&*i.). Return convertible to V*.
bidirectional_iterator_helper
+ <T,V,D,P,R>
Same as above, plus
+ T operator--(T& x, int)
Same as above, plus
+ T temp(x); --x; return temp;
random_access_iterator_helper
+ <T,V,D,P,R>
Same as above, plus
+ T operator+(T x, const D&)
+ T operator+(const D& n, T x)
+ T operator-(T x, const D& n)
+ R operator[](D n) const
+ bool operator>(const T& x1, const T& x2) 
+ bool operator<=(const T& x1, const T& x2)
+ bool operator>=(const T& x1, const T& x2)
Same as above, plus
+ x+=n. Return convertible to T
+ x-=n. Return convertible to T
+ x1<x2. Return convertible to bool
+ And to satisfy RandomAccessIterator:
+ x1-x2. Return convertible to D
- -

Arithmetic Operators Demonstration and Test Program

- -

The operators_test.cpp -program demonstrates the use of the arithmetic operator templates, and -can also be used to verify correct operation. Check the compiler status report for the test results -with selected platforms.

- -

Dereference Operators and Iterator Helpers

- -

The iterator helper templates ease the task -of creating a custom iterator. Similar to arithmetic types, a complete -iterator has many operators that are "redundant" and can be -implemented in terms of the core set of operators.

- -

The dereference operators were motivated -by the iterator helpers, but are often useful in -non-iterator contexts as well. Many of the redundant iterator operators -are also arithmetic operators, so the iterator helper classes borrow -many of the operators defined above. In fact, only two new operators -need to be defined (the pointer-to-member operator-> and -the subscript operator[])!

- -

The requirements for the types used to instantiate the dereference -operators are specified in terms of expressions which must be valid and -their return type. The composite operator templates list their component -templates, which the instantiating type must support, and possibly other -requirements.

- -

Dereference Operators

- -

All the dereference operator templates in this table accept an -optional template parameter (not shown) to be used for base class chaining.

- - - - - - - - - - - - - - - - - - - - - -
Dereference Operator Template Classes
- - - - - - - - - - - - - -
Key
T: operand typeP: pointer type
D: difference_typeR: reference type
i: object of type T (an iterator)n: object of type D (an index)
TemplateSupplied OperationsRequirements
dereferenceable<T, P>P operator->() const(&*i). Return convertible to P.
indexable<T, D, R>R operator[](D n) const*(i + n). Return of type R.
- -

Iterator Helpers

- -

There are three separate iterator helper classes, each for a -different category of iterator. Here is a summary of the core set of -operators that the custom iterator must define, and the extra operators -that are created by the helper classes. These classes cannot be used for base class chaining. For convenience, the helper -classes also fill in all of the typedef's required of iterators by the -C++ standard (iterator_category, value_type, -etc.).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Iterator Helper Template Classes
- - - - - - - - - - - - - -
Key
T: operand typeP: pointer type
D: difference_typeR: reference type
V: value_typex1, x2: objects of type T
TemplateOperations & Requirements
input_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
output_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
forward_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
bidirectional_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
random_access_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of - - To satisfy RandomAccessIterator, - x1 - x2 with return convertible to D - is also required.
- -

Iterator Demonstration and Test Program

- -

The iterators_test.cpp -program demonstrates the use of the iterator templates, and can also be -used to verify correct operation. The following is the custom iterator -defined in the test program. It demonstrates a correct (though trivial) -implementation of the core operations that must be defined in order for -the iterator helpers to "fill in" the rest of the iterator -operations.

- +

Iterator demonstration and test program

+

The iterators_test.cpp +program demonstrates the use of the iterator templates, and can also be used to +verify correct operation. The following is the custom iterator defined in the +test program. It demonstrates a correct (though trivial) implementation of the +core operations that must be defined in order for the iterator helpers to +"fill in" the rest of the iterator operations.

-
template <class T, class R, class P>
+  
template <class T, class R, class P>
 struct test_iter
   : public boost::random_access_iterator_helper<
      test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
@@ -996,109 +523,75 @@ struct test_iter
   typedef std::ptrdiff_t Distance;
 
 public:
-  explicit test_iter(T* i =0);
-  test_iter(const self& x);
-  self& operator=(const self& x);
-  Reference operator*() const;
-  self& operator++();
-  self& operator--();
-  self& operator+=(Distance n);
-  self& operator-=(Distance n);
-  bool operator==(const self& x) const;
-  bool operator<(const self& x) const;
-  friend Distance operator-(const self& x, const self& y);
+  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;
 };
- -

Check the compiler status report for -the test results with selected platforms.

- +

It has been compiled and run successfully with:

+
    +
  • GCC 2.95.2 +
  • Metrowerks Codewarrior 5.2 +
  • Microsoft Visual C++ 6.0 SP3
  • +
+

Jeremy Siek +contributed the iterator operators and helpers.  He also contributed iterators_test.cpp


- -

Contributors

- -
-
Dave Abrahams -
Started the library and contributed the arithmetic operators in - boost/operators.hpp. - -
Jeremy Siek -
Contributed the dereference operators and - iterator helpers in boost/operators.hpp. - Also contributed iterators_test.cpp. - -
Aleksey Gurtovoy -
Contributed the code to support base class - chaining while remaining backward-compatible with old - versions of the library. - -
Beman Dawes -
Contributed operators_test.cpp. - -
Daryle Walker -
Contributed classes for the shift operators, equivalence, - partial ordering, and arithmetic conversions. Added the - grouped operator classes. Added helper classes for - input and output iterators. -
- -

Note for Users of Older Versions

- -

The changes in the library interface and -recommended usage were motivated by some practical issues described -below. The new version of the library is still backward-compatible with -the former one (so you're not forced change any existing code), -but the old usage is deprecated. Though it was arguably simpler and -more intuitive than using base class chaining, -it has been discovered that the old practice of deriving from multiple -operator templates can cause the resulting classes to be much larger -than they should be. Most modern C++ compilers significantly bloat the -size of classes derived from multiple empty base classes, even though -the base classes themselves have no state. For instance, the size of -point<int> from the example -above was 12-24 bytes on various compilers for the Win32 platform, -instead of the expected 8 bytes.

- -

Strictly speaking, it was not the library's fault--the language -rules allow the compiler to apply the empty base class optimization in -that situation. In principle an arbitrary number of empty base classes -can be allocated at the same offset, provided that none of them have a -common ancestor (see section 10.5 [class.derived] paragraph 5 of the -standard). But the language definition also doesn't require -implementations to do the optimization, and few if any of today's -compilers implement it when multiple inheritance is involved. What's -worse, it is very unlikely that implementors will adopt it as a future -enhancement to existing compilers, because it would break binary -compatibility between code generated by two different versions of the -same compiler. As Matt Austern said, "One of the few times when you -have the freedom to do this sort of thing is when you're targeting a new -architecture...". On the other hand, many common compilers will use -the empty base optimization for single inheritance hierarchies.

- -

Given the importance of the issue for the users of the library (which -aims to be useful for writing light-weight classes like -MyInt or point<>), and the forces -described above, we decided to change the library interface so that the -object size bloat could be eliminated even on compilers that support -only the simplest form of the empty base class optimization. The -current library interface is the result of those changes. Though the -new usage is a bit more complicated than the old one, we think it's -worth it to make the library more useful in real world. Alexy Gurtovoy -contributed the code which supports the new usage idiom while allowing -the library remain backward-compatible.

- +

Note for users of older versions

+

The changes in the library interface and recommended +usage were motivated by some practical issues described below. The new +version of the library is still backward-compatible with the former one (so +you're not forced change any existing code), but the old usage is +deprecated. Though it was arguably simpler and more intuitive than using base +class chaining, it has been discovered that the old practice of deriving +from multiple operator templates can cause the resulting classes to be much +larger than they should be. Most modern C++ compilers significantly bloat the +size of classes derived from multiple empty base classes, even though the base +classes themselves have no state. For instance, the size of point<int> +from the example above was 12-24 bytes on various compilers +for the Win32 platform, instead of the expected 8 bytes. +

Strictly speaking, it was not the library's fault - the language rules allow +the compiler to apply the empty base class optimization in that situation. In +principle an arbitrary number of empty base classes can be allocated at the same +offset, provided that none of them have a common ancestor (see section 10.5 [class.derived], +par. 5 of the standard). But the language definition also doesn't require +implementations to do the optimization, and few if any of today's compilers +implement it when multiple inheritance is involved. What's worse, it is very +unlikely that implementors will adopt it as a future enhancement to existing +compilers, because it would break binary compatibility between code generated by +two different versions of the same compiler. As Matt Austern said, "One of +the few times when you have the freedom to do this sort of thing is when you're +targeting a new architecture...". On the other hand, many common compilers +will use the empty base optimization for single inheritance hierarchies.

+

Given the importance of the issue for the users of the library (which aims to +be useful for writing light-weight classes like MyInt or point<>), +and the forces described above, we decided to change the library interface so +that the object size bloat could be eliminated even on compilers that support +only the simplest form of the empty base class optimization. The current library +interface is the result of those changes. Though the new usage is a bit more +complicated than the old one, we think it's worth it to make the library more +useful in real world. Alexy Gurtovoy contributed the code which supports the new +usage idiom while allowing the library remain backward-compatible.


- -

Revised: 20 May 2001

- -

Copyright © David Abrahams and Beman Dawes 1999-2001. -Permission to copy, use, modify, sell and distribute this document is -granted provided this copyright notice appears in all copies. This -document is provided "as is" without express or implied -warranty, and with no claim as to its suitability for any purpose.

+

Revised 10 Feb 2001

+

© Copyright David Abrahams and Beman Dawes 1999-2000. Permission to copy, +use, modify, sell and distribute this document is granted provided this +copyright notice appears in all copies. This document is provided "as +is" without express or implied warranty, and with no claim as to its +suitability for any purpose.

+ diff --git a/operators_test.cpp b/operators_test.cpp index ce03e87..a194521 100644 --- a/operators_test.cpp +++ b/operators_test.cpp @@ -8,26 +8,18 @@ // See http://www.boost.org for most recent version including documentation. // Revision History -// 20 May 01 Output progress messages. Added tests for new operator -// templates. Updated random number generator. Changed tests to -// use Boost Test Tools library. (Daryle Walker) // 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) +// 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 -#define BOOST_INCLUDE_MAIN - -#include // for BOOST_MSVC -#include // for boost::exit_success -#include // for the tested items -#include // for boost::minstd_rand -#include // for main - -#include // for std::cout (std::endl indirectly) +#include +#include +#include +#include namespace @@ -36,18 +28,14 @@ namespace int true_value(int x) { return x; } long true_value(long x) { return x; } signed char true_value(signed char x) { return x; } - short true_value(short 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; } - unsigned short true_value(unsigned short x) { return x; } - // The use of operators<> here tended to obscure - // interactions with certain compiler bugs + // The use of operators<> here tended to obscure interactions with certain + // compiler bugs template - class Wrapped1 - : boost::operators > - , boost::shiftable > + class Wrapped1 : boost::operators > { public: explicit Wrapped1( T v = T() ) : _value(v) {} @@ -72,10 +60,6 @@ namespace { _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; } @@ -86,11 +70,9 @@ namespace T true_value(Wrapped1 x) { return x.value(); } template - class Wrapped2 - : boost::operators > - , boost::operators2, U> - , boost::shiftable1 - , boost::shiftable2, U > > + class Wrapped2 : + boost::operators >, + boost::operators2, U> { public: explicit Wrapped2( T v = T() ) : _value(v) {} @@ -115,10 +97,6 @@ namespace { _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; } @@ -133,8 +111,6 @@ namespace 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; @@ -142,268 +118,203 @@ namespace template T true_value(Wrapped2 x) { return x.value(); } - template - class Wrapped3 - : boost::equivalent > - , boost::partially_ordered > - , boost::equality_comparable > - { - public: - explicit Wrapped3( T v = T() ) : _value(v) {} - T value() const { return _value; } - - bool operator<(const Wrapped3& x) const { return _value < x._value; } - - private: - T _value; - }; - template - T true_value(Wrapped3 x) { return x.value(); } - - template - class Wrapped4 - : boost::equality_comparable1 - , boost::equivalent1 - , boost::partially_ordered1 > > > - , boost::partially_ordered2, U - , boost::equivalent2, U - , boost::equality_comparable2, U> > > - { - public: - explicit Wrapped4( T v = T() ) : _value(v) {} - T value() const { return _value; } - - bool operator<(const Wrapped4& x) const { return _value < x._value; } - - bool operator<(U u) const { return _value < u; } - bool operator>(U u) const { return _value > u; } - - private: - T _value; - }; - template - T true_value(Wrapped4 x) { return x.value(); } - // MyInt uses only the single template-argument form of all_operators<> typedef Wrapped1 MyInt; typedef Wrapped2 MyLong; - typedef Wrapped3 MyChar; - - typedef Wrapped4 MyShort; - template void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) { - BOOST_TEST( true_value(y1) == true_value(y2) ); - BOOST_TEST( true_value(x1) == true_value(x2) ); + 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) { - BOOST_TEST( (x1 < y1) == (x2 < y2) ); - BOOST_TEST( (x1 <= y1) == (x2 <= y2) ); - BOOST_TEST( (x1 >= y1) == (x2 >= y2) ); - BOOST_TEST( (x1 > y1) == (x2 > 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 ); + 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) { - BOOST_TEST( (x1 == y1) == (x2 == y2) ); - BOOST_TEST( (x1 != y1) == (x2 != 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 ); + 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) { - BOOST_TEST( (x1 * y1).value() == (x2 * 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 ); + 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) { - BOOST_TEST( (x1 + y1).value() == (x2 + 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 ); + 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 ); - BOOST_TEST( (x1 - y1).value() == (x2 - 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 ) - BOOST_TEST( (x1 / y1).value() == (x2 / 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 ) - BOOST_TEST( (x1 % y1).value() == (x2 % 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) { - BOOST_TEST( (x1 ^ y1).value() == (x2 ^ 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 ); + 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) { - BOOST_TEST( (x1 & y1).value() == (x2 & 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 ); + 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) { - BOOST_TEST( (x1 | y1).value() == (x2 | 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_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - BOOST_TEST( (x1 << y1).value() == (x2 << y2) ); - } - - template - void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - BOOST_TEST( (x1 >> y1).value() == (x2 >> 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 ); - BOOST_TEST( (x1++).value() == x2++ ); - BOOST_TEST( x1.value() == 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 ); - BOOST_TEST( (x1--).value() == x2-- ); - BOOST_TEST( x1.value() == 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_left_shiftable( x1, y1, x2, y2 ); - test_right_shiftable( x1, y1, x2, y2 ); - test_incrementable( x1, x2 ); - test_decrementable( x1, x2 ); + 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::minstd_rand& randomizer) const + void operator()(boost::min_rand& randomizer) const { - Big b1 = Big( randomizer() ); - Big b2 = Big( randomizer() ); - Small s = Small( randomizer() ); + 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 ); + 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 > + : 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; } + 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 @@ -429,25 +340,20 @@ template Wrapped2; template Wrapped2; #endif -#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) +#ifdef NDEBUG +#error This program is pointless when NDEBUG disables assert()! +#endif - -int -test_main( int , char * [] ) +int main() { - using std::cout; - using std::endl; - // Regression test. Point x; x = x + Point(3, 4); x = x - Point(3, 4); - cout << "Created point, and operated on it." << endl; - for (int n = 0; n < 10000; ++n) { - boost::minstd_rand r; + boost::min_rand r; tester()(r); tester()(r); tester()(r); @@ -461,197 +367,115 @@ test_main( int , char * [] ) tester()(r); } - cout << "Did random tester loop." << endl; - MyInt i1(1); MyInt i2(2); MyInt i; - BOOST_TEST( i1.value() == 1 ); - BOOST_TEST( i2.value() == 2 ); - BOOST_TEST( i.value() == 0 ); + assert( i1.value() == 1 ); + assert( i2.value() == 2 ); + assert( i.value() == 0 ); - cout << "Created MyInt objects.\n"; + 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 ); - PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); - - BOOST_TEST( i2 == i ); - BOOST_TEST( i1 != i2 ); - BOOST_TEST( i1 < i2 ); - BOOST_TEST( i1 <= i2 ); - BOOST_TEST( i <= i2 ); - BOOST_TEST( i2 > i1 ); - BOOST_TEST( i2 >= i1 ); - BOOST_TEST( i2 >= i ); - - PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); - PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); - PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); - PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); - PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); - PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); - PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); - PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); - PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); - - PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); + 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 ); - cout << "Performed tests on MyInt objects.\n"; - MyLong j1(1); MyLong j2(2); MyLong j; - BOOST_TEST( j1.value() == 1 ); - BOOST_TEST( j2.value() == 2 ); - BOOST_TEST( j.value() == 0 ); + assert( j1.value() == 1 ); + assert( j2.value() == 2 ); + assert( j.value() == 0 ); - cout << "Created MyLong objects.\n"; + 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 ); - PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); + assert( (j1 + 2) == 3 ); + assert( (1 + j2) == 3 ); + j = j1 + j2; assert( j.value() == 3 ); - BOOST_TEST( j2 == j ); - BOOST_TEST( 2 == j ); - BOOST_TEST( j2 == 2 ); - BOOST_TEST( j == j2 ); - BOOST_TEST( j1 != j2 ); - BOOST_TEST( j1 != 2 ); - BOOST_TEST( 1 != j2 ); - BOOST_TEST( j1 < j2 ); - BOOST_TEST( 1 < j2 ); - BOOST_TEST( j1 < 2 ); - BOOST_TEST( j1 <= j2 ); - BOOST_TEST( 1 <= j2 ); - BOOST_TEST( j1 <= j ); - BOOST_TEST( j <= j2 ); - BOOST_TEST( 2 <= j2 ); - BOOST_TEST( j <= 2 ); - BOOST_TEST( j2 > j1 ); - BOOST_TEST( 2 > j1 ); - BOOST_TEST( j2 > 1 ); - BOOST_TEST( j2 >= j1 ); - BOOST_TEST( 2 >= j1 ); - BOOST_TEST( j2 >= 1 ); - BOOST_TEST( j2 >= j ); - BOOST_TEST( 2 >= j ); - BOOST_TEST( j2 >= 2 ); - - BOOST_TEST( (j1 + 2) == 3 ); - BOOST_TEST( (1 + j2) == 3 ); - PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); + assert( (j + 2) == 5 ); + assert( (3 + j2) == 5 ); + j = j + j2; assert( j.value() == 5 ); - BOOST_TEST( (j + 2) == 5 ); - BOOST_TEST( (3 + j2) == 5 ); - PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); + assert( (j - 1) == 4 ); + j = j - j1; assert( j.value() == 4 ); - BOOST_TEST( (j - 1) == 4 ); - PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); + assert( (j * 2) == 8 ); + assert( (4 * j2) == 8 ); + j = j * j2; assert( j.value() == 8 ); - BOOST_TEST( (j * 2) == 8 ); - BOOST_TEST( (4 * j2) == 8 ); - PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); + assert( (j / 2) == 4 ); + j = j / j2; assert( j.value() == 4 ); - BOOST_TEST( (j / 2) == 4 ); - PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); + assert( (j % 3) == 1 ); + j = j % (j - j1); assert( j.value() == 1 ); - BOOST_TEST( (j % 3) == 1 ); - PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); + j = j2 + j2; assert( j.value() == 4 ); - PRIVATE_EXPR_TEST( (j = j2 + j2), (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 ); - BOOST_TEST( (1 | j2 | j) == 7 ); - BOOST_TEST( (j1 | 2 | j) == 7 ); - BOOST_TEST( (j1 | j2 | 4) == 7 ); - PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); + assert( (7 & j2) == 2 ); + assert( (j & 2) == 2 ); + j = j & j2; assert( j.value() == 2 ); - BOOST_TEST( (7 & j2) == 2 ); - BOOST_TEST( (j & 2) == 2 ); - PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); + j = j | j1; assert( j.value() == 3 ); - PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); + assert( (3 ^ j1) == 2 ); + assert( (j ^ 1) == 2 ); + j = j ^ j1; assert( j.value() == 2 ); - BOOST_TEST( (3 ^ j1) == 2 ); - BOOST_TEST( (j ^ 1) == 2 ); - PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); + j = (j+j1)*(j2|j1); assert( j.value() == 9 ); - PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); - - BOOST_TEST( (j1 << 2) == 4 ); - BOOST_TEST( (j2 << 1) == 4 ); - PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); - - BOOST_TEST( (j >> 2) == 1 ); - BOOST_TEST( (j2 >> 1) == 1 ); - PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); - - cout << "Performed tests on MyLong objects.\n"; - - MyChar k1(1); - MyChar k2(2); - MyChar k; - - BOOST_TEST( k1.value() == 1 ); - BOOST_TEST( k2.value() == 2 ); - BOOST_TEST( k.value() == 0 ); - - cout << "Created MyChar objects.\n"; - - PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); - - BOOST_TEST( k2 == k ); - BOOST_TEST( k1 != k2 ); - BOOST_TEST( k1 < k2 ); - BOOST_TEST( k1 <= k2 ); - BOOST_TEST( k <= k2 ); - BOOST_TEST( k2 > k1 ); - BOOST_TEST( k2 >= k1 ); - BOOST_TEST( k2 >= k ); - - cout << "Performed tests on MyChar objects.\n"; - - MyShort l1(1); - MyShort l2(2); - MyShort l; - - BOOST_TEST( l1.value() == 1 ); - BOOST_TEST( l2.value() == 2 ); - BOOST_TEST( l.value() == 0 ); - - cout << "Created MyShort objects.\n"; - - PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); - - BOOST_TEST( l2 == l ); - BOOST_TEST( 2 == l ); - BOOST_TEST( l2 == 2 ); - BOOST_TEST( l == l2 ); - BOOST_TEST( l1 != l2 ); - BOOST_TEST( l1 != 2 ); - BOOST_TEST( 1 != l2 ); - BOOST_TEST( l1 < l2 ); - BOOST_TEST( 1 < l2 ); - BOOST_TEST( l1 < 2 ); - BOOST_TEST( l1 <= l2 ); - BOOST_TEST( 1 <= l2 ); - BOOST_TEST( l1 <= l ); - BOOST_TEST( l <= l2 ); - BOOST_TEST( 2 <= l2 ); - BOOST_TEST( l <= 2 ); - BOOST_TEST( l2 > l1 ); - BOOST_TEST( 2 > l1 ); - BOOST_TEST( l2 > 1 ); - BOOST_TEST( l2 >= l1 ); - BOOST_TEST( 2 >= l1 ); - BOOST_TEST( l2 >= 1 ); - BOOST_TEST( l2 >= l ); - BOOST_TEST( 2 >= l ); - BOOST_TEST( l2 >= 2 ); - - cout << "Performed tests on MyShort objects.\n"; - - return boost::exit_success; + std::cout << "0 errors detected\n"; + return 0; }