diff --git a/.travis.yml b/.travis.yml index 7e7a9967c..4be5ef264 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,10 +40,10 @@ matrix: - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF compiler: gcc arch: amd64 - - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' compiler: gcc - arch: amd64 - - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON + arch: amd64/ + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' compiler: gcc arch: amd64 - env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF @@ -84,7 +84,7 @@ matrix: compiler: clang arch: arm64 # coverage report - - env: CONF=debug ARCH=x86 CXX11=ON CXX17=OFF GCOV_FLAGS='--coverage' + - env: CONF=debug ARCH=x86 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=OFF compiler: gcc arch: amd64 cache: @@ -93,7 +93,7 @@ matrix: after_success: - pip install --user cpp-coveralls - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h - - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' + - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF compiler: gcc arch: amd64 cache: @@ -102,7 +102,7 @@ matrix: after_success: - pip install --user cpp-coveralls - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h - - env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' + - env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=ON compiler: gcc arch: arm64 cache: @@ -150,7 +150,7 @@ script: -DRAPIDJSON_BUILD_CXX17=$CXX17 -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=$CONF - -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS" + -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS $CXX_FLAGS" -DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS ..) - cd build diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index 711ac3084..e8d1fb42b 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -222,7 +222,6 @@ class MemoryPoolAllocator { { RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); ++rhs.shared_->refcount; - this->~MemoryPoolAllocator(); baseAllocator_ = rhs.baseAllocator_; chunk_capacity_ = rhs.chunk_capacity_; @@ -230,10 +229,35 @@ class MemoryPoolAllocator { return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(std::move(rhs.baseAllocator_)), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + rhs.shared_ = 0; + } + MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + this->~MemoryPoolAllocator(); + baseAllocator_ = std::move(rhs.baseAllocator_); + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + rhs.shared_ = 0; + return *this; + } +#endif + //! Destructor. /*! This deallocates all memory chunks, excluding the user-supplied buffer. */ ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT { + if (!shared_) { + // do nothing if moved + return; + } if (shared_->refcount > 1) { --shared_->refcount; return; @@ -449,6 +473,17 @@ class StdAllocator : baseAllocator_(rhs.baseAllocator_) { } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(std::move(rhs)), + baseAllocator_(std::move(rhs.baseAllocator_)) + { } +#endif +#if RAPIDJSON_HAS_CXX11 + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; +#endif + /* implicit */ StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(), @@ -549,6 +584,10 @@ class StdAllocator : deallocate(p, n); } +#if RAPIDJSON_HAS_CXX11 + using is_always_equal = std::is_empty; +#endif + template bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT { @@ -561,6 +600,7 @@ class StdAllocator : } //! rapidjson Allocator concept + static const bool kNeedFree = BaseAllocator::kNeedFree; void* Malloc(size_t size) { return baseAllocator_.Malloc(size); diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index ec1b2ce52..2ffc32542 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -16,8 +16,10 @@ #include "rapidjson/allocators.h" +#include #include -#include +#include +#include using namespace rapidjson; @@ -141,12 +143,34 @@ void TestStdAllocator(const Allocator& a) { typedef StdAllocator CharAllocator; typedef std::basic_string, CharAllocator> String; +#if RAPIDJSON_HAS_CXX11 + String s(CharAllocator{a}); +#else CharAllocator ca(a); String s(ca); +#endif for (int i = 0; i < 26; i++) { s.push_back(static_cast('A' + i)); } EXPECT_TRUE(s == "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + typedef StdAllocator, Allocator> MapAllocator; + typedef std::map, MapAllocator> Map; +#if RAPIDJSON_HAS_CXX11 + Map map(std::less(), MapAllocator{a}); +#else + MapAllocator ma(a); + Map map(std::less(), ma); +#endif + for (int i = 0; i < 10; i++) { + map.insert(std::make_pair(i, (i % 2) == 0)); + } + EXPECT_TRUE(map.size() == 10); + for (int i = 0; i < 10; i++) { + typename Map::iterator it = map.find(i); + EXPECT_TRUE(it != map.end()); + EXPECT_TRUE(it->second == ((i % 2) == 0)); + } } TEST(Allocator, CrtAllocator) {