forked from boostorg/unordered
Unordered: Merge from trunk.
Portability fixes, and fix some issues with constructing std::pair. [SVN r74101]
This commit is contained in:
@ -5,8 +5,8 @@
|
||||
// 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)
|
||||
//
|
||||
// Written by Daniel James using some code from Pablo Halpern's
|
||||
// allocator traits implementation.
|
||||
// Allocator traits written by Daniel James based on Pablo Halpern's
|
||||
// implementation.
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
|
||||
@ -18,6 +18,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/select_type.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
|
||||
&& !defined(__BORLANDC__)
|
||||
@ -81,38 +82,39 @@ namespace boost { namespace unordered { namespace detail {
|
||||
};
|
||||
# endif
|
||||
|
||||
struct convertible_from_anything
|
||||
{
|
||||
template<typename T> convertible_from_anything(T const&);
|
||||
};
|
||||
template <typename T> T& make();
|
||||
struct choice9 { typedef char (&type)[9]; };
|
||||
struct choice8 : choice9 { typedef char (&type)[8]; };
|
||||
struct choice7 : choice8 { typedef char (&type)[7]; };
|
||||
struct choice6 : choice7 { typedef char (&type)[6]; };
|
||||
struct choice5 : choice6 { typedef char (&type)[5]; };
|
||||
struct choice4 : choice5 { typedef char (&type)[4]; };
|
||||
struct choice3 : choice4 { typedef char (&type)[3]; };
|
||||
struct choice2 : choice3 { typedef char (&type)[2]; };
|
||||
struct choice1 : choice2 { typedef char (&type)[1]; };
|
||||
choice1 choose();
|
||||
|
||||
typedef char (&no_type)[1];
|
||||
typedef char (&yes_type)[2];
|
||||
|
||||
template <typename T> struct sfinae {
|
||||
typedef yes_type type;
|
||||
};
|
||||
|
||||
// Infrastructure for providing a default type for Tp::tname if absent.
|
||||
#define BOOST_DEFAULT_TYPE_TMPLT(tname) \
|
||||
template <typename Tp, typename Default> \
|
||||
struct default_type_ ## tname { \
|
||||
template <typename T> \
|
||||
static BOOST_DEDUCED_TYPENAME sfinae< \
|
||||
BOOST_DEDUCED_TYPENAME T::tname>::type test(int); \
|
||||
template <typename T> \
|
||||
static no_type test(long); \
|
||||
\
|
||||
enum { value = sizeof(test<Tp>(0)) == sizeof(yes_type) }; \
|
||||
template <typename X> \
|
||||
static choice1::type test(choice1, \
|
||||
BOOST_DEDUCED_TYPENAME X::tname* = 0); \
|
||||
\
|
||||
template <typename X> \
|
||||
static choice2::type test(choice2, void* = 0); \
|
||||
\
|
||||
struct DefaultWrap { typedef Default tname; }; \
|
||||
\
|
||||
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
|
||||
\
|
||||
typedef BOOST_DEDUCED_TYPENAME \
|
||||
boost::detail::if_true<value>:: \
|
||||
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
|
||||
::type::tname type; \
|
||||
}
|
||||
|
||||
|
||||
#define BOOST_DEFAULT_TYPE(T,tname, arg) \
|
||||
BOOST_DEDUCED_TYPENAME default_type_ ## tname<T, arg>::type
|
||||
|
||||
@ -127,47 +129,62 @@ namespace boost { namespace unordered { namespace detail {
|
||||
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
|
||||
// Specialization is only needed for Visual C++. Without it SFINAE doesn't
|
||||
// kick in.
|
||||
template <unsigned int>
|
||||
struct expr_sfinae;
|
||||
|
||||
template <>
|
||||
struct expr_sfinae<sizeof(yes_type)> {
|
||||
typedef yes_type type;
|
||||
};
|
||||
|
||||
|
||||
template <typename T, unsigned int> struct expr_test;
|
||||
template <typename T> struct expr_test<T, sizeof(char)> : T {};
|
||||
template <typename U> static char for_expr_test(U const&);
|
||||
|
||||
#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
|
||||
template <typename U> \
|
||||
static typename expr_test< \
|
||||
BOOST_PP_CAT(choice, result), \
|
||||
sizeof(for_expr_test(((expression), 0)))>::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
|
||||
template <typename U> \
|
||||
static BOOST_PP_CAT(choice, result)::type test( \
|
||||
BOOST_PP_CAT(choice, count))
|
||||
|
||||
template <typename T>
|
||||
struct has_select_on_container_copy_construction
|
||||
{
|
||||
// This needs to be a template for Visual C++.
|
||||
template <typename T2>
|
||||
static yes_type to_yes_type(const T2&);
|
||||
|
||||
template <typename T2>
|
||||
static typename expr_sfinae<sizeof(to_yes_type(
|
||||
((T2 const*)0)->select_on_container_copy_construction()
|
||||
))>::type check(T2*);
|
||||
|
||||
static no_type check(void*);
|
||||
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, make<U const>().select_on_container_copy_construction());
|
||||
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2);
|
||||
|
||||
enum { value = sizeof(check((T*) 0)) == sizeof(yes_type) };
|
||||
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename T> struct identity { typedef T type; };
|
||||
|
||||
#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
|
||||
\
|
||||
typedef typename identity<member>::type BOOST_PP_CAT(check, count); \
|
||||
\
|
||||
template <BOOST_PP_CAT(check, count) e> \
|
||||
struct BOOST_PP_CAT(test, count) { \
|
||||
typedef void* type; \
|
||||
}; \
|
||||
\
|
||||
template <class U> static BOOST_PP_CAT(choice, result)::type \
|
||||
test(BOOST_PP_CAT(choice, count), \
|
||||
typename BOOST_PP_CAT(test, count)< \
|
||||
&U::name>::type = 0)
|
||||
|
||||
#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
|
||||
template <class U> static BOOST_PP_CAT(choice, result)::type \
|
||||
test(BOOST_PP_CAT(choice, count), void* = 0)
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct has_select_on_container_copy_construction
|
||||
{
|
||||
typedef T (T::*SelectFunc)() const;
|
||||
|
||||
template <SelectFunc e> struct sfinae { typedef yes_type type; };
|
||||
|
||||
template <class U>
|
||||
static typename sfinae<&U::select_on_container_copy_construction>::type
|
||||
test(int);
|
||||
template <class U>
|
||||
static no_type test(...);
|
||||
BOOST_UNORDERED_CHECK_MEMBER(1, 1, select_on_container_copy_construction, T (T::*)() const);
|
||||
BOOST_UNORDERED_DEFAULT_MEMBER(2, 2);
|
||||
|
||||
enum { value = sizeof(test<T>(1)) == sizeof(yes_type) };
|
||||
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -517,44 +517,139 @@ namespace boost { namespace unordered { namespace detail {
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Node Constructors
|
||||
|
||||
template <typename T, typename Arg1 = void>
|
||||
struct emulated_pair_constructor
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template <typename A, typename B>
|
||||
struct emulated_pair_constructor<std::pair<A, B>, void>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename Value>
|
||||
struct emulated_pair_constructor<std::pair<A, B>, Value>
|
||||
{
|
||||
static choice1::type check(choice1, std::pair<A, B> const&);
|
||||
static choice2::type check(choice2, A const&);
|
||||
|
||||
enum { value = sizeof(check(choose(), make<Value>())) - 1 };
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline void construct_impl(void* address)
|
||||
{
|
||||
new(address) T();
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
|
||||
template <class T, class... Args>
|
||||
inline void construct_impl(T*, void* address, Args&&... args)
|
||||
template <class T, class Arg1>
|
||||
inline void construct_impl(
|
||||
typename boost::disable_if<emulated_pair_constructor<T, Arg1>,
|
||||
void*>::type address,
|
||||
Arg1&& a1)
|
||||
{
|
||||
new(address) T(std::forward<Args>(args)...);
|
||||
new(address) T(std::forward<Arg1>(a1));
|
||||
}
|
||||
|
||||
template <class T, class Arg1>
|
||||
inline void construct_impl(
|
||||
typename boost::enable_if<emulated_pair_constructor<T, Arg1>,
|
||||
void*>::type address,
|
||||
Arg1&& a1)
|
||||
{
|
||||
new(address) T(std::forward<Arg1>(a1), typename T::second_type());
|
||||
}
|
||||
|
||||
template <class T, class Arg1, class Arg2>
|
||||
inline void construct_impl(void* address, Arg1&& a1, Arg2&& a2)
|
||||
{
|
||||
new(address) T(std::forward<Arg1>(a1), std::forward<Arg2>(a2));
|
||||
}
|
||||
|
||||
template <class T, class Arg1, class Arg2, class... Args>
|
||||
inline typename boost::disable_if<emulated_pair_constructor<T>, void>::type
|
||||
construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
new(address) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T, class Arg1, class Arg2, class... Args>
|
||||
inline typename boost::enable_if<emulated_pair_constructor<T>, void>::type
|
||||
construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
new(address) T(std::forward<Arg1>(arg1),
|
||||
typename T::second_type(
|
||||
std::forward<Arg2>(arg2), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
class T, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
T*, void* address, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
) \
|
||||
{ \
|
||||
new(address) T( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
} \
|
||||
\
|
||||
template <class First, class Second, class Key, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
std::pair<First, Second>*, void* address, \
|
||||
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
new(address) std::pair<First, Second>(k, \
|
||||
Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
|
||||
template <class T, class Arg1>
|
||||
inline BOOST_DEDUCED_TYPENAME boost::disable_if<emulated_pair_constructor<T, Arg1>, void>::type
|
||||
construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
|
||||
{
|
||||
new(address) T(boost::forward<Arg1>(a1));
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
template <class T, class Arg1>
|
||||
inline BOOST_DEDUCED_TYPENAME boost::enable_if<emulated_pair_constructor<T, Arg1>, void>::type
|
||||
construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
|
||||
{
|
||||
new(address) T(
|
||||
boost::forward<Arg1>(a1),
|
||||
BOOST_DEDUCED_TYPENAME T::second_type()
|
||||
);
|
||||
}
|
||||
|
||||
template <class T, class Arg1, class Arg2>
|
||||
inline void construct_impl(void* address,
|
||||
BOOST_FWD_REF(Arg1) a1, BOOST_FWD_REF(Arg2) a2)
|
||||
{
|
||||
new(address) T(boost::forward<Arg1>(a1), boost::forward<Arg2>(a2));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
|
||||
template < \
|
||||
class T, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
BOOST_DEDUCED_TYPENAME \
|
||||
boost::disable_if<emulated_pair_constructor<T>, void*>::type \
|
||||
address, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
|
||||
) \
|
||||
{ \
|
||||
new(address) T( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
|
||||
template <class T, class Key, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
BOOST_DEDUCED_TYPENAME \
|
||||
boost::enable_if<emulated_pair_constructor<T>, void*>::type \
|
||||
address, \
|
||||
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
|
||||
{ \
|
||||
new(address) T(k, \
|
||||
BOOST_DEDUCED_TYPENAME \
|
||||
T::second_type(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
|
||||
#endif
|
||||
|
||||
@ -594,7 +689,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void construct(Args&&... args)
|
||||
{
|
||||
construct_preamble();
|
||||
construct_impl((value_type*) 0, node_->address(),
|
||||
construct_impl<value_type>(node_->address(),
|
||||
std::forward<Args>(args)...);
|
||||
value_constructed_ = true;
|
||||
}
|
||||
@ -609,8 +704,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
) \
|
||||
{ \
|
||||
construct_preamble(); \
|
||||
construct_impl( \
|
||||
(value_type*) 0, node_->address(), \
|
||||
construct_impl<value_type>(node_->address(), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
|
||||
); \
|
||||
value_constructed_ = true; \
|
||||
|
@ -167,7 +167,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
//
|
||||
// Or from rehash post-condition:
|
||||
// count > size / mlf_
|
||||
return next_prime(double_to_size_t(floor(size / (double) mlf_)) + 1);
|
||||
return next_prime(double_to_size_t(floor(
|
||||
static_cast<double>(size) /
|
||||
static_cast<double>(mlf_))) + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -451,7 +453,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
else {
|
||||
// no throw:
|
||||
min_buckets = next_prime((std::max)(min_buckets,
|
||||
double_to_size_t(floor(this->size_ / (double) mlf_)) + 1));
|
||||
double_to_size_t(floor(
|
||||
static_cast<double>(this->size_) /
|
||||
static_cast<double>(mlf_))) + 1));
|
||||
if(min_buckets != this->bucket_count_) {
|
||||
this->rehash_impl(min_buckets);
|
||||
this->max_load_ = calculate_max_load();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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:
|
||||
|
@ -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 ]
|
||||
|
227
test/unordered/allocator_traits.cpp
Normal file
227
test/unordered/allocator_traits.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
|
||||
// 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>
|
||||
#include <boost/limits.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();
|
||||
}
|
@ -514,6 +514,85 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
|
||||
|
||||
#endif
|
||||
|
||||
struct overloaded_constructor
|
||||
{
|
||||
overloaded_constructor(int x1 = 1, int x2 = 2, int x3 = 3, int x4 = 4)
|
||||
: x1(x1), x2(x2), x3(x3), x4(x4) {}
|
||||
|
||||
int x1, x2, x3, x4;
|
||||
|
||||
bool operator==(overloaded_constructor const& rhs) const
|
||||
{
|
||||
return x1 == rhs.x1 && x2 == rhs.x2 && x3 == rhs.x3 && x4 == rhs.x4;
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(overloaded_constructor const& x)
|
||||
{
|
||||
std::size_t hash = 0;
|
||||
boost::hash_combine(hash, x.x1);
|
||||
boost::hash_combine(hash, x.x2);
|
||||
boost::hash_combine(hash, x.x3);
|
||||
boost::hash_combine(hash, x.x4);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
// This will actually be deprecated pretty soon.
|
||||
|
||||
UNORDERED_AUTO_TEST(map_emplace_test)
|
||||
{
|
||||
boost::unordered_map<int, overloaded_constructor> x;
|
||||
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(0) != x.end() &&
|
||||
x.find(0)->second == overloaded_constructor());
|
||||
|
||||
x.emplace(1);
|
||||
BOOST_TEST(x.find(1) != x.end() &&
|
||||
x.find(1)->second == overloaded_constructor());
|
||||
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
x.find(2)->second == overloaded_constructor(3));
|
||||
|
||||
x.emplace(4, 5, 6);
|
||||
BOOST_TEST(x.find(4) != x.end() &&
|
||||
x.find(4)->second == overloaded_constructor(5, 6));
|
||||
|
||||
x.emplace(7, 8, 9, 10);
|
||||
BOOST_TEST(x.find(7) != x.end() &&
|
||||
x.find(7)->second == overloaded_constructor(8, 9, 10));
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
{
|
||||
boost::unordered_set<overloaded_constructor> x;
|
||||
overloaded_constructor check;
|
||||
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
|
||||
x.clear();
|
||||
x.emplace(1);
|
||||
check = overloaded_constructor(1);
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
|
||||
x.clear();
|
||||
x.emplace(2, 3);
|
||||
check = overloaded_constructor(2, 3);
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
|
||||
x.clear();
|
||||
x.emplace(4, 5, 6);
|
||||
check = overloaded_constructor(4, 5, 6);
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
|
||||
x.clear();
|
||||
x.emplace(7, 8, 9, 10);
|
||||
check = overloaded_constructor(7, 8, 9, 10);
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -341,7 +341,10 @@ namespace unnecessary_copy_tests
|
||||
x.emplace(source<std::pair<count_copies, count_copies> >());
|
||||
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || \
|
||||
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
|
||||
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \
|
||||
(!defined(__GNUC__) && !defined(BOOST_MSVC))
|
||||
count_copies part;
|
||||
reset();
|
||||
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
|
||||
|
Reference in New Issue
Block a user