// Copyright 2006-2009 Daniel James. // 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) // Define some minimal classes which provide the bare minimum concepts to // test that the containers don't rely on something that they shouldn't. // They are not intended to be good examples of how to implement the concepts. #if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER) #define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER #include #include #include #if defined(BOOST_MSVC) #pragma warning(push) #pragma warning(disable:4100) // unreferenced formal parameter #endif namespace test { namespace minimal { class destructible; class copy_constructible; class copy_constructible_equality_comparable; class default_copy_constructible; class assignable; struct ampersand_operator_used {}; template class hash; template class equal_to; template class ptr; template class const_ptr; template class allocator; template class cxx11_allocator; struct constructor_param { operator int() const { return 0; } }; class destructible { public: destructible(constructor_param const&) {} ~destructible() {} private: destructible(destructible const&); destructible& operator=(destructible const&); }; class copy_constructible { public: copy_constructible(constructor_param const&) {} copy_constructible(copy_constructible const&) {} ~copy_constructible() {} private: copy_constructible& operator=(copy_constructible const&); copy_constructible() {} }; class copy_constructible_equality_comparable { public: copy_constructible_equality_comparable(constructor_param const&) {} copy_constructible_equality_comparable( copy_constructible_equality_comparable const&) { } ~copy_constructible_equality_comparable() { } private: copy_constructible_equality_comparable& operator=( copy_constructible_equality_comparable const&); copy_constructible_equality_comparable() {} ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; bool operator==( copy_constructible_equality_comparable, copy_constructible_equality_comparable) { return true; } bool operator!=( copy_constructible_equality_comparable, copy_constructible_equality_comparable) { return false; } class default_copy_constructible { public: default_copy_constructible(constructor_param const&) {} default_copy_constructible() { } default_copy_constructible(default_copy_constructible const&) { } ~default_copy_constructible() { } private: default_copy_constructible& operator=( default_copy_constructible const&); ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; class assignable { public: assignable(constructor_param const&) {} assignable(assignable const&) {} assignable& operator=(assignable const&) { return *this; } ~assignable() {} private: assignable() {} // TODO: This messes up a concept check in the tests. //ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; struct movable_init {}; class movable1 { BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1) public: movable1(constructor_param const&) {} movable1() {} explicit movable1(movable_init) {} movable1(BOOST_RV_REF(movable1)) {} movable1& operator=(BOOST_RV_REF(movable1)); ~movable1() {} }; #if !defined(BOOST_NO_RVALUE_REFERENCES) class movable2 { public: movable2(constructor_param const&) {} explicit movable2(movable_init) {} movable2(movable2&&) {} ~movable2() {} private: movable2() {} movable2(movable2 const&); movable2& operator=(movable2 const&); }; #else typedef movable1 movable2; #endif template class hash { public: hash(constructor_param const&) {} hash() {} hash(hash const&) {} hash& operator=(hash const&) { return *this; } ~hash() {} std::size_t operator()(T const&) const { return 0; } private: ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template class equal_to { public: equal_to(constructor_param const&) {} equal_to() {} equal_to(equal_to const&) {} equal_to& operator=(equal_to const&) { return *this; } ~equal_to() {} bool operator()(T const&, T const&) const { return true; } private: ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template class ptr; template class const_ptr; struct void_ptr { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template friend class ptr; private: #endif void* ptr_; public: void_ptr() : ptr_(0) {} template explicit void_ptr(ptr const& x) : ptr_(x.ptr_) {} // I'm not using the safe bool idiom because the containers should be // able to cope with bool conversions. operator bool() const { return !!ptr_; } bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; } bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; } }; class void_const_ptr { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template friend class const_ptr; private: #endif void* ptr_; public: void_const_ptr() : ptr_(0) {} template explicit void_const_ptr(const_ptr const& x) : ptr_(x.ptr_) {} // I'm not using the safe bool idiom because the containers should be // able to cope with bool conversions. operator bool() const { return !!ptr_; } bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; } bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; } }; template class ptr { friend class allocator; friend class const_ptr; friend struct void_ptr; T* ptr_; ptr(T* x) : ptr_(x) {} public: ptr() : ptr_(0) {} explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {} T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } ptr& operator++() { ++ptr_; return *this; } ptr operator++(int) { ptr tmp(*this); ++ptr_; return tmp; } ptr operator+(std::ptrdiff_t s) const { return ptr(ptr_ + s); } friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr(s + p.ptr_); } T& operator[](std::ptrdiff_t s) const { return ptr_[s]; } bool operator!() const { return !ptr_; } // I'm not using the safe bool idiom because the containers should be // able to cope with bool conversions. operator bool() const { return !!ptr_; } bool operator==(ptr const& x) const { return ptr_ == x.ptr_; } bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; } bool operator<(ptr const& x) const { return ptr_ < x.ptr_; } bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } private: // TODO: //ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template class const_ptr { friend class allocator; friend struct const_void_ptr; T const* ptr_; const_ptr(T const* ptr) : ptr_(ptr) {} public: const_ptr() : ptr_(0) {} const_ptr(ptr const& x) : ptr_(x.ptr_) {} explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {} T const& operator*() const { return *ptr_; } T const* operator->() const { return ptr_; } const_ptr& operator++() { ++ptr_; return *this; } const_ptr operator++(int) { const_ptr tmp(*this); ++ptr_; return tmp; } const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); } friend const_ptr operator+(std::ptrdiff_t s, const_ptr p) { return ptr(s + p.ptr_); } T const& operator[](int s) const { return ptr_[s]; } bool operator!() const { return !ptr_; } operator bool() const { return !!ptr_; } bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; } bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; } bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; } bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; } bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } private: // TODO: //ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template class allocator { public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef void_ptr void_pointer; typedef void_const_ptr const_void_pointer; typedef ptr pointer; typedef const_ptr const_pointer; typedef T& reference; typedef T const& const_reference; typedef T value_type; template struct rebind { typedef allocator other; }; allocator() {} template allocator(allocator const&) {} allocator(allocator const&) {} ~allocator() {} pointer address(reference r) { return pointer(&r); } const_pointer address(const_reference r) { return const_pointer(&r); } pointer allocate(size_type n) { return pointer(static_cast(::operator new(n * sizeof(T)))); } template pointer allocate(size_type n, const_ptr u) { return pointer(static_cast(::operator new(n * sizeof(T)))); } void deallocate(pointer p, size_type) { ::operator delete((void*) p.ptr_); } void construct(T* p, T const& t) { new((void*)p) T(t); } #if defined(BOOST_UNORDERED_VARIADIC_MOVE) template void construct(T* p, Args&&... args) { new((void*)p) T(boost::forward(args)...); } #endif void destroy(T* p) { p->~T(); } size_type max_size() const { return 1000; } #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \ BOOST_WORKAROUND(BOOST_MSVC, <= 1300) public: allocator& operator=(allocator const&) { return *this;} #else private: allocator& operator=(allocator const&); #endif private: ampersand_operator_used operator&() const { return ampersand_operator_used(); } }; template inline bool operator==(allocator const&, allocator const&) { return true; } template inline bool operator!=(allocator const&, allocator const&) { return false; } template void swap(allocator&, allocator&) { } // C++11 allocator // // Not a fully minimal C++11 allocator, just what I support. Hopefully will // cut down further in the future. template class cxx11_allocator { public: typedef T value_type; template struct rebind { typedef cxx11_allocator other; }; cxx11_allocator() {} template cxx11_allocator(cxx11_allocator const&) {} cxx11_allocator(cxx11_allocator const&) {} ~cxx11_allocator() {} T* address(T& r) { return &r; } T const* address(T const& r) { return &r; } T* allocate(std::size_t n) { return static_cast(::operator new(n * sizeof(T))); } template T* allocate(std::size_t n, const_ptr u) { return static_cast(::operator new(n * sizeof(T))); } void deallocate(T* p, std::size_t) { ::operator delete((void*) p); } void construct(T* p, T const& t) { new((void*)p) T(t); } #if defined(BOOST_UNORDERED_VARIADIC_MOVE) template void construct(T* p, Args&&... args) { new((void*)p) T(boost::forward(args)...); } #endif void destroy(T* p) { p->~T(); } std::size_t max_size() const { return 1000u; } }; template inline bool operator==(cxx11_allocator const&, cxx11_allocator const&) { return true; } template inline bool operator!=(cxx11_allocator const&, cxx11_allocator const&) { return false; } template void swap(cxx11_allocator&, cxx11_allocator&) { } } } #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) namespace boost { #else namespace test { namespace minimal { #endif std::size_t hash_value( test::minimal::copy_constructible_equality_comparable) { return 1; } #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) }} #else } #endif #if defined(BOOST_MSVC) #pragma warning(pop) #endif #endif