Implement allocator_traits::is_always_equal

This commit is contained in:
Daniel James
2018-01-03 20:55:40 +00:00
parent 9d558b010d
commit be0acc575f
2 changed files with 95 additions and 66 deletions

View File

@ -864,6 +864,78 @@ namespace boost {
#endif
////////////////////////////////////////////////////////////////////////////
// TRAITS TYPE DEDETION MECHANISM
//
// Used to implement traits that use a type if present, or a
// default otherwise.
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> struct default_type_##tname \
{ \
\
template <typename X> \
static choice1::type test(choice1, 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 typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE \
then<Tp, DefaultWrap>::type::tname type; \
}
#else
namespace boost {
namespace unordered {
namespace detail {
template <typename T, typename T2> struct sfinae : T2
{
};
}
}
}
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> struct default_type_##tname \
{ \
\
template <typename X> \
static typename boost::unordered::detail::sfinae<typename X::tname, \
choice1>::type test(choice1); \
\
template <typename X> static choice2::type test(choice2); \
\
struct DefaultWrap \
{ \
typedef Default tname; \
}; \
\
enum \
{ \
value = (1 == sizeof(test<Tp>(choose()))) \
}; \
\
typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE \
then<Tp, DefaultWrap>::type::tname type; \
}
#endif
#define BOOST_UNORDERED_DEFAULT_TYPE(T, tname, arg) \
typename default_type_##tname<T, arg>::type
////////////////////////////////////////////////////////////////////////////////
//
// Allocator traits
@ -943,72 +1015,6 @@ namespace boost {
}
}
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> struct default_type_##tname \
{ \
\
template <typename X> \
static choice1::type test(choice1, 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 typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE \
then<Tp, DefaultWrap>::type::tname type; \
}
#else
namespace boost {
namespace unordered {
namespace detail {
template <typename T, typename T2> struct sfinae : T2
{
};
}
}
}
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> struct default_type_##tname \
{ \
\
template <typename X> \
static typename boost::unordered::detail::sfinae<typename X::tname, \
choice1>::type test(choice1); \
\
template <typename X> static choice2::type test(choice2); \
\
struct DefaultWrap \
{ \
typedef Default tname; \
}; \
\
enum \
{ \
value = (1 == sizeof(test<Tp>(choose()))) \
}; \
\
typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE \
then<Tp, DefaultWrap>::type::tname type; \
}
#endif
#define BOOST_UNORDERED_DEFAULT_TYPE(T, tname, arg) \
typename default_type_##tname<T, arg>::type
namespace boost {
namespace unordered {
namespace detail {
@ -1023,6 +1029,7 @@ namespace boost {
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(
propagate_on_container_move_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(is_always_equal);
#if !defined(BOOST_NO_SFINAE_EXPR)
@ -1319,6 +1326,9 @@ namespace boost {
false_type) propagate_on_container_move_assignment;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, propagate_on_container_swap,
false_type) propagate_on_container_swap;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, is_always_equal,
typename boost::is_empty<Alloc>::type) is_always_equal;
};
}
}
@ -1339,9 +1349,20 @@ namespace boost {
namespace unordered {
namespace detail {
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(is_always_equal);
template <typename Alloc>
struct allocator_traits : std::allocator_traits<Alloc>
{
// As is_always_equal was introduced in C++17, std::allocator_traits
// doesn't always have it. So use it when available, implement it
// ourselves when not. Would be simpler not to bother with
// std::allocator_traits, but I feel like I should try to use
// it where possible.
typedef BOOST_UNORDERED_DEFAULT_TYPE(std::allocator_traits<Alloc>,
is_always_equal,
BOOST_UNORDERED_DEFAULT_TYPE(Alloc, is_always_equal,
typename boost::is_empty<Alloc>::type)) is_always_equal;
};
template <typename Alloc, typename T> struct rebind_wrap

View File

@ -126,6 +126,7 @@ void test_empty_allocator()
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(traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 0);
}
@ -139,6 +140,7 @@ template <typename T> struct allocator1
typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap;
typedef yes_type is_always_equal;
allocator1<T> select_on_container_copy_construction() const
{
@ -166,6 +168,7 @@ void test_allocator1()
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(traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
@ -192,6 +195,7 @@ template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap;
typedef no_type is_always_equal;
};
void test_allocator2()
@ -208,6 +212,7 @@ void test_allocator2()
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(!traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
@ -240,6 +245,8 @@ template <typename T> struct allocator3
typedef ptr<T const> const_pointer;
typedef unsigned short size_type;
int x; // Just to make it non-empty, so that is_always_equal is false.
ALLOCATOR_METHODS_TYPEDEFS(allocator3)
typedef yes_type propagate_on_container_copy_assignment;
@ -267,6 +274,7 @@ void test_allocator3()
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(!traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}