forked from boostorg/unordered
Merge pull request #56 from LeonineKing1199/feature/allocator-traits
Replace internal implementation of `allocation_traits` with Core's
This commit is contained in:
@ -13,6 +13,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/core/allocator_traits.hpp>
|
||||||
#include <boost/core/no_exceptions_support.hpp>
|
#include <boost/core/no_exceptions_support.hpp>
|
||||||
#include <boost/core/pointer_traits.hpp>
|
#include <boost/core/pointer_traits.hpp>
|
||||||
#include <boost/detail/select_type.hpp>
|
#include <boost/detail/select_type.hpp>
|
||||||
@ -1055,468 +1056,24 @@ namespace boost {
|
|||||||
//
|
//
|
||||||
// Allocator traits
|
// Allocator traits
|
||||||
//
|
//
|
||||||
// First our implementation, then later light wrappers around the alternatives
|
|
||||||
|
|
||||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
|
|
||||||
|
|
||||||
#include <boost/limits.hpp>
|
|
||||||
#include <boost/pointer_to_other.hpp>
|
|
||||||
#include <boost/utility/enable_if.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace unordered {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <typename Alloc, typename T> struct rebind_alloc;
|
|
||||||
|
|
||||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
|
||||||
|
|
||||||
template <template <typename, typename...> class Alloc, typename U,
|
|
||||||
typename T, typename... Args>
|
|
||||||
struct rebind_alloc<Alloc<U, Args...>, T>
|
|
||||||
{
|
|
||||||
typedef Alloc<T, Args...> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <template <typename> class Alloc, typename U, typename T>
|
|
||||||
struct rebind_alloc<Alloc<U>, T>
|
|
||||||
{
|
|
||||||
typedef Alloc<T> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <typename, typename> class Alloc, typename U,
|
|
||||||
typename T, typename A0>
|
|
||||||
struct rebind_alloc<Alloc<U, A0>, T>
|
|
||||||
{
|
|
||||||
typedef Alloc<T, A0> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <typename, typename, typename> class Alloc, typename U,
|
|
||||||
typename T, typename A0, typename A1>
|
|
||||||
struct rebind_alloc<Alloc<U, A0, A1>, T>
|
|
||||||
{
|
|
||||||
typedef Alloc<T, A0, A1> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename Alloc, typename T> struct rebind_wrap
|
|
||||||
{
|
|
||||||
template <typename X>
|
|
||||||
static choice1::type test(
|
|
||||||
choice1, typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
|
|
||||||
template <typename X> static choice2::type test(choice2, void* = 0);
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
value = (1 == sizeof(test<Alloc>(choose())))
|
|
||||||
};
|
|
||||||
|
|
||||||
struct fallback
|
|
||||||
{
|
|
||||||
template <typename U> struct rebind
|
|
||||||
{
|
|
||||||
typedef typename rebind_alloc<Alloc, T>::type other;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef
|
|
||||||
typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE then<
|
|
||||||
Alloc, fallback>::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace unordered {
|
|
||||||
namespace detail {
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
|
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(
|
|
||||||
propagate_on_container_copy_assignment);
|
|
||||||
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)
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(
|
|
||||||
select_on_container_copy_construction, U const, (), 0);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(max_size, U const, (), 0);
|
|
||||||
|
|
||||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
|
||||||
|
|
||||||
template <typename T, typename ValueType, typename... Args>
|
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(construct, U,
|
|
||||||
(boost::unordered::detail::make<ValueType*>(),
|
|
||||||
std::declval<Args>()...),
|
|
||||||
2);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <typename T, typename ValueType>
|
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(construct, U,
|
|
||||||
(boost::unordered::detail::make<ValueType*>(),
|
|
||||||
boost::unordered::detail::make<ValueType const>()),
|
|
||||||
2);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename T, typename ValueType>
|
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(
|
|
||||||
destroy, U, (boost::unordered::detail::make<ValueType*>()), 1);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
|
|
||||||
|
|
||||||
template <typename T> BOOST_UNORDERED_HAS_MEMBER(max_size);
|
|
||||||
|
|
||||||
template <typename T, typename ValueType>
|
|
||||||
BOOST_UNORDERED_HAS_MEMBER(construct);
|
|
||||||
|
|
||||||
template <typename T, typename ValueType>
|
|
||||||
BOOST_UNORDERED_HAS_MEMBER(destroy);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace unordered {
|
|
||||||
namespace detail {
|
|
||||||
namespace func {
|
|
||||||
|
|
||||||
template <typename Alloc>
|
|
||||||
inline typename boost::enable_if<
|
|
||||||
boost::unordered::detail::has_select_on_container_copy_construction<
|
|
||||||
Alloc>,
|
|
||||||
Alloc>::type
|
|
||||||
call_select_on_container_copy_construction(const Alloc& rhs)
|
|
||||||
{
|
|
||||||
return rhs.select_on_container_copy_construction();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Alloc>
|
|
||||||
inline typename boost::disable_if<
|
|
||||||
boost::unordered::detail::has_select_on_container_copy_construction<
|
|
||||||
Alloc>,
|
|
||||||
Alloc>::type
|
|
||||||
call_select_on_container_copy_construction(const Alloc& rhs)
|
|
||||||
{
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename SizeType, typename Alloc>
|
|
||||||
inline typename boost::enable_if<
|
|
||||||
boost::unordered::detail::has_max_size<Alloc>, SizeType>::type
|
|
||||||
call_max_size(const Alloc& a)
|
|
||||||
{
|
|
||||||
return a.max_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename SizeType, typename Alloc>
|
|
||||||
inline typename boost::disable_if<
|
|
||||||
boost::unordered::detail::has_max_size<Alloc>, SizeType>::type
|
|
||||||
call_max_size(const Alloc&)
|
|
||||||
{
|
|
||||||
return (std::numeric_limits<SizeType>::max)();
|
|
||||||
}
|
|
||||||
} // namespace func.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace unordered {
|
|
||||||
namespace detail {
|
|
||||||
template <typename Alloc> struct allocator_traits
|
|
||||||
{
|
|
||||||
typedef Alloc allocator_type;
|
|
||||||
typedef typename Alloc::value_type value_type;
|
|
||||||
|
|
||||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
|
||||||
Alloc, pointer, value_type*) pointer;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct pointer_to_other : boost::pointer_to_other<pointer, T>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
|
|
||||||
typename pointer_to_other<const value_type>::type) const_pointer;
|
|
||||||
|
|
||||||
// typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
|
|
||||||
// typename pointer_to_other<void>::type)
|
|
||||||
// void_pointer;
|
|
||||||
//
|
|
||||||
// typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
|
|
||||||
// typename pointer_to_other<const void>::type)
|
|
||||||
// const_void_pointer;
|
|
||||||
|
|
||||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
|
||||||
Alloc, difference_type, std::ptrdiff_t) difference_type;
|
|
||||||
|
|
||||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(
|
|
||||||
Alloc, size_type, std::size_t) size_type;
|
|
||||||
|
|
||||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
|
||||||
template <typename T>
|
|
||||||
using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using rebind_traits =
|
|
||||||
boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static pointer allocate(Alloc& a, size_type n) { return a.allocate(n); }
|
|
||||||
|
|
||||||
// I never use this, so I'll just comment it out for now.
|
|
||||||
//
|
|
||||||
// static pointer allocate(Alloc& a, size_type n,
|
|
||||||
// const_void_pointer hint)
|
|
||||||
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
|
|
||||||
|
|
||||||
static void deallocate(Alloc& a, pointer p, size_type n)
|
|
||||||
{
|
|
||||||
a.deallocate(p, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
#if BOOST_UNORDERED_CXX11_CONSTRUCTION
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
static
|
|
||||||
typename boost::enable_if_c<boost::unordered::detail::has_construct<
|
|
||||||
Alloc, T, Args...>::value>::type
|
|
||||||
construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
|
|
||||||
{
|
|
||||||
a.construct(p, boost::forward<Args>(x)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
static
|
|
||||||
typename boost::disable_if_c<boost::unordered::detail::has_construct<
|
|
||||||
Alloc, T, Args...>::value>::type
|
|
||||||
construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
|
|
||||||
{
|
|
||||||
new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::enable_if_c<
|
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
|
||||||
destroy(Alloc& a, T* p)
|
|
||||||
{
|
|
||||||
a.destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::disable_if_c<
|
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
|
||||||
destroy(Alloc&, T* p)
|
|
||||||
{
|
|
||||||
boost::unordered::detail::func::destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif !defined(BOOST_NO_SFINAE_EXPR)
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::enable_if_c<
|
|
||||||
boost::unordered::detail::has_construct<Alloc, T>::value>::type
|
|
||||||
construct(Alloc& a, T* p, T const& x)
|
|
||||||
{
|
|
||||||
a.construct(p, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::disable_if_c<
|
|
||||||
boost::unordered::detail::has_construct<Alloc, T>::value>::type
|
|
||||||
construct(Alloc&, T* p, T const& x)
|
|
||||||
{
|
|
||||||
new (static_cast<void*>(p)) T(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::enable_if_c<
|
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
|
||||||
destroy(Alloc& a, T* p)
|
|
||||||
{
|
|
||||||
a.destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::disable_if_c<
|
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
|
||||||
destroy(Alloc&, T* p)
|
|
||||||
{
|
|
||||||
boost::unordered::detail::func::destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// If we don't have SFINAE expressions, only call construct for the
|
|
||||||
// copy constructor for the allocator's value_type - as that's
|
|
||||||
// the only construct method that old fashioned allocators support.
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::enable_if_c<
|
|
||||||
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
|
||||||
boost::is_same<T, value_type>::value,
|
|
||||||
void>::type
|
|
||||||
construct(Alloc& a, T* p, T const& x)
|
|
||||||
{
|
|
||||||
a.construct(p, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::disable_if_c<
|
|
||||||
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
|
||||||
boost::is_same<T, value_type>::value,
|
|
||||||
void>::type
|
|
||||||
construct(Alloc&, T* p, T const& x)
|
|
||||||
{
|
|
||||||
new (static_cast<void*>(p)) T(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::enable_if_c<
|
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
|
||||||
boost::is_same<T, value_type>::value,
|
|
||||||
void>::type
|
|
||||||
destroy(Alloc& a, T* p)
|
|
||||||
{
|
|
||||||
a.destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename boost::disable_if_c<
|
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
|
||||||
boost::is_same<T, value_type>::value,
|
|
||||||
void>::type
|
|
||||||
destroy(Alloc&, T* p)
|
|
||||||
{
|
|
||||||
boost::unordered::detail::func::destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static size_type max_size(const Alloc& a)
|
|
||||||
{
|
|
||||||
return boost::unordered::detail::func::call_max_size<size_type>(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocator propagation on construction
|
|
||||||
|
|
||||||
static Alloc select_on_container_copy_construction(Alloc const& rhs)
|
|
||||||
{
|
|
||||||
return boost::unordered::detail::func::
|
|
||||||
call_select_on_container_copy_construction(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocator propagation on assignment and swap.
|
|
||||||
// Return true if lhs is modified.
|
|
||||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc,
|
|
||||||
propagate_on_container_copy_assignment,
|
|
||||||
false_type) propagate_on_container_copy_assignment;
|
|
||||||
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc,
|
|
||||||
propagate_on_container_move_assignment,
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
|
|
||||||
#undef BOOST_UNORDERED_DEFAULT_TYPE
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// std::allocator_traits
|
|
||||||
|
|
||||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
typedef typename std::allocator_traits<Alloc>::template rebind_alloc<T>
|
|
||||||
type;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// boost::container::allocator_traits
|
|
||||||
|
|
||||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
|
||||||
|
|
||||||
#include <boost/container/allocator_traits.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace unordered {
|
namespace unordered {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename Alloc>
|
template <typename Alloc>
|
||||||
struct allocator_traits : boost::container::allocator_traits<Alloc>
|
struct allocator_traits : boost::allocator_traits<Alloc>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Alloc, typename T>
|
template <typename Alloc, typename T>
|
||||||
struct rebind_wrap : boost::container::allocator_traits<
|
struct rebind_wrap : boost::allocator_rebind<Alloc, T>
|
||||||
Alloc>::template portable_rebind_alloc<T>
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Functions used to construct nodes. Emulates variadic construction,
|
// Functions used to construct nodes. Emulates variadic construction,
|
||||||
// piecewise construction etc.
|
// piecewise construction etc.
|
||||||
|
@ -213,7 +213,15 @@ void test_allocator2()
|
|||||||
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
|
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
|
||||||
BOOST_TEST(!traits::propagate_on_container_swap::value);
|
BOOST_TEST(!traits::propagate_on_container_swap::value);
|
||||||
BOOST_TEST(!traits::is_always_equal::value);
|
BOOST_TEST(!traits::is_always_equal::value);
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||||
|
// conditionally compile this assertion as all C++03 emulations of expression
|
||||||
|
// SFINAE are broken one way or another and the benefits of using Core's
|
||||||
|
// `allocator_traits` outweigh the costs of breaking this kind of code (i.e.
|
||||||
|
// inheriting SOCCC via a base)
|
||||||
|
//
|
||||||
BOOST_TEST(call_select<allocator>() == 1);
|
BOOST_TEST(call_select<allocator>() == 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocator 3
|
// allocator 3
|
||||||
|
Reference in New Issue
Block a user