Unordered: More portable allocator_traits.

[SVN r74067]
This commit is contained in:
Daniel James
2011-08-26 08:11:46 +00:00
parent cfd52c8f38
commit 099a893678
6 changed files with 317 additions and 61 deletions
+7 -2
View File
@@ -194,8 +194,13 @@ namespace test
enum { value = false };
};
template <typename Alloc>
int selected_count(Alloc const&)
struct convert_from_anything
{
template <typename T>
convert_from_anything(T const&) {}
};
int selected_count(convert_from_anything)
{
return 0;
}
+12 -5
View File
@@ -186,9 +186,14 @@ namespace test
};
template <typename T, typename Flags = propagate_swap,
bool SelectCopy = Flags::is_select_on_copy ? true : false>
struct cxx11_allocator :
public cxx11_allocator_base<T>,
typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags>
struct cxx11_allocator<
T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type
> : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
@@ -228,8 +233,10 @@ namespace test
};
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags, true> :
public cxx11_allocator_base<T>,
struct cxx11_allocator<
T, Flags,
typename boost::enable_if_c<Flags::is_select_on_copy>::type
> : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
+2 -2
View File
@@ -26,7 +26,7 @@ namespace test
object generate(object const*);
implicitly_convertible generate(implicitly_convertible const*);
class object : globally_counted_object
class object : private globally_counted_object
{
friend class hash;
friend class equal_to;
@@ -64,7 +64,7 @@ namespace test
}
};
class implicitly_convertible : globally_counted_object
class implicitly_convertible : private globally_counted_object
{
int tag1_, tag2_;
public:
+1
View File
@@ -22,6 +22,7 @@ test-suite unordered
:
[ run fwd_set_test.cpp ]
[ run fwd_map_test.cpp ]
[ run allocator_traits.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
+226
View File
@@ -0,0 +1,226 @@
// Copyright 2011 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)
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
// Boilerplate
#define ALLOCATOR_METHODS(name) \
template <typename U> struct rebind { \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r;} \
T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
T* allocate(std::size_t n, void const* u) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
void deallocate(T* p, std::size_t n) { ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \
{ return (std::numeric_limits<std::size_t>::max)(); } \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
#define ALLOCATOR_METHODS_TYPEDEFS(name) \
template <typename U> struct rebind { \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r;} \
const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \
{ return pointer(::operator new(n * sizeof(T))); } \
pointer allocate(std::size_t n, void const* u) \
{ return pointer(::operator new(n * sizeof(T))); } \
void deallocate(pointer p, std::size_t n) \
{ ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
size_type max_size() const \
{ return (std::numeric_limits<size_type>::max)(); } \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
struct yes_type { enum { value = true }; };
struct no_type { enum { value = false }; };
// For tracking calls...
static int selected;
void reset() {
selected = 0;
}
template <typename Allocator>
int call_select()
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a;
reset();
BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
return selected;
}
// Empty allocator test
template <typename T>
struct empty_allocator
{
typedef T value_type;
ALLOCATOR_METHODS(empty_allocator)
};
void test_empty_allocator()
{
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 0);
}
// allocator 1
template <typename T>
struct allocator1
{
typedef T value_type;
ALLOCATOR_METHODS(allocator1)
typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap;
allocator1<T> select_on_container_copy_construction() const {
++selected;
return allocator1<T>();
}
};
void test_allocator1()
{
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 2
template <typename T>
struct allocator2
{
typedef T value_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef std::size_t size_type;
ALLOCATOR_METHODS(allocator2)
typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap;
// Note: Not const - so it shouldn't be called.
allocator2<T> select_on_container_copy_construction() {
++selected;
return allocator2<T>();
}
};
void test_allocator2()
{
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 0);
}
// allocator 3
template <typename T>
struct ptr
{
T* value_;
ptr(void* v) : value_((T*) v) {}
T& operator*() const { return *value_; }
};
template <typename T>
struct allocator3
{
typedef T value_type;
typedef ptr<T> pointer;
typedef ptr<T const> const_pointer;
typedef unsigned short size_type;
ALLOCATOR_METHODS_TYPEDEFS(allocator3)
typedef yes_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
allocator3<T> select_on_container_copy_construction() const {
++selected;
return allocator3<T>();
}
};
void test_allocator3()
{
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, unsigned short>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, ptr<int> >));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
}
int main()
{
test_empty_allocator();
test_allocator1();
test_allocator2();
test_allocator3();
return boost::report_errors();
}