Avoid exposing functions via ADL.

I'd put the iterators in their own namespace so that they wouldn't pick
up functions in detail via ADL, but I forgot that their template
parameters would cause that to happen anyway. The simplest way to fix
that for now is just to stuff the problematic functions into a
sub-namespace, so that they're no longer exposed.

[SVN r85280]
This commit is contained in:
Daniel James
2013-08-10 13:09:08 +00:00
parent 29660f9c4d
commit 3508ceaa58
4 changed files with 45 additions and 34 deletions

View File

@ -234,9 +234,11 @@ namespace boost { namespace unordered { namespace detail {
#pragma warning(disable:4100) // unreferenced formal parameter #pragma warning(disable:4100) // unreferenced formal parameter
#endif #endif
template <class T> namespace func {
inline void destroy(T* x) { template <class T>
x->~T(); inline void destroy(T* x) {
x->~T();
}
} }
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
@ -257,13 +259,12 @@ namespace boost { namespace unordered { namespace detail {
template <typename T, unsigned int> struct expr_test; template <typename T, unsigned int> struct expr_test;
template <typename T> struct expr_test<T, sizeof(char)> : T {}; 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) \ # define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
template <typename U> \ template <typename U> \
static typename boost::unordered::detail::expr_test< \ static typename boost::unordered::detail::expr_test< \
BOOST_PP_CAT(choice, result), \ BOOST_PP_CAT(choice, result), \
sizeof(boost::unordered::detail::for_expr_test(( \ sizeof(for_expr_test(( \
(expression), \ (expression), \
0)))>::type test( \ 0)))>::type test( \
BOOST_PP_CAT(choice, count)) BOOST_PP_CAT(choice, count))
@ -276,6 +277,7 @@ namespace boost { namespace unordered { namespace detail {
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \ # define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
struct BOOST_PP_CAT(has_, name) \ struct BOOST_PP_CAT(has_, name) \
{ \ { \
template <typename U> static char for_expr_test(U const&); \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \ BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
boost::unordered::detail::make< thing >().name args); \ boost::unordered::detail::make< thing >().name args); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \ BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
@ -473,6 +475,9 @@ namespace boost { namespace unordered { namespace detail {
# endif # endif
namespace func
{
template <typename Alloc> template <typename Alloc>
inline Alloc call_select_on_container_copy_construction(const Alloc& rhs, inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
typename boost::enable_if_c< typename boost::enable_if_c<
@ -510,6 +515,8 @@ namespace boost { namespace unordered { namespace detail {
return (std::numeric_limits<SizeType>::max)(); return (std::numeric_limits<SizeType>::max)();
} }
} // namespace func.
template <typename Alloc> template <typename Alloc>
struct allocator_traits struct allocator_traits
{ {
@ -589,7 +596,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p) destroy(Alloc&, T* p)
{ {
boost::unordered::detail::destroy(p); boost::unordered::detail::func::destroy(p);
} }
# elif !defined(BOOST_NO_SFINAE_EXPR) # elif !defined(BOOST_NO_SFINAE_EXPR)
@ -623,7 +630,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p) destroy(Alloc&, T* p)
{ {
boost::unordered::detail::destroy(p); boost::unordered::detail::func::destroy(p);
} }
# else # else
@ -669,21 +676,22 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value, boost::is_same<T, value_type>::value,
void*>::type = 0) void*>::type = 0)
{ {
boost::unordered::detail::destroy(p); boost::unordered::detail::func::destroy(p);
} }
# endif # endif
static size_type max_size(const Alloc& a) static size_type max_size(const Alloc& a)
{ {
return boost::unordered::detail::call_max_size<size_type>(a); return boost::unordered::detail::func::
call_max_size<size_type>(a);
} }
// Allocator propagation on construction // Allocator propagation on construction
static Alloc select_on_container_copy_construction(Alloc const& rhs) static Alloc select_on_container_copy_construction(Alloc const& rhs)
{ {
return boost::unordered::detail:: return boost::unordered::detail::func::
call_select_on_container_copy_construction(rhs); call_select_on_container_copy_construction(rhs);
} }
@ -758,7 +766,7 @@ namespace boost { namespace unordered { namespace detail {
#endif #endif
namespace boost { namespace unordered { namespace detail { namespace boost { namespace unordered { namespace detail { namespace func {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// call_construct // call_construct
@ -792,7 +800,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename Alloc, typename T> template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) { inline void destroy_value_impl(Alloc&, T* x) {
boost::unordered::detail::destroy(x); boost::unordered::detail::func::destroy(x);
} }
@ -802,7 +810,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename Alloc, typename T> template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) { inline void destroy_value_impl(Alloc&, T* x) {
boost::unordered::detail::destroy(x); boost::unordered::detail::func::destroy(x);
} }
#endif #endif
@ -818,7 +826,7 @@ namespace boost { namespace unordered { namespace detail {
template<typename Alloc, typename T> \ template<typename Alloc, typename T> \
void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \ void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
{ \ { \
boost::unordered::detail::call_construct(alloc, ptr); \ boost::unordered::detail::func::call_construct(alloc, ptr); \
} \ } \
\ \
BOOST_PP_REPEAT_FROM_TO(1, n, \ BOOST_PP_REPEAT_FROM_TO(1, n, \
@ -830,7 +838,7 @@ namespace boost { namespace unordered { namespace detail {
void construct_from_tuple(Alloc& alloc, T* ptr, \ void construct_from_tuple(Alloc& alloc, T* ptr, \
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \ namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \ { \
boost::unordered::detail::call_construct(alloc, ptr, \ boost::unordered::detail::func::call_construct(alloc, ptr, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
); \ ); \
} }
@ -945,7 +953,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
inline void construct_value_impl(Alloc& alloc, T* address, inline void construct_value_impl(Alloc& alloc, T* address,
BOOST_FWD_REF(Args)... args) BOOST_FWD_REF(Args)... args)
{ {
boost::unordered::detail::call_construct(alloc, boost::unordered::detail::func::call_construct(alloc,
address, boost::forward<Args>(args)...); address, boost::forward<Args>(args)...);
} }
@ -960,9 +968,9 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
construct_value_impl(Alloc& alloc, std::pair<A, B>* address, construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
boost::unordered::detail::construct_from_tuple(alloc, boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->first), boost::forward<A1>(a1)); boost::addressof(address->first), boost::forward<A1>(a1));
boost::unordered::detail::construct_from_tuple(alloc, boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->second), boost::forward<A2>(a2)); boost::addressof(address->second), boost::forward<A2>(a2));
} }
@ -1032,19 +1040,15 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args, boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
typename enable_if<use_piecewise<A0>, void*>::type = 0) typename enable_if<use_piecewise<A0>, void*>::type = 0)
{ {
boost::unordered::detail::construct_from_tuple(alloc, boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->first), args.a1); boost::addressof(address->first), args.a1);
boost::unordered::detail::construct_from_tuple(alloc, boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->second), args.a2); boost::addressof(address->second), args.a2);
} }
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
}}} }}}}
////////////////////////////////////////////////////////////////////////////////
//
// Some helper functions for allocating & constructing
namespace boost { namespace unordered { namespace detail { namespace boost { namespace unordered { namespace detail {

View File

@ -32,6 +32,10 @@ namespace boost { namespace unordered { namespace detail {
}}} }}}
// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
// in the detail namespace. It didn't work because the template parameters
// were in detail. I'm not changing it at the moment to be safe. I might
// do in the future if I change the iterator types.
namespace boost { namespace unordered { namespace iterator_detail { namespace boost { namespace unordered { namespace iterator_detail {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -353,7 +357,7 @@ namespace boost { namespace unordered { namespace detail {
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS) void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
{ {
construct(); construct();
boost::unordered::detail::construct_value_impl( boost::unordered::detail::func::construct_value_impl(
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true; value_constructed_ = true;
} }
@ -362,7 +366,7 @@ namespace boost { namespace unordered { namespace detail {
void construct_with_value2(BOOST_FWD_REF(A0) a0) void construct_with_value2(BOOST_FWD_REF(A0) a0)
{ {
construct(); construct();
boost::unordered::detail::construct_value_impl( boost::unordered::detail::func::construct_value_impl(
alloc_, node_->value_ptr(), alloc_, node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0))); BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
value_constructed_ = true; value_constructed_ = true;
@ -392,7 +396,7 @@ namespace boost { namespace unordered { namespace detail {
{ {
if (node_) { if (node_) {
if (value_constructed_) { if (value_constructed_) {
boost::unordered::detail::destroy_value_impl(alloc_, boost::unordered::detail::func::destroy_value_impl(alloc_,
node_->value_ptr()); node_->value_ptr());
} }
@ -424,7 +428,7 @@ namespace boost { namespace unordered { namespace detail {
if (value_constructed_) if (value_constructed_)
{ {
boost::unordered::detail::destroy_value_impl(alloc_, boost::unordered::detail::func::destroy_value_impl(alloc_,
node_->value_ptr()); node_->value_ptr());
value_constructed_ = false; value_constructed_ = false;
} }
@ -541,7 +545,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_; node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_); nodes_ = static_cast<node_pointer>(p->next_);
boost::unordered::detail::destroy_value_impl(this->alloc_, boost::unordered::detail::func::destroy_value_impl(this->alloc_,
p->value_ptr()); p->value_ptr());
node_allocator_traits::destroy(this->alloc_, boost::addressof(*p)); node_allocator_traits::destroy(this->alloc_, boost::addressof(*p));
node_allocator_traits::deallocate(this->alloc_, p, 1); node_allocator_traits::deallocate(this->alloc_, p, 1);
@ -736,7 +740,7 @@ namespace boost { namespace unordered { namespace detail {
void destroy(bool which) void destroy(bool which)
{ {
boost::unordered::detail::destroy((function_pair*)(&funcs_[which])); boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
} }
public: public:

View File

@ -456,7 +456,7 @@ namespace boost { namespace unordered { namespace detail {
void swap_allocators(table& other, false_type) void swap_allocators(table& other, false_type)
{ {
boost::unordered::detail::ignore_unused_variable_warning(other); boost::unordered::detail::func::ignore_unused_variable_warning(other);
// According to 23.2.1.8, if propagate_on_container_swap is // According to 23.2.1.8, if propagate_on_container_swap is
// false the behaviour is undefined unless the allocators // false the behaviour is undefined unless the allocators
@ -516,7 +516,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = static_cast<node_pointer>(prev->next_); node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_; prev->next_ = n->next_;
boost::unordered::detail::destroy_value_impl(node_alloc(), boost::unordered::detail::func::destroy_value_impl(node_alloc(),
n->value_ptr()); n->value_ptr());
node_allocator_traits::destroy(node_alloc(), node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n)); boost::addressof(*n));

View File

@ -28,7 +28,10 @@ namespace boost { namespace unordered { namespace detail {
struct move_tag {}; struct move_tag {};
struct empty_emplace {}; struct empty_emplace {};
template <class T> inline void ignore_unused_variable_warning(T const&) {} namespace func {
template <class T>
inline void ignore_unused_variable_warning(T const&) {}
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// iterator SFINAE // iterator SFINAE