From 9f315530336ba8b05eae015f9e13f981d62d9790 Mon Sep 17 00:00:00 2001 From: Marcel Raad Date: Tue, 23 Sep 2014 15:37:28 +0200 Subject: [PATCH 1/5] Don't delete copy constructor when rvalue references are disabled Before SVN r82706 from February 2013 (git a7091d1009f057b1148b36fabf91f83667db5f72), Boost.Move worked perfectly for compilers that supported deleted functions without supporting rvalue references (for example, clang with libstdc++ 4.2.1 on Mac to support OS X 10.6). r82706 broke those setups as temporaries now call the deleted copy constructor instead of the move constructor. This change reverts those setups to the old behavior. --- include/boost/move/core.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/move/core.hpp b/include/boost/move/core.hpp index af21990..b420875 100644 --- a/include/boost/move/core.hpp +++ b/include/boost/move/core.hpp @@ -20,7 +20,7 @@ //boost_move_no_copy_constructor_or_assign typedef //used to detect noncopyable types for other Boost libraries. -#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ private:\ TYPE(TYPE &);\ From 4115ecc45ace038268cd8e334a46e9ce192eb520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 23 Sep 2014 16:37:59 +0200 Subject: [PATCH 2/5] Updated changelog with Git Pull #3 --- doc/move.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/move.qbk b/doc/move.qbk index 1df3e5d..762a6c9 100644 --- a/doc/move.qbk +++ b/doc/move.qbk @@ -757,10 +757,11 @@ Many thanks to all boosters that have tested, reviewed and improved the library. [section:release_notes_boost_1_57_00 Boost 1.57 Release] -* Added `unique_ptr` utility. Thanks to Howard Hinnant for his excellent unique_ptr emulation code and testsuite. +* Added `unique_ptr` smart pointer. Thanks to Howard Hinnant for his excellent unique_ptr emulation code and testsuite. * Added `move_if_noexcept` utility. Thanks to Antony Polukhin for the implementation. * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/9785 Trac #9785: ['"Compiler warning with intel icc in boost/move/core.hpp"]], + * [@https://github.com/boostorg/move/pull/3 Git Pull #3: ['"Don't delete copy constructor when rvalue references are disabled"]], [endsect] From 4e7a046df208a9d48b16575aca8bb4b550cd974e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 25 Sep 2014 16:15:36 +0200 Subject: [PATCH 3/5] Replaced with when possible to minimize dependencies. --- example/doc_clone_ptr.cpp | 2 +- example/doc_construct_forward.cpp | 2 +- example/doc_file_descriptor.cpp | 2 +- include/boost/move/algorithm.hpp | 2 +- include/boost/move/detail/config_begin.hpp | 2 ++ include/boost/move/detail/move_helpers.hpp | 2 +- include/boost/move/iterator.hpp | 32 +++++++++++++--------- test/construct_forward.cpp | 2 +- test/conversion_test.cpp | 2 +- test/copy_elision_test.cpp | 2 +- test/copy_move_optimization.cpp | 2 +- test/move.cpp | 2 +- 12 files changed, 31 insertions(+), 23 deletions(-) diff --git a/example/doc_clone_ptr.cpp b/example/doc_clone_ptr.cpp index 976b142..f1b72b0 100644 --- a/example/doc_clone_ptr.cpp +++ b/example/doc_clone_ptr.cpp @@ -9,7 +9,7 @@ // ////////////////////////////////////////////////////////////////////////////// #include -#include +#include //[clone_ptr_base_derived class Base diff --git a/example/doc_construct_forward.cpp b/example/doc_construct_forward.cpp index 4eee536..388a97c 100644 --- a/example/doc_construct_forward.cpp +++ b/example/doc_construct_forward.cpp @@ -12,7 +12,7 @@ #include //[construct_forward_example -#include +#include #include class copyable_only_tester diff --git a/example/doc_file_descriptor.cpp b/example/doc_file_descriptor.cpp index 1dd7bc0..0ec3987 100644 --- a/example/doc_file_descriptor.cpp +++ b/example/doc_file_descriptor.cpp @@ -14,7 +14,7 @@ //[file_descriptor_def -#include +#include #include class file_descriptor diff --git a/include/boost/move/algorithm.hpp b/include/boost/move/algorithm.hpp index 43a81c3..da2f186 100644 --- a/include/boost/move/algorithm.hpp +++ b/include/boost/move/algorithm.hpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include diff --git a/include/boost/move/detail/config_begin.hpp b/include/boost/move/detail/config_begin.hpp index 8505f4b..7e90c3b 100644 --- a/include/boost/move/detail/config_begin.hpp +++ b/include/boost/move/detail/config_begin.hpp @@ -7,7 +7,9 @@ // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_CONFIG_HPP #include +#endif #ifdef BOOST_MSVC #pragma warning (push) diff --git a/include/boost/move/detail/move_helpers.hpp b/include/boost/move/detail/move_helpers.hpp index 49c5efe..78d98ea 100644 --- a/include/boost/move/detail/move_helpers.hpp +++ b/include/boost/move/detail/move_helpers.hpp @@ -12,7 +12,7 @@ #ifndef BOOST_MOVE_MOVE_HELPERS_HPP #define BOOST_MOVE_MOVE_HELPERS_HPP -#include +#include #include #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/include/boost/move/iterator.hpp b/include/boost/move/iterator.hpp index 79e7bfd..dda6f83 100644 --- a/include/boost/move/iterator.hpp +++ b/include/boost/move/iterator.hpp @@ -15,7 +15,7 @@ #define BOOST_MOVE_ITERATOR_HPP #include -#include +#include #include //std::iterator namespace boost { @@ -177,14 +177,16 @@ inline move_iterator make_move_iterator(const It &it) //! back of a container template // C models Container class back_move_insert_iterator - : public std::iterator { C* container_m; public: - typedef C container_type; - typedef typename C::value_type value_type; - typedef typename C::reference reference; + typedef C container_type; + typedef typename C::value_type value_type; + typedef typename C::reference reference; + typedef typename C::pointer pointer; + typedef typename C::difference_type difference_type; + typedef std::output_iterator_tag iterator_category; explicit back_move_insert_iterator(C& x) : container_m(&x) { } @@ -217,14 +219,16 @@ inline back_move_insert_iterator back_move_inserter(C& x) //! front of a container template // C models Container class front_move_insert_iterator - : public std::iterator { C* container_m; public: - typedef C container_type; - typedef typename C::value_type value_type; - typedef typename C::reference reference; + typedef C container_type; + typedef typename C::value_type value_type; + typedef typename C::reference reference; + typedef typename C::pointer pointer; + typedef typename C::difference_type difference_type; + typedef std::output_iterator_tag iterator_category; explicit front_move_insert_iterator(C& x) : container_m(&x) { } @@ -254,15 +258,17 @@ inline front_move_insert_iterator front_move_inserter(C& x) ////////////////////////////////////////////////////////////////////////////// template // C models Container class move_insert_iterator - : public std::iterator { C* container_m; typename C::iterator pos_; public: - typedef C container_type; - typedef typename C::value_type value_type; - typedef typename C::reference reference; + typedef C container_type; + typedef typename C::value_type value_type; + typedef typename C::reference reference; + typedef typename C::pointer pointer; + typedef typename C::difference_type difference_type; + typedef std::output_iterator_tag iterator_category; explicit move_insert_iterator(C& x, typename C::iterator pos) : container_m(&x), pos_(pos) diff --git a/test/construct_forward.cpp b/test/construct_forward.cpp index 6922d82..87c9a80 100644 --- a/test/construct_forward.cpp +++ b/test/construct_forward.cpp @@ -9,7 +9,7 @@ // ////////////////////////////////////////////////////////////////////////////// #include -#include +#include #include #include "../example/movable.hpp" #include "../example/copymovable.hpp" diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp index 13a1adc..cf28d6a 100644 --- a/test/conversion_test.cpp +++ b/test/conversion_test.cpp @@ -8,7 +8,7 @@ // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include +#include #include #include #include diff --git a/test/copy_elision_test.cpp b/test/copy_elision_test.cpp index b15ebf2..4faf5ba 100644 --- a/test/copy_elision_test.cpp +++ b/test/copy_elision_test.cpp @@ -12,7 +12,7 @@ # define BOOST_COPYABLE_AND_MOVABLE(X) # define MOVE(x) (x) #else -#include +#include # define MOVE(x) boost::move(x) #endif diff --git a/test/copy_move_optimization.cpp b/test/copy_move_optimization.cpp index 4702a6f..06d1847 100644 --- a/test/copy_move_optimization.cpp +++ b/test/copy_move_optimization.cpp @@ -9,7 +9,7 @@ //Since RVO is better than move-construction, //avoid copy constructor overloading. #include -#include +#include #include bool moved = false; diff --git a/test/move.cpp b/test/move.cpp index 3c98159..2d40ec8 100644 --- a/test/move.cpp +++ b/test/move.cpp @@ -10,7 +10,7 @@ // ////////////////////////////////////////////////////////////////////////////// #include -#include +#include #include "../example/movable.hpp" #include "../example/copymovable.hpp" #include From 76ab7093ae74111fa82f483af60049070ec61cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 25 Sep 2014 16:45:22 +0200 Subject: [PATCH 4/5] Removed warnings in GCC 4.8 -Wall -pedantic --- test/copy_elision_test.cpp | 38 ++++++++-------- test/unique_ptr_default_deleter.cpp | 4 +- test/unique_ptr_functions.cpp | 68 ++++++++++++++--------------- test/unique_ptr_test_utils_beg.hpp | 4 +- 4 files changed, 59 insertions(+), 55 deletions(-) diff --git a/test/copy_elision_test.cpp b/test/copy_elision_test.cpp index 4faf5ba..39123e1 100644 --- a/test/copy_elision_test.cpp +++ b/test/copy_elision_test.cpp @@ -4,6 +4,7 @@ #include #include +#include #ifdef NO_MOVE # undef BOOST_COPY_ASSIGN_REF @@ -73,9 +74,12 @@ unsigned X::instances = 0; stmt; \ } \ unsigned const n = X::copies - old_copies; \ - if (n > max) \ + volatile unsigned const minv(min), maxv(max); \ + BOOST_TEST(n <= maxv); \ + if (n > maxv) \ std::cout << "*** max is too low or compiler is buggy ***\n"; \ - if (n < min) \ + BOOST_TEST(n >= minv); \ + if (n < minv) \ std::cout << "*** min is too high or compiler is buggy ***\n"; \ \ std::cout << "-----------\n" \ @@ -84,7 +88,7 @@ unsigned X::instances = 0; << max - n << "/" << max - min \ << " possible elisions performed\n\n"; \ \ - if (n > min) \ + if (n > minv) \ std::cout << "*** " << n - min \ << " possible elisions missed! ***\n"; \ } @@ -105,7 +109,7 @@ struct trace char const* m_name; }; -void sink(X a) +void sink(X) { trace t("sink"); } @@ -146,28 +150,28 @@ int main(int argc, char* argv[]) { (void)argv; // Double parens prevent "most vexing parse" - CHECK_COPIES( X a(( lvalue() )), 1, 1, "Direct initialization from lvalue"); - CHECK_COPIES( X a(( rvalue() )), 0, 1, "Direct initialization from rvalue"); + CHECK_COPIES( X a(( lvalue() )), 1U, 1U, "Direct initialization from lvalue"); + CHECK_COPIES( X a(( rvalue() )), 0U, 1U, "Direct initialization from rvalue"); - CHECK_COPIES( X a = lvalue(), 1, 1, "Copy initialization from lvalue" ); - CHECK_COPIES( X a = rvalue(), 0, 1, "Copy initialization from rvalue" ); + CHECK_COPIES( X a = lvalue(), 1U, 1U, "Copy initialization from lvalue" ); + CHECK_COPIES( X a = rvalue(), 0U, 1U, "Copy initialization from rvalue" ); - CHECK_COPIES( sink( lvalue() ), 1, 1, "Pass lvalue by value" ); - CHECK_COPIES( sink( rvalue() ), 0, 1, "Pass rvalue by value" ); + CHECK_COPIES( sink( lvalue() ), 1U, 1U, "Pass lvalue by value" ); + CHECK_COPIES( sink( rvalue() ), 0U, 1U, "Pass rvalue by value" ); - CHECK_COPIES( nrvo_source(), 0, 1, "Named return value optimization (NRVO)" ); - CHECK_COPIES( urvo_source(), 0, 1, "Unnamed return value optimization (URVO)" ); + CHECK_COPIES( nrvo_source(), 0U, 1U, "Named return value optimization (NRVO)" ); + CHECK_COPIES( urvo_source(), 0U, 1U, "Unnamed return value optimization (URVO)" ); // Just to prove these things compose properly - CHECK_COPIES( X a(urvo_source()), 0, 2, "Return value used as ctor arg" ); + CHECK_COPIES( X a(urvo_source()), 0U, 2U, "Return value used as ctor arg" ); // Expect to miss one possible elision here - CHECK_COPIES( identity( rvalue() ), 0, 2, "Return rvalue passed by value" ); + CHECK_COPIES( identity( rvalue() ), 0U, 2U, "Return rvalue passed by value" ); // Expect to miss an elision in at least one of the following lines - CHECK_COPIES( X a = ternary( argc == 1000 ), 0, 2, "Return result of ternary operation" ); - CHECK_COPIES( X a = ternary( argc != 1000 ), 0, 2, "Return result of ternary operation again" ); - return 0; + CHECK_COPIES( X a = ternary( argc == 1000 ), 0U, 2U, "Return result of ternary operation" ); + CHECK_COPIES( X a = ternary( argc != 1000 ), 0U, 2U, "Return result of ternary operation again" ); + return boost::report_errors(); } #include diff --git a/test/unique_ptr_default_deleter.cpp b/test/unique_ptr_default_deleter.cpp index 35563f9..1bf16ea 100644 --- a/test/unique_ptr_default_deleter.cpp +++ b/test/unique_ptr_default_deleter.cpp @@ -47,8 +47,8 @@ struct B : public A { static int count; - B() {++count;} - B(const B&) {++count;} + B() : A() {++count;} + B(const B&) : A() {++count;} virtual ~B() {--count;} }; diff --git a/test/unique_ptr_functions.cpp b/test/unique_ptr_functions.cpp index d8cdf9e..21dc99c 100644 --- a/test/unique_ptr_functions.cpp +++ b/test/unique_ptr_functions.cpp @@ -31,8 +31,8 @@ struct B : public A { static int count; - B() {++count;} - B(const B&) {++count;} + B() : A() {++count;} + B(const B&) : A() {++count;} virtual ~B() {--count;} }; @@ -218,25 +218,25 @@ void test() BOOST_TEST(!(pb != 0)); BOOST_TEST(!(0 != pb)); //Less - BOOST_TEST((pa < 0) == (pa.get() < 0)); - BOOST_TEST((0 < pa) == (0 < pa.get())); - BOOST_TEST((pb < 0) == (pb.get() < 0)); - BOOST_TEST((0 < pb) == (0 < pb.get())); + BOOST_TEST((pa < 0) == (pa.get() < (A*)0)); + BOOST_TEST((0 < pa) == ((A*)0 < pa.get())); + BOOST_TEST((pb < 0) == (pb.get() < (A*)0)); + BOOST_TEST((0 < pb) == ((A*)0 < pb.get())); //Greater - BOOST_TEST((pa > 0) == (pa.get() > 0)); - BOOST_TEST((0 > pa) == (0 > pa.get())); - BOOST_TEST((pb > 0) == (pb.get() > 0)); - BOOST_TEST((0 > pb) == (0 > pb.get())); + BOOST_TEST((pa > 0) == (pa.get() > (A*)0)); + BOOST_TEST((0 > pa) == ((A*)0 > pa.get())); + BOOST_TEST((pb > 0) == (pb.get() > (A*)0)); + BOOST_TEST((0 > pb) == ((A*)0 > pb.get())); //Less or equal - BOOST_TEST((pa <= 0) == (pa.get() <= 0)); - BOOST_TEST((0 <= pa) == (0 <= pa.get())); - BOOST_TEST((pb <= 0) == (pb.get() <= 0)); - BOOST_TEST((0 <= pb) == (0 <= pb.get())); + BOOST_TEST((pa <= 0) == (pa.get() <= (A*)0)); + BOOST_TEST((0 <= pa) == ((A*)0 <= pa.get())); + BOOST_TEST((pb <= 0) == (pb.get() <= (A*)0)); + BOOST_TEST((0 <= pb) == ((A*)0 <= pb.get())); //Greater or equal - BOOST_TEST((pa >= 0) == (pa.get() >= 0)); - BOOST_TEST((0 >= pa) == (0 >= pa.get())); - BOOST_TEST((pb >= 0) == (pb.get() >= 0)); - BOOST_TEST((0 >= pb) == (0 >= pb.get())); + BOOST_TEST((pa >= 0) == (pa.get() >= (A*)0)); + BOOST_TEST((0 >= pa) == ((A*)0 >= pa.get())); + BOOST_TEST((pb >= 0) == (pb.get() >= (A*)0)); + BOOST_TEST((0 >= pb) == ((A*)0 >= pb.get())); } BOOST_TEST(A::count == 0); } @@ -270,25 +270,25 @@ void test() BOOST_TEST(!(pb != nullptr)); BOOST_TEST(!(nullptr != pb)); //Less - BOOST_TEST((pa < nullptr) == (pa.get() < nullptr)); - BOOST_TEST((nullptr < pa) == (nullptr < pa.get())); - BOOST_TEST((pb < nullptr) == (pb.get() < nullptr)); - BOOST_TEST((nullptr < pb) == (nullptr < pb.get())); + BOOST_TEST((pa < nullptr) == (pa.get() < (A*)nullptr)); + BOOST_TEST((nullptr < pa) == ((A*)nullptr < pa.get())); + BOOST_TEST((pb < nullptr) == (pb.get() < (A*)nullptr)); + BOOST_TEST((nullptr < pb) == ((A*)nullptr < pb.get())); //Greater - BOOST_TEST((pa > nullptr) == (pa.get() > nullptr)); - BOOST_TEST((nullptr > pa) == (nullptr > pa.get())); - BOOST_TEST((pb > nullptr) == (pb.get() > nullptr)); - BOOST_TEST((nullptr > pb) == (nullptr > pb.get())); + BOOST_TEST((pa > nullptr) == (pa.get() > (A*)nullptr)); + BOOST_TEST((nullptr > pa) == ((A*)nullptr > pa.get())); + BOOST_TEST((pb > nullptr) == (pb.get() > (A*)nullptr)); + BOOST_TEST((nullptr > pb) == ((A*)nullptr > pb.get())); //Less or equal - BOOST_TEST((pa <= nullptr) == (pa.get() <= nullptr)); - BOOST_TEST((nullptr <= pa) == (nullptr <= pa.get())); - BOOST_TEST((pb <= nullptr) == (pb.get() <= nullptr)); - BOOST_TEST((nullptr <= pb) == (nullptr <= pb.get())); + BOOST_TEST((pa <= nullptr) == (pa.get() <= (A*)nullptr)); + BOOST_TEST((nullptr <= pa) == ((A*)nullptr <= pa.get())); + BOOST_TEST((pb <= nullptr) == (pb.get() <= (A*)nullptr)); + BOOST_TEST((nullptr <= pb) == ((A*)nullptr <= pb.get())); //Greater or equal - BOOST_TEST((pa >= nullptr) == (pa.get() >= nullptr)); - BOOST_TEST((nullptr >= pa) == (nullptr >= pa.get())); - BOOST_TEST((pb >= nullptr) == (pb.get() >= nullptr)); - BOOST_TEST((nullptr >= pb) == (nullptr >= pb.get())); + BOOST_TEST((pa >= nullptr) == (pa.get() >= (A*)nullptr)); + BOOST_TEST((nullptr >= pa) == ((A*)nullptr >= pa.get())); + BOOST_TEST((pb >= nullptr) == (pb.get() >= (A*)nullptr)); + BOOST_TEST((nullptr >= pb) == ((A*)nullptr >= pb.get())); } BOOST_TEST(A::count == 0); #endif //#if !defined(BOOST_NO_CXX11_NULLPTR) diff --git a/test/unique_ptr_test_utils_beg.hpp b/test/unique_ptr_test_utils_beg.hpp index 1b50426..965732c 100644 --- a/test/unique_ptr_test_utils_beg.hpp +++ b/test/unique_ptr_test_utils_beg.hpp @@ -173,8 +173,8 @@ struct B : public A { static int count; - B() {++count;} - B(const B&) {++count;} + B() : A() {++count;} + B(const B &b) : A(b) {++count;} virtual ~B() {--count;} }; From 1338039e7a43a99e085061b60be90e0b042884e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 30 Sep 2014 20:10:01 +0200 Subject: [PATCH 5/5] - Derive move_detail::is_rv from integral_constant to recover the internal "::type" typedef - Fix typo in header guard --- include/boost/move/algorithm.hpp | 2 +- include/boost/move/core.hpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/move/algorithm.hpp b/include/boost/move/algorithm.hpp index da2f186..f5f4b81 100644 --- a/include/boost/move/algorithm.hpp +++ b/include/boost/move/algorithm.hpp @@ -271,4 +271,4 @@ inline F copy_or_move(I f, I l, F r #include -#endif //#ifndef BOOST_MOVE_MOVE_HPP +#endif //#ifndef BOOST_MOVE_ALGORITHM_HPP diff --git a/include/boost/move/core.hpp b/include/boost/move/core.hpp index b420875..e2b13cd 100644 --- a/include/boost/move/core.hpp +++ b/include/boost/move/core.hpp @@ -87,7 +87,9 @@ template struct is_rv - : ::boost::move_detail::is_rv_impl + //Derive from integral constant because some Boost code assummes it has + //a "type" internal typedef + : integral_constant::value > {}; } //namespace move_detail {