diff --git a/boost/integer/cover_operators.hpp b/boost/integer/cover_operators.hpp index 46bb819..7ddea20 100644 --- a/boost/integer/cover_operators.hpp +++ b/boost/integer/cover_operators.hpp @@ -1,16 +1,26 @@ // boost/integer/cover_operators.hpp ----------------------------------------// -// (C) Copyright Darin Adler 2000 +// Copyright Darin Adler 2000 +// Copyright Beman Dawes 2008 // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) //----------------------------------------------------------------------------// +// If the class being covered has a non-explicit conversion to an integer type +// then a smaller number of cover operations are needed. Define the macro +// BOOST_MINIMAL_INTEGER_COVER_OPERATORS to indicate this. + +//----------------------------------------------------------------------------// + #ifndef BOOST_INTEGER_COVER_OPERATORS_HPP #define BOOST_INTEGER_COVER_OPERATORS_HPP -#include +# ifndef BOOST_MINIMAL_INTEGER_COVER_OPERATORS +# include +# endif + #include namespace boost @@ -21,13 +31,17 @@ namespace boost // A class that adds integer operators to an integer cover class template - class cover_operators : boost::operators + class cover_operators +# ifndef BOOST_MINIMAL_INTEGER_COVER_OPERATORS + : boost::operators +# endif { // The other operations take advantage of the type conversion that's // built into unary +. // Unary operations. friend IntegerType operator+(const T& x) { return x; } +# ifndef BOOST_MINIMAL_INTEGER_COVER_OPERATORS friend IntegerType operator-(const T& x) { return -+x; } friend IntegerType operator~(const T& x) { return ~+x; } friend IntegerType operator!(const T& x) { return !+x; } @@ -35,6 +49,7 @@ namespace boost // The basic ordering operations. friend bool operator==(const T& x, IntegerType y) { return +x == y; } friend bool operator<(const T& x, IntegerType y) { return +x < y; } +# endif // The basic arithmetic operations. friend T& operator+=(T& x, IntegerType y) { return x = +x + y; } @@ -57,8 +72,23 @@ namespace boost friend T& operator++(T& x) { return x += 1; } friend T& operator--(T& x) { return x -= 1; } - /// TODO: stream I/O needs to be templatized on the stream type, so will - /// work with wide streams, etc. +# ifdef BOOST_MINIMAL_INTEGER_COVER_OPERATORS + friend T operator++(T& x, int) + { + T tmp(x); + x += 1; + return tmp; + } + friend T operator--(T& x, int) + { + T tmp(x); + x -= 1; + return tmp; + } +# endif + + // TODO: stream I/O needs to be templatized on the stream type, so will + // work with wide streams, etc. // Stream input and output. friend std::ostream& operator<<(std::ostream& s, const T& x) diff --git a/boost/integer/endian.hpp b/boost/integer/endian.hpp index bfe2317..a860e9c 100644 --- a/boost/integer/endian.hpp +++ b/boost/integer/endian.hpp @@ -26,8 +26,15 @@ #ifndef BOOST_ENDIAN_HPP #define BOOST_ENDIAN_HPP +// Pending updates to boost/config.hpp for C++0x, assume that the C++0x feature +// we care about is not present: +#define BOOST_NO_DEFAULTED_FUNCTIONS + +#include #include -//#include +#define BOOST_MINIMAL_INTEGER_COVER_OPERATORS +#include +#undef BOOST_MINIMAL_INTEGER_COVER_OPERATORS #include #include #include @@ -39,9 +46,9 @@ # endif # ifndef BOOST_NO_DEFAULTED_FUNCTIONS -# define BOOST_ENDIAN_DEFAULTED = default; // C++0x +# define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x # else -# define BOOST_ENDIAN_DEFAULTED {} // C++03 +# define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03 # endif # if defined(BOOST_NO_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIANS_IN_UNIONS) @@ -142,6 +149,11 @@ namespace boost namespace integer { +# ifdef BOOST_ENDIAN_LOG + bool endian_log(true); +# endif + + // endian class template and specializations -----------------------------// // simulate C++0x scoped enums @@ -160,17 +172,31 @@ namespace boost // unaligned big endian specialization template class endian< endianness::big, T, n_bits, alignment::unaligned > - // : cover_operators< endian< endianness::big, T, n_bits >, T > + : cover_operators< endian< endianness::big, T, n_bits >, T > { BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); public: typedef T value_type; # ifndef BOOST_ENDIAN_NO_CTORS - endian() BOOST_ENDIAN_DEFAULTED - endian(T val) { detail::store_big_endian(m_value, val); } + endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT + explicit endian(T val) + { +# ifdef BOOST_ENDIAN_LOG + if ( endian_log ) + std::clog << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n"; +# endif + detail::store_big_endian(m_value, val); + } # endif endian & operator=(T val) { detail::store_big_endian(m_value, val); return *this; } - operator T() const { return detail::load_big_endian(m_value); } + operator T() const + { +# ifdef BOOST_ENDIAN_LOG + if ( endian_log ) + std::clog << "big, unaligned, " << n_bits << "-bits, convert(" << detail::load_big_endian(m_value) << ")\n"; +# endif + return detail::load_big_endian(m_value); + } private: char m_value[n_bits/8]; }; @@ -178,17 +204,31 @@ namespace boost // unaligned little endian specialization template class endian< endianness::little, T, n_bits, alignment::unaligned > -// : cover_operators< endian< endianness::little, T, n_bits >, T > + : cover_operators< endian< endianness::little, T, n_bits >, T > { BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); public: typedef T value_type; # ifndef BOOST_ENDIAN_NO_CTORS - endian() BOOST_ENDIAN_DEFAULTED - endian(T val) { detail::store_little_endian(m_value, val); } + endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT + explicit endian(T val) + { +# ifdef BOOST_ENDIAN_LOG + if ( endian_log ) + std::clog << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n"; +# endif + detail::store_little_endian(m_value, val); + } # endif endian & operator=(T val) { detail::store_little_endian(m_value, val); return *this; } - operator T() const { return detail::load_little_endian(m_value); } + operator T() const + { +# ifdef BOOST_ENDIAN_LOG + if ( endian_log ) + std::clog << "little, unaligned, " << n_bits << "-bits, convert(" << detail::load_little_endian(m_value) << ")\n"; +# endif + return detail::load_little_endian(m_value); + } private: char m_value[n_bits/8]; }; @@ -196,17 +236,17 @@ namespace boost // unaligned native endian specialization template class endian< endianness::native, T, n_bits, alignment::unaligned > -// : cover_operators< endian< endianness::native, T, n_bits >, T > + : cover_operators< endian< endianness::native, T, n_bits >, T > { BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); public: typedef T value_type; # ifndef BOOST_ENDIAN_NO_CTORS - endian() BOOST_ENDIAN_DEFAULTED + endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT # ifdef BOOST_BIG_ENDIAN - endian(T val) { detail::store_big_endian(m_value, val); } + explicit endian(T val) { detail::store_big_endian(m_value, val); } # else - endian(T val) { detail::store_little_endian(m_value, val); } + explicit endian(T val) { detail::store_little_endian(m_value, val); } # endif # endif # ifdef BOOST_BIG_ENDIAN @@ -226,18 +266,18 @@ namespace boost // aligned big endian specialization template class endian< endianness::big, T, n_bits, alignment::aligned > -// : cover_operators< endian< endianness::big, T, n_bits, alignment::aligned >, T > + : cover_operators< endian< endianness::big, T, n_bits, alignment::aligned >, T > { BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); public: typedef T value_type; # ifndef BOOST_ENDIAN_NO_CTORS - endian() BOOST_ENDIAN_DEFAULTED + endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT # ifdef BOOST_BIG_ENDIAN endian(T val) : m_value(val) { } # else - endian(T val) { detail::store_big_endian(&m_value, val); } + explicit endian(T val) { detail::store_big_endian(&m_value, val); } # endif # endif # ifdef BOOST_BIG_ENDIAN @@ -254,18 +294,18 @@ namespace boost // aligned little endian specialization template class endian< endianness::little, T, n_bits, alignment::aligned > -// : cover_operators< endian< endianness::little, T, n_bits, alignment::aligned >, T > + : cover_operators< endian< endianness::little, T, n_bits, alignment::aligned >, T > { BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); public: typedef T value_type; # ifndef BOOST_ENDIAN_NO_CTORS - endian() BOOST_ENDIAN_DEFAULTED + endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT # ifdef BOOST_BIG_ENDIAN endian(T val) : m_value(val) { } # else - endian(T val) { detail::store_little_endian(&m_value, val); } + explicit endian(T val) { detail::store_little_endian(&m_value, val); } # endif # endif # ifdef BOOST_LITTLE_ENDIAN diff --git a/libs/integer/test/endian-in-sandbox/endian_operations_test/endian_operations_test.vcproj b/libs/integer/test/endian-in-sandbox/endian_operations_test/endian_operations_test.vcproj index 384d449..37ff6c5 100644 --- a/libs/integer/test/endian-in-sandbox/endian_operations_test/endian_operations_test.vcproj +++ b/libs/integer/test/endian-in-sandbox/endian_operations_test/endian_operations_test.vcproj @@ -49,6 +49,7 @@ UsePrecompiledHeader="0" WarningLevel="3" DebugInformationFormat="4" + DisableSpecificWarnings="4552" /> #include +#include + +namespace bi = boost::integer; #ifdef _MSC_VER -# pragma warning( disable : 4244 ) +# pragma warning( disable : 4244 ) // conversion ..., possible loss of data +# pragma warning( disable : 4018 ) // signed/unsigned mismatch #endif -using namespace boost::integer; - template struct default_construct { @@ -38,34 +49,73 @@ struct construct } }; +template +struct initialize +{ + static void test() + { + T1 o2(2); + T1 o1 = o2; + } +}; + template struct assign { static void test() { T2 o2; - o2 = 123; + o2 = 1; T1 o1; - o1 = 02; + o1 = o2; } }; template -struct pass +struct relational { static void test() { + T1 o1(1); + T2 o2(2); + if ( o1 == o2 ) return; + if ( o1 != o2 ) return; + if ( o1 < o2 ) return; + if ( o1 <= o2 ) return; + if ( o1 > o2 ) return; + if ( o1 >= o2 ) return; } }; template -struct compare +struct op_plus { static void test() { - T1 o1 = 1; - T2 o2 = 2; - if (o1 == o2) return; + T1 o1(1); + T2 o2(2); + T1 o3; + + o3 = +o1; + + o3 = o1 + o2; + + o1 += o2; + } +}; + +template +struct op_star +{ + static void test() + { + T1 o1(1); + T2 o2(2); + T1 o3; + + o3 = o1 * o2; + + o1 *= o2; } }; @@ -83,54 +133,54 @@ void op_test_aux() Test::test(); Test::test(); Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); - Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); + Test::test(); } @@ -148,68 +198,141 @@ void op_test() op_test_aux(); op_test_aux(); op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); - op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); + op_test_aux(); } int main() { - + bi::endian_log = false; - big32_t o1(1); - big32_t o2(2L); - big32_t o3(3LL); + // make sure some simple things work + + bi::big32_t o1(1); + bi::big32_t o2(2L); + bi::big32_t o3(3LL); + bi::big64_t o4(1); + + // use cases; if BOOST_ENDIAN_LOG is defined, will output to clog info on + // what overloads and conversions are actually being performed. + + bi::endian_log = true; + + std::clog << "set up test values\n"; + bi::big32_t big(12345); + bi::ulittle16_t ulittle(10); + bi::big64_t result; + + + std::clog << "\nresult = +big\n"; + result = +big; + + std::clog << "\nresult = -big\n"; + result = -big; + + std::clog << "\n++big\n"; + ++big; + + std::clog << "\nresult = big++\n"; + big++; + + std::clog << "\n--big\n"; + --big; + + std::clog << "\nbig--\n"; + big--; + + std::clog << "\nresult = big * big\n"; + result = big * big; + + std::clog << "\nresult = big * big\n"; + result = big * big; + + std::clog << "\nresult = big * ulittle\n"; + result = big * ulittle; + + std::clog << "\nbig *= ulittle\n"; + big *= ulittle; + + std::clog << "\nresult = ulittle * big\n"; + result = ulittle * big; + + std::clog << "\nresult = big * 5\n"; + result = big * 5; + + std::clog << "\nbig *= 5\n"; + big *= 5; + + std::clog << "\nresult = 5 * big\n"; + result = 5 * big; + + std::clog << "\nresult = ulittle * 5\n"; + result = ulittle * 5; + + std::clog << "\nresult = 5 * ulittle\n"; + result = 5 * ulittle; + + std::clog << "\nresult = 5 * 10\n"; + result = 5 * 10; + std::clog << "\n"; + + bi::endian_log = false; + + // perform the indicated test on ~60*60 operand types op_test(); - op_test(); + op_test(); // includes copy construction + op_test(); op_test(); - op_test(); - op_test(); + op_test(); + op_test(); + op_test(); + return 0; } diff --git a/libs/integer/test/endian_test.cpp b/libs/integer/test/endian_test.cpp index 40ad189..5dd411d 100644 --- a/libs/integer/test/endian_test.cpp +++ b/libs/integer/test/endian_test.cpp @@ -1,6 +1,6 @@ // endian_test.cpp ---------------------------------------------------------// -// Copyright Beman Dawes, 1999-2006 +// Copyright Beman Dawes, 1999-2008 // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -9,6 +9,13 @@ //----------------------------------------------------------------------------// +// This test probes for correct endianess, size, and value. + +// See endian_operations_test for tests of operator correctness and interaction +// between operand types. + +//----------------------------------------------------------------------------// + #include #include #include @@ -19,9 +26,10 @@ #include // for atoi(), exit() #include // for memcmp() -using namespace std; // not the best programming practice, but I +using namespace std; // Not the best programming practice, but I using namespace boost; // want to verify this combination of using -using namespace boost::integer; // namespaces works. +using namespace boost::integer; // namespaces works. See endian_operations_test +// // for tests that don't do "using namespace". #define VERIFY(predicate) verify( predicate, __LINE__ ) #define VERIFY_SIZE(actual, expected) verify_size( actual, expected, __LINE__ ) @@ -72,8 +80,8 @@ namespace void verify_representation( bool is_big, int line ) { int silence = 0; - Endian x = static_cast - (0x123456789abcdef0LL + silence); // will truncate + Endian x ( static_cast + (0x123456789abcdef0LL + silence) ); // will truncate if ( is_big ) verify( memcmp( &x, @@ -93,8 +101,6 @@ namespace # endif } - - // detect_endianness -----------------------------------------------------// void detect_endianness()