From 09dcc68ecda3339d03712064655152bd4eb27571 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 30 Jan 2017 17:34:49 -0500 Subject: [PATCH 01/30] Implement constexpr addressof --- include/boost/core/addressof.hpp | 316 +++++++++++++++++++----------- test/Jamfile.v2 | 1 + test/addressof_constexpr_test.cpp | 21 ++ 3 files changed, 224 insertions(+), 114 deletions(-) create mode 100644 test/addressof_constexpr_test.cpp diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index 889b582..a308da4 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -1,162 +1,250 @@ -// Copyright (C) 2002 Brad King (brad.king@kitware.com) -// Douglas Gregor (gregod@cs.rpi.edu) -// -// Copyright (C) 2002, 2008, 2013 Peter Dimov -// -// 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) +/* +Copyright (C) 2002 Brad King (brad.king@kitware.com) + Douglas Gregor (gregod@cs.rpi.edu) -// For more information, see http://www.boost.org +Copyright (C) 2002, 2008, 2013 Peter Dimov + +Copyright (C) 2017 Glen Joseph Fernandes (glenjofe@gmail.com) + +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) +*/ #ifndef BOOST_CORE_ADDRESSOF_HPP #define BOOST_CORE_ADDRESSOF_HPP -# include -# include -# include +#include +#include +#include -namespace boost -{ +#if defined(BOOST_NO_SFINAE_EXPR) || \ + defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ + defined(BOOST_NO_CXX11_CONSTEXPR) || \ + defined(BOOST_NO_CXX11_DECLTYPE) || \ + (defined(BOOST_MSVC) && \ + BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))) +#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF +#endif -namespace detail -{ - -template struct addr_impl_ref -{ - T & v_; - - BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {} - BOOST_FORCEINLINE operator T& () const { return v_; } +namespace boost { +namespace core { +namespace detail { +template +class addressof_ref { +public: + BOOST_FORCEINLINE addressof_ref(T& o) BOOST_NOEXCEPT + : o_(o) { } + BOOST_FORCEINLINE operator T&() const BOOST_NOEXCEPT { + return o_; + } private: - addr_impl_ref & operator=(const addr_impl_ref &); + T& o_; }; -template struct addressof_impl -{ - static BOOST_FORCEINLINE T * f( T & v, long ) - { - return reinterpret_cast( - &const_cast(reinterpret_cast(v))); +template +struct address_of { + static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT { + return reinterpret_cast(& + const_cast(reinterpret_cast(o))); } - - static BOOST_FORCEINLINE T * f( T * v, int ) - { - return v; + static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT { + return p; } }; -#if !defined( BOOST_NO_CXX11_NULLPTR ) - -#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) ) - - typedef decltype(nullptr) addr_nullptr_t; - +#if !defined(BOOST_NO_CXX11_NULLPTR) +#if !defined(BOOST_NO_CXX11_DECLTYPE) && \ + (defined(__INTEL_COMPILER) || \ + (defined(__clang__) && !defined(_LIBCPP_VERSION))) +typedef decltype(nullptr) null_type; #else - - typedef std::nullptr_t addr_nullptr_t; - +typedef std::nullptr_t null_type; #endif -template<> struct addressof_impl< addr_nullptr_t > -{ - typedef addr_nullptr_t T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of { + typedef null_type type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; -template<> struct addressof_impl< addr_nullptr_t const > -{ - typedef addr_nullptr_t const T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of { + typedef const null_type type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; -template<> struct addressof_impl< addr_nullptr_t volatile > -{ - typedef addr_nullptr_t volatile T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of { + typedef volatile null_type type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; -template<> struct addressof_impl< addr_nullptr_t const volatile > -{ - typedef addr_nullptr_t const volatile T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of { + typedef const volatile null_type type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; - #endif -} // namespace detail +#if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +template +BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT +{ +#if (defined(__BORLANDC__) && \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))) || \ + (defined(__SUNPRO_CC) && \ + BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) + return address_of::get(o, 0); +#else + return address_of::get(addressof_ref(o), 0); +#endif +} +#else +template +struct add_rvalue_reference { + typedef T&& type; +}; + +template +typename add_rvalue_reference::type declval() BOOST_NOEXCEPT; + +template +struct make_void { + typedef void type; +}; + +template +struct has_member_address_operator { + static constexpr bool value = false; +}; + +template +struct has_member_address_operator().operator&())>::type> { + static constexpr bool value = true; +}; + +#if defined(BOOST_INTEL) && BOOST_WORKAROUND(BOOST_INTEL, < 1600) +struct addressable { }; + +addressable* operator&(addressable&) BOOST_NOEXCEPT; +#endif + +template +struct has_non_member_address_operator { + static constexpr bool value = false; +}; + +template +struct has_non_member_address_operator()))>::type> { + static constexpr bool value = true; +}; + +template +struct is_addressable { + static constexpr bool value = false; +}; + +template +struct is_addressable())>::type> { + static constexpr bool value = true; +}; + +template +struct has_constexpr_address { + static constexpr bool value = is_addressable::value && + !has_member_address_operator::value && + !has_non_member_address_operator::value; +}; + +template +struct address_if { }; + +template +struct address_if { + typedef T* type; +}; template BOOST_FORCEINLINE -T * addressof( T & v ) +typename address_if::value, T>::type +addressof(T& o) BOOST_NOEXCEPT { -#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || (defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) - - return boost::detail::addressof_impl::f( v, 0 ); - -#else - - return boost::detail::addressof_impl::f( boost::detail::addr_impl_ref( v ), 0 ); - -#endif + return address_of::get(addressof_ref(o), 0); } -#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) ) - -namespace detail +template +constexpr BOOST_FORCEINLINE +typename address_if::value, T>::type +addressof(T& o) BOOST_NOEXCEPT { + return &o; +} +#endif -template struct addressof_addp +} /* detail */ +} /* core */ + +template +BOOST_CONSTEXPR BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT { - typedef T * type; + return core::detail::addressof(o); +} + +#if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +#if defined(__SUNPRO_CC) && \ + BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +namespace core { +namespace detail { + +template +struct add_pointer { + typedef T* type; }; -} // namespace detail +} /* detail */ +} /* core */ -template< class T, std::size_t N > -BOOST_FORCEINLINE -typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] ) +template +BOOST_FORCEINLINE typename core::detail::add_pointer::type +addressof(T (&o)[N]) BOOST_NOEXCEPT { - return &t; -} - -#endif - -// Borland doesn't like casting an array reference to a char reference -// but these overloads work around the problem. -#if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -BOOST_FORCEINLINE -T (*addressof(T (&t)[N]))[N] -{ - return reinterpret_cast(&t); -} - -template -BOOST_FORCEINLINE -const T (*addressof(const T (&t)[N]))[N] -{ - return reinterpret_cast(&t); + return &o; } #endif -} // namespace boost +#if defined(__BORLANDC__) && \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template +BOOST_FORCEINLINE +T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N] +{ + return reinterpret_cast(&o); +} -#endif // BOOST_CORE_ADDRESSOF_HPP +template +BOOST_FORCEINLINE +const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] +{ + return reinterpret_cast(&o); +} +#endif +#endif + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f40577d..64cde15 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -13,6 +13,7 @@ run addressof_test.cpp ; run addressof_test2.cpp ; run addressof_np_test.cpp ; run addressof_fn_test.cpp ; +compile addressof_constexpr_test.cpp ; run checked_delete_test.cpp ; compile-fail checked_delete_fail.cpp ; diff --git a/test/addressof_constexpr_test.cpp b/test/addressof_constexpr_test.cpp new file mode 100644 index 0000000..9d93565 --- /dev/null +++ b/test/addressof_constexpr_test.cpp @@ -0,0 +1,21 @@ +/* +Copyright 2017 Glen Joseph Fernandes + + +Distributed under the Boost Software +License, Version 1.0. +http://boost.org/LICENSE_1_0.txt +*/ + +#include +#include + +#if !defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +struct Type { }; + +static int v1 = 0; +static Type v2 = { }; + +BOOST_STATIC_ASSERT(boost::addressof(v1) == &v1); +BOOST_STATIC_ASSERT(boost::addressof(v2) == &v2); +#endif From 3d98e6aed462a448268971c7bc01f2c08c12b727 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 31 Jan 2017 19:29:53 -0500 Subject: [PATCH 02/30] Use __builtin_addressof when available --- include/boost/core/addressof.hpp | 273 +++++++++++++++++-------------- 1 file changed, 149 insertions(+), 124 deletions(-) diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index a308da4..7dda247 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -15,20 +15,33 @@ http://www.boost.org/LICENSE_1_0.txt) #define BOOST_CORE_ADDRESSOF_HPP #include + +#if BOOST_MSVC_FULL_VER >= 190024215 +#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF +#elif BOOST_GCC >= 70000 +#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF +#elif defined(__has_builtin) +#if __has_builtin(__builtin_addressof) +#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF +#endif +#endif + +#if defined(BOOST_CORE_HAS_BUILTIN_ADDRESSOF) +namespace boost { + +template +BOOST_CONSTEXPR inline T* +addressof(T& o) BOOST_NOEXCEPT +{ + return __builtin_addressof(o); +} + +} /* boost */ +#else #include #include -#if defined(BOOST_NO_SFINAE_EXPR) || \ - defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ - defined(BOOST_NO_CXX11_CONSTEXPR) || \ - defined(BOOST_NO_CXX11_DECLTYPE) || \ - (defined(BOOST_MSVC) && \ - BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))) -#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF -#endif - namespace boost { -namespace core { namespace detail { template @@ -46,8 +59,8 @@ private: template struct address_of { static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT { - return reinterpret_cast(& - const_cast(reinterpret_cast(o))); + return reinterpret_cast(&const_cast< + char&>(reinterpret_cast(o))); } static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT { return p; @@ -58,45 +71,54 @@ struct address_of { #if !defined(BOOST_NO_CXX11_DECLTYPE) && \ (defined(__INTEL_COMPILER) || \ (defined(__clang__) && !defined(_LIBCPP_VERSION))) -typedef decltype(nullptr) null_type; +typedef decltype(nullptr) addressof_null_t; #else -typedef std::nullptr_t null_type; +typedef std::nullptr_t addressof_null_t; #endif template<> -struct address_of { - typedef null_type type; +struct address_of { + typedef addressof_null_t type; static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { return &o; } }; template<> -struct address_of { - typedef const null_type type; +struct address_of { + typedef const addressof_null_t type; static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { return &o; } }; template<> -struct address_of { - typedef volatile null_type type; +struct address_of { + typedef volatile addressof_null_t type; static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { return &o; } }; template<> -struct address_of { - typedef const volatile null_type type; +struct address_of { + typedef const volatile addressof_null_t type; static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { return &o; } }; #endif -#if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +} /* detail */ + +#if defined(BOOST_NO_SFINAE_EXPR) || \ + defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ + defined(BOOST_NO_CXX11_CONSTEXPR) || \ + defined(BOOST_NO_CXX11_DECLTYPE) || \ + (defined(BOOST_MSVC) && \ + BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))) +#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF + template BOOST_FORCEINLINE T* addressof(T& o) BOOST_NOEXCEPT @@ -105,122 +127,25 @@ addressof(T& o) BOOST_NOEXCEPT BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))) || \ (defined(__SUNPRO_CC) && \ BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) - return address_of::get(o, 0); + return detail::address_of::get(o, 0); #else - return address_of::get(addressof_ref(o), 0); + return detail::address_of::get(detail::addressof_ref(o), 0); #endif } -#else -template -struct add_rvalue_reference { - typedef T&& type; -}; -template -typename add_rvalue_reference::type declval() BOOST_NOEXCEPT; - -template -struct make_void { - typedef void type; -}; - -template -struct has_member_address_operator { - static constexpr bool value = false; -}; - -template -struct has_member_address_operator().operator&())>::type> { - static constexpr bool value = true; -}; - -#if defined(BOOST_INTEL) && BOOST_WORKAROUND(BOOST_INTEL, < 1600) -struct addressable { }; - -addressable* operator&(addressable&) BOOST_NOEXCEPT; -#endif - -template -struct has_non_member_address_operator { - static constexpr bool value = false; -}; - -template -struct has_non_member_address_operator()))>::type> { - static constexpr bool value = true; -}; - -template -struct is_addressable { - static constexpr bool value = false; -}; - -template -struct is_addressable())>::type> { - static constexpr bool value = true; -}; - -template -struct has_constexpr_address { - static constexpr bool value = is_addressable::value && - !has_member_address_operator::value && - !has_non_member_address_operator::value; -}; - -template -struct address_if { }; - -template -struct address_if { - typedef T* type; -}; - -template -BOOST_FORCEINLINE -typename address_if::value, T>::type -addressof(T& o) BOOST_NOEXCEPT -{ - return address_of::get(addressof_ref(o), 0); -} - -template -constexpr BOOST_FORCEINLINE -typename address_if::value, T>::type -addressof(T& o) BOOST_NOEXCEPT -{ - return &o; -} -#endif - -} /* detail */ -} /* core */ - -template -BOOST_CONSTEXPR BOOST_FORCEINLINE T* -addressof(T& o) BOOST_NOEXCEPT -{ - return core::detail::addressof(o); -} - -#if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) #if defined(__SUNPRO_CC) && \ BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) -namespace core { namespace detail { template -struct add_pointer { +struct addressof_result { typedef T* type; }; } /* detail */ -} /* core */ template -BOOST_FORCEINLINE typename core::detail::add_pointer::type +BOOST_FORCEINLINE typename detail::addressof_result::type addressof(T (&o)[N]) BOOST_NOEXCEPT { return &o; @@ -243,8 +168,108 @@ const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] return reinterpret_cast(&o); } #endif +#else +namespace detail { + +template +struct addressof_rvalue { + typedef T&& type; +}; + +template +typename addressof_rvalue::type +addressof_declval() BOOST_NOEXCEPT; + +template +struct addressof_make_void { + typedef void type; +}; + +template +struct addressof_member_operator { + static constexpr bool value = false; +}; + +template +struct addressof_member_operator().operator&())>::type> { + static constexpr bool value = true; +}; + +#if defined(BOOST_INTEL) && BOOST_WORKAROUND(BOOST_INTEL, < 1600) +struct addressof_addressable { }; + +addressof_addressable* +operator&(addressof_addressable&) BOOST_NOEXCEPT; +#endif + +template +struct addressof_non_member_operator { + static constexpr bool value = false; +}; + +template +struct addressof_non_member_operator()))>::type> { + static constexpr bool value = true; +}; + +template +struct addressof_expression { + static constexpr bool value = false; +}; + +template +struct addressof_expression())>::type> { + static constexpr bool value = true; +}; + +template +struct addressof_is_constexpr { + static constexpr bool value = addressof_expression::value && + !addressof_member_operator::value && + !addressof_non_member_operator::value; +}; + +template +struct addressof_if { }; + +template +struct addressof_if { + typedef T* type; +}; + +template +BOOST_FORCEINLINE +typename addressof_if::value, T>::type +addressof(T& o) BOOST_NOEXCEPT +{ + return address_of::get(addressof_ref(o), 0); +} + +template +constexpr BOOST_FORCEINLINE +typename addressof_if::value, T>::type +addressof(T& o) BOOST_NOEXCEPT +{ + return &o; +} + +} /* detail */ + +template +constexpr BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT +{ + return detail::addressof(o); +} #endif } /* boost */ +#endif #endif From 686dbcb8eb7cd5b237a073fe10b05711bbc62a14 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 1 Feb 2017 08:34:03 -0500 Subject: [PATCH 03/30] No BOOST_WORKAROUND for MSVC as >1900 has builtin --- include/boost/core/addressof.hpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index 7dda247..6f7638d 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -59,8 +59,8 @@ private: template struct address_of { static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT { - return reinterpret_cast(&const_cast< - char&>(reinterpret_cast(o))); + return reinterpret_cast(& + const_cast(reinterpret_cast(o))); } static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT { return p; @@ -115,8 +115,7 @@ struct address_of { defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ defined(BOOST_NO_CXX11_CONSTEXPR) || \ defined(BOOST_NO_CXX11_DECLTYPE) || \ - (defined(BOOST_MSVC) && \ - BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))) + defined(BOOST_MSVC_FULL_VER) #define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF template @@ -181,7 +180,7 @@ typename addressof_rvalue::type addressof_declval() BOOST_NOEXCEPT; template -struct addressof_make_void { +struct addressof_void { typedef void type; }; @@ -191,9 +190,8 @@ struct addressof_member_operator { }; template -struct addressof_member_operator().operator&())>::type> { +struct addressof_member_operator().operator&())>::type> { static constexpr bool value = true; }; @@ -210,9 +208,8 @@ struct addressof_non_member_operator { }; template -struct addressof_non_member_operator()))>::type> { +struct addressof_non_member_operator()))>::type> { static constexpr bool value = true; }; @@ -223,8 +220,7 @@ struct addressof_expression { template struct addressof_expression())>::type> { + typename addressof_void())>::type> { static constexpr bool value = true; }; From 4016f8e7cc7f992155caf97a4bb21cd81552a7b6 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 1 Feb 2017 11:02:01 -0500 Subject: [PATCH 04/30] Define CORE_NO_CONSTEXPR_ADDRESSOF if NO_CXX11_CONSTEXPR is defined The test case could check for BOOST_NO_CXX11_CONSTEXPR but it makes sense for BOOST_CORE_NO_CONSTEXPR_ADDRESSOF to be defined in this case also. --- include/boost/core/addressof.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index 6f7638d..b40afed 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -27,6 +27,10 @@ http://www.boost.org/LICENSE_1_0.txt) #endif #if defined(BOOST_CORE_HAS_BUILTIN_ADDRESSOF) +#if defined(BOOST_NO_CXX11_CONSTEXPR) +#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF +#endif + namespace boost { template From 55b27867708e8269a92c7dd889daffe48fb3c77a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 2 Feb 2017 18:40:06 +0200 Subject: [PATCH 05/30] Add ref_cv_test --- test/Jamfile.v2 | 1 + test/ref_cv_test.cpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 test/ref_cv_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 64cde15..f93ff51 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -30,6 +30,7 @@ compile-fail ref_rv_fail4.cpp ; compile-fail ref_rv_fail5.cpp ; compile-fail ref_implicit_fail.cpp ; compile-fail ref_implicit_fail2.cpp ; +run ref_cv_test.cpp ; run eif_constructors.cpp ; run eif_dummy_arg_disambiguation.cpp ; diff --git a/test/ref_cv_test.cpp b/test/ref_cv_test.cpp new file mode 100644 index 0000000..734d9b3 --- /dev/null +++ b/test/ref_cv_test.cpp @@ -0,0 +1,35 @@ +// ref_cv_test.cpp: ref( x ) where x is of a cv-qualified type +// +// Copyright (c) 2017 Peter Dimov +// +// 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 + +#include +#include + +#define BOOST_TEST_REF( x ) BOOST_TEST( &boost::ref( x ).get() == &x ) +#define BOOST_TEST_CREF( x ) BOOST_TEST( &boost::cref( x ).get() == &x ) + +int main() +{ + int x1 = 1; + int const x2 = 2; + int volatile x3 = 3; + int const volatile x4 = 4; + + BOOST_TEST_REF( x1 ); + BOOST_TEST_CREF( x1 ); + + BOOST_TEST_REF( x2 ); + BOOST_TEST_CREF( x2 ); + + BOOST_TEST_REF( x3 ); + BOOST_TEST_CREF( x3 ); + + BOOST_TEST_REF( x4 ); + BOOST_TEST_CREF( x4 ); + + return boost::report_errors(); +} From b0a58a16e230d8ff5adf85b599458823debdb611 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 2 Feb 2017 20:01:02 +0200 Subject: [PATCH 06/30] Add g++4.7-c++11, g++4.8-c++11, g++5-c++14 to .travis.yml --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index a74c257..07def3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,9 +49,15 @@ matrix: - os: linux env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++03 + - os: linux + env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++11 + - os: linux env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++03 + - os: linux + env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++11 + - os: linux env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++03 @@ -64,6 +70,9 @@ matrix: - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++11 + - os: linux + env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 + - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 From 9587d6b84585f2934f4ae3493e6075534f7488aa Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 2 Feb 2017 13:42:42 -0500 Subject: [PATCH 07/30] Support g++4.7 with SFINAE workaround --- include/boost/core/addressof.hpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index b40afed..70db5a9 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -6,8 +6,8 @@ Copyright (C) 2002, 2008, 2013 Peter Dimov Copyright (C) 2017 Glen Joseph Fernandes (glenjofe@gmail.com) -Distributed under the Boost Software License, Version 1.0. (See -accompanying file LICENSE_1_0.txt or copy at +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) */ @@ -57,6 +57,7 @@ public: return o_; } private: + addressof_ref& operator=(const addressof_ref&); T& o_; }; @@ -119,25 +120,22 @@ struct address_of { defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ defined(BOOST_NO_CXX11_CONSTEXPR) || \ defined(BOOST_NO_CXX11_DECLTYPE) || \ - defined(BOOST_MSVC_FULL_VER) + BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, < 190024215) #define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF template BOOST_FORCEINLINE T* addressof(T& o) BOOST_NOEXCEPT { -#if (defined(__BORLANDC__) && \ - BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))) || \ - (defined(__SUNPRO_CC) && \ - BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) || \ + BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120) return detail::address_of::get(o, 0); #else return detail::address_of::get(detail::addressof_ref(o), 0); #endif } -#if defined(__SUNPRO_CC) && \ - BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) namespace detail { template @@ -155,8 +153,7 @@ addressof(T (&o)[N]) BOOST_NOEXCEPT } #endif -#if defined(__BORLANDC__) && \ - BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) template BOOST_FORCEINLINE T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N] @@ -199,7 +196,9 @@ struct addressof_member_operator Date: Thu, 2 Feb 2017 21:44:14 -0500 Subject: [PATCH 08/30] Exclude g++4.7 from constexpr implementation --- include/boost/core/addressof.hpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index 70db5a9..303bd0c 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -16,9 +16,9 @@ http://www.boost.org/LICENSE_1_0.txt) #include -#if BOOST_MSVC_FULL_VER >= 190024215 +#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215 #define BOOST_CORE_HAS_BUILTIN_ADDRESSOF -#elif BOOST_GCC >= 70000 +#elif defined(BOOST_GCC) && BOOST_GCC >= 70000 #define BOOST_CORE_HAS_BUILTIN_ADDRESSOF #elif defined(__has_builtin) #if __has_builtin(__builtin_addressof) @@ -120,7 +120,8 @@ struct address_of { defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ defined(BOOST_NO_CXX11_CONSTEXPR) || \ defined(BOOST_NO_CXX11_DECLTYPE) || \ - BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, < 190024215) + BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900)) || \ + BOOST_WORKAROUND(BOOST_GCC, < 40800) #define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF template @@ -172,13 +173,7 @@ const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] namespace detail { template -struct addressof_rvalue { - typedef T&& type; -}; - -template -typename addressof_rvalue::type -addressof_declval() BOOST_NOEXCEPT; +T&& addressof_declval() BOOST_NOEXCEPT; template struct addressof_void { @@ -196,9 +191,7 @@ struct addressof_member_operator Date: Sun, 5 Feb 2017 19:06:21 +0000 Subject: [PATCH 09/30] fix for trac issue #12814, including a new test for the issue --- include/boost/core/lightweight_test.hpp | 37 +++++++++++++++++++++++++ test/lightweight_test_test.cpp | 5 ++++ 2 files changed, 42 insertions(+) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index d6db024..e084b35 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -23,6 +23,7 @@ #include #include #include +#include // IDE's like Visual Studio perform better if output goes to std::cout or // some other stream, so allow user to configure output stream: @@ -118,6 +119,24 @@ template inline void test_eq_impl( char const * expr1, char co } } +// overload for const char* +inline void test_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* t, const char* u ) +{ + if( std::strcmp(t, u) == 0 ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << t << "' != '" << u << "'" << std::endl; + ++test_errors(); + } +} + template inline void test_ne_impl( char const * expr1, char const * expr2, char const * file, int line, char const * function, T const & t, U const & u ) { @@ -135,6 +154,24 @@ template inline void test_ne_impl( char const * expr1, char co } } +// overload for const char* +inline void test_ne_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* t, const char* u ) +{ + if( std::strcmp(t, u) != 0 ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << t << "' == '" << u << "'" << std::endl; + ++test_errors(); + } +} + #if defined(_MSC_VER) # pragma warning(pop) #elif defined(__clang__) && defined(__has_warning) diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index d4808a1..be87950 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -65,10 +65,15 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); + const char* s1 = "abc"; // make sure addresses are different + const char* s2 = "abc"; // make sure addresses are different + BOOST_TEST_EQ(s1, s2); + // BOOST_TEST_NE BOOST_TEST_NE( ++x, y ); BOOST_TEST_NE( &x, &y ); + BOOST_TEST_NE( "abc", "ABC" ); // BOOST_TEST_THROWS From 7774d33e45a774c0c5659da550790d7705cf5862 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Sun, 5 Feb 2017 19:24:15 +0000 Subject: [PATCH 10/30] really make sure addresses are different --- test/lightweight_test_test.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index be87950..a38d9d2 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -65,9 +65,7 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); - const char* s1 = "abc"; // make sure addresses are different - const char* s2 = "abc"; // make sure addresses are different - BOOST_TEST_EQ(s1, s2); + BOOST_TEST_EQ("abc", "xxxabc"+3); // make sure addresses are different // BOOST_TEST_NE From 3942e9c0974e8435b6d12de4fe2695e691423ab1 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Sun, 5 Feb 2017 20:01:47 +0000 Subject: [PATCH 11/30] following pdimovs suggestion to avoid folding --- test/lightweight_test_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index a38d9d2..a2c5971 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -65,7 +65,7 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); - BOOST_TEST_EQ("abc", "xxxabc"+3); // make sure addresses are different + BOOST_TEST_EQ("xabc"+1, "yabc"+1); // make sure addresses are different // BOOST_TEST_NE From 98ee47effd627f57fe205862f092bd793e4836d6 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Feb 2017 08:14:36 -0500 Subject: [PATCH 12/30] Use new BOOST_NO_CXX11_SFINAE_EXPR feature macro --- include/boost/core/addressof.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index 303bd0c..0a2b46b 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -116,12 +116,10 @@ struct address_of { } /* detail */ -#if defined(BOOST_NO_SFINAE_EXPR) || \ +#if defined(BOOST_NO_CXX11_SFINAE_EXPR) || \ defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ defined(BOOST_NO_CXX11_CONSTEXPR) || \ - defined(BOOST_NO_CXX11_DECLTYPE) || \ - BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900)) || \ - BOOST_WORKAROUND(BOOST_GCC, < 40800) + defined(BOOST_NO_CXX11_DECLTYPE) #define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF template From cc5472623f05ca8c37b7aea14687c8393efcd92a Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Mon, 6 Feb 2017 20:08:43 +0000 Subject: [PATCH 13/30] compare pointers as addresses and use BOOST_TEST_CSTR_xx to compare cstrings --- include/boost/core/lightweight_test.hpp | 51 ++++++++++++++++++++++--- test/lightweight_test_test.cpp | 7 ++-- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index e084b35..2608582 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -119,9 +119,27 @@ template inline void test_eq_impl( char const * expr1, char co } } -// overload for const char* -inline void test_eq_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* t, const char* u ) +// overloads for pointers compare and print addresses +template inline void test_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const T* const t, const U* const u ) +{ + if( t == u ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << (const void*)t << "' != '" << (const void*)u << "'" << std::endl; + ++test_errors(); + } +} + +// impl for cstring +inline void test_cstr_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* const t, const char* const u ) { if( std::strcmp(t, u) == 0 ) { @@ -154,9 +172,27 @@ template inline void test_ne_impl( char const * expr1, char co } } -// overload for const char* -inline void test_ne_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* t, const char* u ) +// overloads for pointers compare and print addresses +template inline void test_ne_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const T* const t, const U* const u ) +{ + if( t != u ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << (const void*)t << "' == '" << (const void*)u << "'" << std::endl; + ++test_errors(); + } +} + +// impl for cstring +inline void test_cstr_ne_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* const t, const char* const u ) { if( std::strcmp(t, u) != 0 ) { @@ -214,6 +250,9 @@ inline int report_errors() #define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) #define BOOST_TEST_NE(expr1,expr2) ( ::boost::detail::test_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) +#define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) +#define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) + #ifndef BOOST_NO_EXCEPTIONS #define BOOST_TEST_THROWS( EXPR, EXCEP ) \ try { \ diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index a2c5971..a3b04a9 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -64,14 +64,15 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); - - BOOST_TEST_EQ("xabc"+1, "yabc"+1); // make sure addresses are different + BOOST_TEST_CSTR_EQ("xabc"+1, "yabc"+1); // equal cstrings, different addresses + BOOST_TEST_EQ( &y, &y ); // BOOST_TEST_NE BOOST_TEST_NE( ++x, y ); BOOST_TEST_NE( &x, &y ); - BOOST_TEST_NE( "abc", "ABC" ); + BOOST_TEST_NE("xabc"+1, "yabc"+1); // equal cstrings, different addresses + BOOST_TEST_CSTR_NE("x", "y"); // BOOST_TEST_THROWS From a44090aebec04ed1f67ebda93fba3d55ac07004b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 7 Feb 2017 01:52:59 +0200 Subject: [PATCH 14/30] Only install necessary packages in .travis.yml to speed it up --- .travis.yml | 155 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 07def3a..f7a3095 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,24 +19,6 @@ env: matrix: - BOGUS_JOB=true -addons: - apt: - packages: - - g++-4.7 - - g++-4.8 - - g++-4.9 - - g++-5 - - g++-6 - - clang-3.6 - - clang-3.7 - - clang-3.8 - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise - - llvm-toolchain-precise-3.6 - - llvm-toolchain-precise-3.7 - - llvm-toolchain-precise-3.8 - matrix: exclude: @@ -48,69 +30,206 @@ matrix: - os: linux env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++03 + addons: + apt: + packages: + - g++-4.7 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++11 + addons: + apt: + packages: + - g++-4.7 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++03 + addons: + apt: + packages: + - g++-4.8 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++11 + addons: + apt: + packages: + - g++-4.8 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++03 + addons: + apt: + packages: + - g++-4.9 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++11 + addons: + apt: + packages: + - g++-4.9 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++03 + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++11 + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test - os: linux env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++03 + - os: linux + env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11 + - os: linux env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++03 + addons: + apt: + packages: + - clang-3.6 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 - os: linux env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++11 + addons: + apt: + packages: + - clang-3.6 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 - os: linux env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++03 + addons: + apt: + packages: + - clang-3.7 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 - os: linux env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++11 + addons: + apt: + packages: + - clang-3.7 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 - os: linux env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++03 + addons: + apt: + packages: + - clang-3.8 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 - os: linux env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++11 + addons: + apt: + packages: + - clang-3.8 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 - os: linux env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++14 + addons: + apt: + packages: + - clang-3.8 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 - os: linux env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++1z + addons: + apt: + packages: + - clang-3.8 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 - os: osx env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++03 From 4570cced275ae36261634a4a23d1fb66873b124e Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Tue, 7 Feb 2017 15:05:08 +0000 Subject: [PATCH 15/30] more compared code following suggestion from Glen Fernandes and testing expected failures --- include/boost/core/lightweight_test.hpp | 58 ++++++------------------- test/Jamfile.v2 | 2 + test/lightweight_test_fail10.cpp | 18 ++++++++ test/lightweight_test_fail9.cpp | 18 ++++++++ 4 files changed, 51 insertions(+), 45 deletions(-) create mode 100644 test/lightweight_test_fail10.cpp create mode 100644 test/lightweight_test_fail9.cpp diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 2608582..804c8f4 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -102,6 +102,12 @@ inline void throw_failed_impl(char const * excep, char const * file, int line, c # pragma GCC diagnostic ignored "-Wsign-compare" #endif +// specialize test output for char pointers to avoid printing as cstring +template inline const T& test_output_impl(const T& v) { return v; } +inline const void* test_output_impl(const char* v) { return v; } +inline const void* test_output_impl(const unsigned char* v) { return v; } +inline const void* test_output_impl(const signed char* v) { return v; } + template inline void test_eq_impl( char const * expr1, char const * expr2, char const * file, int line, char const * function, T const & t, U const & u ) { @@ -114,43 +120,7 @@ template inline void test_eq_impl( char const * expr1, char co BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' failed in function '" << function << "': " - << "'" << t << "' != '" << u << "'" << std::endl; - ++test_errors(); - } -} - -// overloads for pointers compare and print addresses -template inline void test_eq_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const T* const t, const U* const u ) -{ - if( t == u ) - { - report_errors_remind(); - } - else - { - BOOST_LIGHTWEIGHT_TEST_OSTREAM - << file << "(" << line << "): test '" << expr1 << " == " << expr2 - << "' failed in function '" << function << "': " - << "'" << (const void*)t << "' != '" << (const void*)u << "'" << std::endl; - ++test_errors(); - } -} - -// impl for cstring -inline void test_cstr_eq_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* const t, const char* const u ) -{ - if( std::strcmp(t, u) == 0 ) - { - report_errors_remind(); - } - else - { - BOOST_LIGHTWEIGHT_TEST_OSTREAM - << file << "(" << line << "): test '" << expr1 << " == " << expr2 - << "' failed in function '" << function << "': " - << "'" << t << "' != '" << u << "'" << std::endl; + << "'" << test_output_impl(t) << "' != '" << test_output_impl(u) << "'" << std::endl; ++test_errors(); } } @@ -167,16 +137,15 @@ template inline void test_ne_impl( char const * expr1, char co BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test '" << expr1 << " != " << expr2 << "' failed in function '" << function << "': " - << "'" << t << "' == '" << u << "'" << std::endl; + << "'" << test_output_impl(t) << "' == '" << test_output_impl(u) << "'" << std::endl; ++test_errors(); } } -// overloads for pointers compare and print addresses -template inline void test_ne_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const T* const t, const U* const u ) +inline void test_cstr_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, char const * const t, char const * const u ) { - if( t != u ) + if( std::strcmp(t, u) == 0 ) { report_errors_remind(); } @@ -185,14 +154,13 @@ template inline void test_ne_impl( char const * expr1, char co BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' failed in function '" << function << "': " - << "'" << (const void*)t << "' == '" << (const void*)u << "'" << std::endl; + << "'" << t << "' != '" << u << "'" << std::endl; ++test_errors(); } } -// impl for cstring inline void test_cstr_ne_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* const t, const char* const u ) + char const * file, int line, char const * function, char const * const t, char const * const u ) { if( std::strcmp(t, u) != 0 ) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f93ff51..31ba00f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -76,6 +76,8 @@ run-fail lightweight_test_fail7.cpp ; run-fail lightweight_test_fail7.cpp : : : off : lightweight_test_fail7_no_rtti ; run-fail lightweight_test_fail8.cpp ; run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; +run-fail lightweight_test_fail9.cpp ; +run-fail lightweight_test_fail10.cpp ; run is_same_test.cpp ; diff --git a/test/lightweight_test_fail10.cpp b/test/lightweight_test_fail10.cpp new file mode 100644 index 0000000..388c47e --- /dev/null +++ b/test/lightweight_test_fail10.cpp @@ -0,0 +1,18 @@ +// +// Negative test for BOOST_TEST_EQ on const char* +// +// Copyright (c) 2017 Hans Dembinski +// +// 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 +// + +#include + +int main() +{ + BOOST_TEST_EQ("xab"+1 , "yab"+1); // compares addresses, not cstrings + + return boost::report_errors(); +} diff --git a/test/lightweight_test_fail9.cpp b/test/lightweight_test_fail9.cpp new file mode 100644 index 0000000..a87a4f1 --- /dev/null +++ b/test/lightweight_test_fail9.cpp @@ -0,0 +1,18 @@ +// +// Negative test for BOOST_TEST_CSTR_EQ +// +// Copyright (c) 2017 Hans Dembinski +// +// 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 +// + +#include + +int main() +{ + BOOST_TEST_CSTR_EQ("x" , "y"); + + return boost::report_errors(); +} From 7038296c157b6e5a284b6eb944275eb1b025943f Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Thu, 9 Feb 2017 12:47:47 +0000 Subject: [PATCH 16/30] build fix --- doc/Jamfile.v2 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index f598bb7..bdba059 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -5,8 +5,9 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://boost.org/LICENSE_1_0.txt) -import doxygen ; -import quickbook ; +using boostbook ; +using doxygen ; +using quickbook ; doxygen ref_reference : From fe137b97c3ed63ea25f3b9e112cf6fe71b24ab11 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Thu, 9 Feb 2017 12:48:06 +0000 Subject: [PATCH 17/30] adding documentation for new test macros --- doc/lightweight_test.qbk | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index 4b9abd1..c7ef180 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -36,6 +36,8 @@ When using `lightweight_test.hpp`, *do not forget* to #define BOOST_ERROR(message) /*unspecified*/ #define BOOST_TEST_EQ(expr1, expr2) /*unspecified*/ #define BOOST_TEST_NE(expr1, expr2) /*unspecified*/ +#define BOOST_TEST_CSTR_EQ(expr1, expr2) /*unspecified*/ +#define BOOST_TEST_CSTR_NE(expr1, expr2) /*unspecified*/ #define BOOST_TEST_THROWS(expr, excep) /*unspecified*/ namespace boost @@ -101,6 +103,26 @@ message containing both expressions. [endsect] +[section BOOST_TEST_CSTR_EQ] + +`` +BOOST_TEST_CSTR_EQ(expr1, expr2) +`` + +Specialization of BOOST_TEST_EQ which interprets expr1 and expr2 as pointers to null-terminated byte strings (C strings). If `std::strcmp(expr1, expr2) != 0`, increase the error count and output a message containing both expressions. + +[endsect] + +[section BOOST_TEST_CSTR_NE] + +`` +BOOST_TEST_CSTR_NE(expr1, expr2) +`` + +Specialization of BOOST_TEST_NE which interprets expr1 and expr2 as pointers to null-terminated byte strings (C strings). If `std::strcmp(expr1, expr2) == 0`, increase the error count and output a message containing both expressions. + +[endsect] + [section BOOST_TEST_THROWS] `` From b59a3df4c4c7d50003be2dc8126c602649f82c3d Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Thu, 9 Feb 2017 13:52:33 +0000 Subject: [PATCH 18/30] reverting changes to jamfile --- doc/Jamfile.v2 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index bdba059..f598bb7 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -5,9 +5,8 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://boost.org/LICENSE_1_0.txt) -using boostbook ; -using doxygen ; -using quickbook ; +import doxygen ; +import quickbook ; doxygen ref_reference : From 9dd5285dbbf459b8a78580571fd8a782bf307280 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Feb 2017 23:14:07 +0200 Subject: [PATCH 19/30] Handle char*, volatile* properly in BOOST_TEST_EQ/NE --- include/boost/core/lightweight_test.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 804c8f4..d1766a4 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -107,6 +107,10 @@ template inline const T& test_output_impl(const T& v) { return v; } inline const void* test_output_impl(const char* v) { return v; } inline const void* test_output_impl(const unsigned char* v) { return v; } inline const void* test_output_impl(const signed char* v) { return v; } +inline const void* test_output_impl(char* v) { return v; } +inline const void* test_output_impl(unsigned char* v) { return v; } +inline const void* test_output_impl(signed char* v) { return v; } +template inline const void* test_output_impl(T volatile* v) { return const_cast(v); } template inline void test_eq_impl( char const * expr1, char const * expr2, char const * file, int line, char const * function, T const & t, U const & u ) From 3bc56800cdda6bcec8b0514cac1d7939f0c74472 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sat, 11 Feb 2017 15:03:45 +0100 Subject: [PATCH 20/30] Added BOOST_TEST_ALL_EQ macro to compare container contents --- doc/lightweight_test.qbk | 9 ++++++ include/boost/core/lightweight_test.hpp | 41 +++++++++++++++++++++++++ test/lightweight_test_test.cpp | 10 ++++++ 3 files changed, 60 insertions(+) diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index c7ef180..c3ab7bc 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -38,6 +38,7 @@ When using `lightweight_test.hpp`, *do not forget* to #define BOOST_TEST_NE(expr1, expr2) /*unspecified*/ #define BOOST_TEST_CSTR_EQ(expr1, expr2) /*unspecified*/ #define BOOST_TEST_CSTR_NE(expr1, expr2) /*unspecified*/ +#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) /* unspecified */ #define BOOST_TEST_THROWS(expr, excep) /*unspecified*/ namespace boost @@ -121,6 +122,14 @@ BOOST_TEST_CSTR_NE(expr1, expr2) Specialization of BOOST_TEST_NE which interprets expr1 and expr2 as pointers to null-terminated byte strings (C strings). If `std::strcmp(expr1, expr2) == 0`, increase the error count and output a message containing both expressions. +[section BOOST_TEST_ALL_EQ] + +`` +BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) +`` + +Compares the content of two containers. If they have different sizes, or if any pairwise element differs, increases the error count and outputs a message containing all differing elements. + [endsect] [section BOOST_TEST_THROWS] diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index d1766a4..d8a316e 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -19,6 +19,8 @@ // http://www.boost.org/LICENSE_1_0.txt // +#include +#include #include #include #include @@ -180,6 +182,43 @@ inline void test_cstr_ne_impl( char const * expr1, char const * expr2, } } +template +void test_all_eq_impl(char const * file, int line, char const * function, + FwdIt1 first_begin, FwdIt1 first_end, + FwdIt2 second_begin, FwdIt2 second_end) +{ + if (std::distance(first_begin, first_end) != std::distance(second_begin, second_end)) + { + ::boost::detail::error_impl("Container sizes are different", __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); + } + else + { + FwdIt1 first_it = first_begin; + FwdIt2 second_it = second_begin; + std::ostringstream indices; + do + { + while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) + { + ++first_it; + ++second_it; + } + if (first_it == first_end) + { + boost::detail::report_errors_remind(); + return; + } + indices << " [" << std::distance(first_begin, first_it) << "] '" << *first_it << "' != '" << *second_it << "'"; + ++first_it; + ++second_it; + } while (first_it != first_end); + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): Container contents differ in function '" << function << "': mismatching indices" + << indices.str() << std::endl; + ++boost::detail::test_errors(); + } +} + #if defined(_MSC_VER) # pragma warning(pop) #elif defined(__clang__) && defined(__has_warning) @@ -225,6 +264,8 @@ inline int report_errors() #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) +#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) ) + #ifndef BOOST_NO_EXCEPTIONS #define BOOST_TEST_THROWS( EXPR, EXCEP ) \ try { \ diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index a3b04a9..bfef152 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -8,6 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // +#include #include struct X @@ -74,6 +75,15 @@ int main() BOOST_TEST_NE("xabc"+1, "yabc"+1); // equal cstrings, different addresses BOOST_TEST_CSTR_NE("x", "y"); + // BOOST_TEST_ALL_EQ + { + std::vector xarray; + xarray.push_back(1); + xarray.push_back(2); + std::vector yarray(xarray); + BOOST_TEST_ALL_EQ(xarray.begin(), xarray.end(), yarray.begin(), yarray.end()); + } + // BOOST_TEST_THROWS BOOST_TEST_THROWS( throw X(), X ); From 6a5f540f08e1aec51c8a6464046cfe5ab8fa77af Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sat, 11 Feb 2017 16:37:12 +0100 Subject: [PATCH 21/30] Removed std::ostringstream --- include/boost/core/lightweight_test.hpp | 29 ++++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index d8a316e..5e0ef5c 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -20,7 +20,6 @@ // #include -#include #include #include #include @@ -182,10 +181,11 @@ inline void test_cstr_ne_impl( char const * expr1, char const * expr2, } } -template -void test_all_eq_impl(char const * file, int line, char const * function, - FwdIt1 first_begin, FwdIt1 first_end, - FwdIt2 second_begin, FwdIt2 second_end) +template +void test_all_eq_impl(FormattedOutputFunction& output, + char const * file, int line, char const * function, + ForwardIterator1 first_begin, ForwardIterator1 first_end, + ForwardIterator2 second_begin, ForwardIterator2 second_end) { if (std::distance(first_begin, first_end) != std::distance(second_begin, second_end)) { @@ -193,9 +193,9 @@ void test_all_eq_impl(char const * file, int line, char const * function, } else { - FwdIt1 first_it = first_begin; - FwdIt2 second_it = second_begin; - std::ostringstream indices; + ForwardIterator1 first_it = first_begin; + ForwardIterator2 second_it = second_begin; + bool first_iteration = true; do { while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) @@ -208,13 +208,16 @@ void test_all_eq_impl(char const * file, int line, char const * function, boost::detail::report_errors_remind(); return; } - indices << " [" << std::distance(first_begin, first_it) << "] '" << *first_it << "' != '" << *second_it << "'"; + if (first_iteration) + { + first_iteration = true; + output << file << "(" << line << "): Container contents differ in function '" << function << "': mismatching indices"; + } + output << " [" << std::distance(first_begin, first_it) << "] '" << *first_it << "' != '" << *second_it << "'"; ++first_it; ++second_it; } while (first_it != first_end); - BOOST_LIGHTWEIGHT_TEST_OSTREAM - << file << "(" << line << "): Container contents differ in function '" << function << "': mismatching indices" - << indices.str() << std::endl; + output << std::endl; ++boost::detail::test_errors(); } } @@ -264,7 +267,7 @@ inline int report_errors() #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) -#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) ) +#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) ) #ifndef BOOST_NO_EXCEPTIONS #define BOOST_TEST_THROWS( EXPR, EXCEP ) \ From 265583bc78bc5b62bbdc7a49c5a6ff30d38e9bbe Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sat, 11 Feb 2017 18:26:57 +0100 Subject: [PATCH 22/30] Fixed error output of test_all_eq_impl --- include/boost/core/lightweight_test.hpp | 23 ++++++++---- test/Jamfile.v2 | 1 + test/lightweight_test_fail11.cpp | 50 +++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 test/lightweight_test_fail11.cpp diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 5e0ef5c..e263e01 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -189,13 +189,13 @@ void test_all_eq_impl(FormattedOutputFunction& output, { if (std::distance(first_begin, first_end) != std::distance(second_begin, second_end)) { - ::boost::detail::error_impl("Container sizes are different", __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); + ::boost::detail::error_impl("Container sizes are different", file, line, function); } else { ForwardIterator1 first_it = first_begin; ForwardIterator2 second_it = second_begin; - bool first_iteration = true; + std::size_t error_count = 0; do { while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) @@ -205,20 +205,27 @@ void test_all_eq_impl(FormattedOutputFunction& output, } if (first_it == first_end) { - boost::detail::report_errors_remind(); - return; + break; // do-while } - if (first_iteration) + if (error_count == 0) { - first_iteration = true; output << file << "(" << line << "): Container contents differ in function '" << function << "': mismatching indices"; } output << " [" << std::distance(first_begin, first_it) << "] '" << *first_it << "' != '" << *second_it << "'"; ++first_it; ++second_it; + ++error_count; } while (first_it != first_end); - output << std::endl; - ++boost::detail::test_errors(); + + if (error_count == 0) + { + boost::detail::report_errors_remind(); + } + else + { + output << std::endl; + ++boost::detail::test_errors(); + } } } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 31ba00f..fb9845f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -78,6 +78,7 @@ run-fail lightweight_test_fail8.cpp ; run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; run-fail lightweight_test_fail9.cpp ; run-fail lightweight_test_fail10.cpp ; +run-fail lightweight_test_fail11.cpp ; run is_same_test.cpp ; diff --git a/test/lightweight_test_fail11.cpp b/test/lightweight_test_fail11.cpp new file mode 100644 index 0000000..474d307 --- /dev/null +++ b/test/lightweight_test_fail11.cpp @@ -0,0 +1,50 @@ +// +// Negative test for BOOST_TEST_ALL_EQ +// +// Copyright (c) 2017 Bjorn Reese +// +// 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 +// + +#include +#include + +int main() +{ + int test_cases = 0; + + { + std::vector x, y; + x.push_back( 1 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + { + std::vector x, y; + y.push_back( 1 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1 ); x.push_back( 2 ); x.push_back( 3 ); x.push_back( 4 ); + y.push_back( 1 ); y.push_back( 3 ); y.push_back( 2 ); y.push_back( 4 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1.0f ); x.push_back( 2.0f ); x.push_back( 3.0f ); x.push_back( 4.0f ); + y.push_back( 4.0f ); y.push_back( 2.0f ); y.push_back( 3.0f ); y.push_back( 1.0f ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + boost::report_errors(); + + return boost::detail::test_errors() == test_cases; +} From c96ad4ccbaab46a8b492414eb2a622d096d62651 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sat, 11 Feb 2017 18:39:06 +0100 Subject: [PATCH 23/30] Added container sizes to error output of test_all_eq_impl --- include/boost/core/lightweight_test.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index e263e01..4532819 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -187,9 +187,16 @@ void test_all_eq_impl(FormattedOutputFunction& output, ForwardIterator1 first_begin, ForwardIterator1 first_end, ForwardIterator2 second_begin, ForwardIterator2 second_end) { - if (std::distance(first_begin, first_end) != std::distance(second_begin, second_end)) + typename std::iterator_traits::difference_type first_distance = std::distance(first_begin, first_end); + typename std::iterator_traits::difference_type second_distance = std::distance(second_begin, second_end); + if (first_distance != second_distance) { - ::boost::detail::error_impl("Container sizes are different", file, line, function); + output << file << "(" << line << "): " + << "Container sizes are different" + << " in function '" << function << "': " + << first_distance << " != " << second_distance + << std::endl; + ++test_errors(); } else { From fb09632580fc0f4bfc17699ff44fdac0b0d5983c Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sun, 12 Feb 2017 12:26:58 +0100 Subject: [PATCH 24/30] Use test_output_impl in test_all_eq_impl --- include/boost/core/lightweight_test.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 4532819..8cc5547 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -218,7 +218,7 @@ void test_all_eq_impl(FormattedOutputFunction& output, { output << file << "(" << line << "): Container contents differ in function '" << function << "': mismatching indices"; } - output << " [" << std::distance(first_begin, first_it) << "] '" << *first_it << "' != '" << *second_it << "'"; + output << " [" << std::distance(first_begin, first_it) << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'"; ++first_it; ++second_it; ++error_count; From db8efb4ce9818287bab3abe8c81455adfc3c5eaf Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sun, 12 Feb 2017 13:19:39 +0100 Subject: [PATCH 25/30] Changed ForwardIterator to InputIterator for test_all_eq_impl --- include/boost/core/lightweight_test.hpp | 93 ++++++++++++++----------- test/lightweight_test_fail11.cpp | 76 ++++++++++++++++++++ 2 files changed, 130 insertions(+), 39 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 8cc5547..8ed0f7d 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -181,58 +181,73 @@ inline void test_cstr_ne_impl( char const * expr1, char const * expr2, } } -template +template void test_all_eq_impl(FormattedOutputFunction& output, char const * file, int line, char const * function, - ForwardIterator1 first_begin, ForwardIterator1 first_end, - ForwardIterator2 second_begin, ForwardIterator2 second_end) + InputIterator1 first_begin, InputIterator1 first_end, + InputIterator2 second_begin, InputIterator2 second_end) { - typename std::iterator_traits::difference_type first_distance = std::distance(first_begin, first_end); - typename std::iterator_traits::difference_type second_distance = std::distance(second_begin, second_end); - if (first_distance != second_distance) + InputIterator1 first_it = first_begin; + InputIterator2 second_it = second_begin; + typename std::iterator_traits::difference_type first_index = 0; + typename std::iterator_traits::difference_type second_index = 0; + std::size_t error_count = 0; + do { - output << file << "(" << line << "): " - << "Container sizes are different" - << " in function '" << function << "': " - << first_distance << " != " << second_distance - << std::endl; - ++test_errors(); - } - else - { - ForwardIterator1 first_it = first_begin; - ForwardIterator2 second_it = second_begin; - std::size_t error_count = 0; - do + while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) { - while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) - { - ++first_it; - ++second_it; - } - if (first_it == first_end) - { - break; // do-while - } - if (error_count == 0) - { - output << file << "(" << line << "): Container contents differ in function '" << function << "': mismatching indices"; - } - output << " [" << std::distance(first_begin, first_it) << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'"; ++first_it; ++second_it; - ++error_count; - } while (first_it != first_end); - + ++first_index; + ++second_index; + } + if ((first_it == first_end) || (second_it == second_end)) + { + break; // do-while + } if (error_count == 0) { - boost::detail::report_errors_remind(); + output << file << "(" << line << "): Container contents differ in function '" << function << "':"; + } + output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'"; + ++first_it; + ++second_it; + ++first_index; + ++second_index; + ++error_count; + } while (first_it != first_end); + + while (first_it != first_end) + { + ++first_it; + ++first_index; + } + while (second_it != second_end) + { + ++second_it; + ++second_index; + } + if (first_index != second_index) + { + if (error_count == 0) + { + output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")"; } else { - output << std::endl; - ++boost::detail::test_errors(); + output << " [*] size(" << first_index << ") != size(" << second_index << ")"; } + ++error_count; + } + + if (error_count == 0) + { + boost::detail::report_errors_remind(); + } + else + { + output << std::endl; + ++boost::detail::test_errors(); } } diff --git a/test/lightweight_test_fail11.cpp b/test/lightweight_test_fail11.cpp index 474d307..120a859 100644 --- a/test/lightweight_test_fail11.cpp +++ b/test/lightweight_test_fail11.cpp @@ -9,18 +9,52 @@ // #include +#include #include int main() { int test_cases = 0; + // Array + + { + int x[] = { 1 }; + int y[] = { 1, 2 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + { + int x[] = { 1, 2 }; + int y[] = { 1 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + { + int x[] = { 2 }; + int y[] = { 1, 2 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + { + int x[] = { 1, 2, 3, 4 }; + int y[] = { 1, 3, 2, 4 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + // Vector + { std::vector x, y; x.push_back( 1 ); BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); ++test_cases; } + { std::vector x, y; y.push_back( 1 ); @@ -44,6 +78,48 @@ int main() ++test_cases; } + { + std::vector x, y; + x.push_back( 1 ); x.push_back( 2 ); x.push_back( 3 ); + y.push_back( 1 ); y.push_back( 3 ); y.push_back( 2 ); y.push_back( 4 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1 ); x.push_back( 2 ); x.push_back( 3 ); x.push_back( 4 ); + y.push_back( 1 ); y.push_back( 3 ); y.push_back( 2 );; + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + // Set + + { + std::set x, y; + x.insert(1); + y.insert(1); y.insert(3); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::set x, y; + x.insert(1); x.insert(2); + y.insert(1); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::set x, y; + x.insert(1); x.insert(2); + y.insert(1); y.insert(3); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + boost::report_errors(); return boost::detail::test_errors() == test_cases; From d828e40f6d4d18ec6635d2ecff7cb2239e28dcf1 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sun, 12 Feb 2017 15:06:31 +0100 Subject: [PATCH 26/30] Output at most 8 differing container values --- include/boost/core/lightweight_test.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 8ed0f7d..908cc77 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -192,6 +192,7 @@ void test_all_eq_impl(FormattedOutputFunction& output, typename std::iterator_traits::difference_type first_index = 0; typename std::iterator_traits::difference_type second_index = 0; std::size_t error_count = 0; + const std::size_t max_count = 8; do { while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) @@ -209,6 +210,11 @@ void test_all_eq_impl(FormattedOutputFunction& output, { output << file << "(" << line << "): Container contents differ in function '" << function << "':"; } + else if (error_count >= max_count) + { + output << " ..."; + break; + } output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'"; ++first_it; ++second_it; From baed4103a069a6d06951ae06cf23c9ef2a31de73 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sun, 12 Feb 2017 15:08:25 +0100 Subject: [PATCH 27/30] Optimized calculation of container sizes --- include/boost/core/lightweight_test.hpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 908cc77..b4b59c7 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -223,16 +223,8 @@ void test_all_eq_impl(FormattedOutputFunction& output, ++error_count; } while (first_it != first_end); - while (first_it != first_end) - { - ++first_it; - ++first_index; - } - while (second_it != second_end) - { - ++second_it; - ++second_index; - } + first_index += std::distance(first_it, first_end); + second_index += std::distance(second_it, second_end); if (first_index != second_index) { if (error_count == 0) From c8b7acc8aab81bc1c0393112849088763bfa68bb Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sun, 12 Feb 2017 15:11:30 +0100 Subject: [PATCH 28/30] Changed lightweight_test_fail11 from run-fail to run --- test/Jamfile.v2 | 2 +- test/lightweight_test_fail11.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fb9845f..83f6012 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -78,7 +78,7 @@ run-fail lightweight_test_fail8.cpp ; run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; run-fail lightweight_test_fail9.cpp ; run-fail lightweight_test_fail10.cpp ; -run-fail lightweight_test_fail11.cpp ; +run lightweight_test_fail11.cpp ; run is_same_test.cpp ; diff --git a/test/lightweight_test_fail11.cpp b/test/lightweight_test_fail11.cpp index 120a859..0fb0fb9 100644 --- a/test/lightweight_test_fail11.cpp +++ b/test/lightweight_test_fail11.cpp @@ -122,5 +122,5 @@ int main() boost::report_errors(); - return boost::detail::test_errors() == test_cases; + return boost::detail::test_errors() != test_cases; } From 54e262ee135c0aa81c06f7f7f367271ca12c16ba Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Mon, 13 Feb 2017 15:55:42 +0100 Subject: [PATCH 29/30] Minor fixes --- doc/lightweight_test.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index c3ab7bc..77a3e49 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -128,7 +128,7 @@ Specialization of BOOST_TEST_NE which interprets expr1 and expr2 as pointers to BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) `` -Compares the content of two containers. If they have different sizes, or if any pairwise element differs, increases the error count and outputs a message containing all differing elements. +Compares the content of two sequences. If they have different sizes, or if any pairwise element differs, increases the error count and outputs a message containing at most 8 differing elements. [endsect] From 1bdb657b71ad312d7d3685f516af53f9914a1a54 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Mon, 13 Feb 2017 15:58:15 +0100 Subject: [PATCH 30/30] Renamed test suite for BOOST_TEST_ALL_EQ --- test/Jamfile.v2 | 2 +- ...tweight_test_fail11.cpp => lightweight_test_all_eq_test.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{lightweight_test_fail11.cpp => lightweight_test_all_eq_test.cpp} (100%) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 83f6012..712de26 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -65,6 +65,7 @@ run lightweight_test_test.cpp ; run lightweight_test_test.cpp : : : off : lightweight_test_test_no_except ; run lightweight_test_test2.cpp ; +run lightweight_test_all_eq_test.cpp ; run-fail lightweight_test_fail.cpp ; run-fail lightweight_test_fail2.cpp ; @@ -78,7 +79,6 @@ run-fail lightweight_test_fail8.cpp ; run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; run-fail lightweight_test_fail9.cpp ; run-fail lightweight_test_fail10.cpp ; -run lightweight_test_fail11.cpp ; run is_same_test.cpp ; diff --git a/test/lightweight_test_fail11.cpp b/test/lightweight_test_all_eq_test.cpp similarity index 100% rename from test/lightweight_test_fail11.cpp rename to test/lightweight_test_all_eq_test.cpp