Files
boost_unordered/include/boost/unordered/detail/emplace_args.hpp
Daniel James dac1dc5837 Unordered: Reorganization to use void pointers and other things.
Helps allocators which can't use incomplete pointers, and avoid using
base pointers where that might not be possible.  And some other
reorganization. Storing arguments to emplace in a structure when
variadic template parameters aren't available. Changed some of the odd
design for working with older compilers.

[SVN r74742]
2011-10-05 19:45:14 +00:00

549 lines
20 KiB
C++

// Copyright (C) 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)
// See http://www.boost.org/libs/unordered for documentation
#ifndef BOOST_UNORDERED_EMPLACE_ARGS_HPP
#define BOOST_UNORDERED_EMPLACE_ARGS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/tuple/tuple.hpp>
#include <utility>
#if !defined(BOOST_NO_0X_HDR_TUPLE)
#include <tuple>
#elif defined(BOOST_HAS_TR1_TUPLE)
#include <tr1/tuple>
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4512) // assignment operator could not be generated.
#pragma warning(disable:4345) // behavior change: an object of POD type
// constructed with an initializer of the form ()
// will be default-initialized.
#endif
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
#if 0 && !defined(BOOST_NO_RVALUE_REFERENCES) && \
!defined(BOOST_NO_VARIADIC_TEMPLATES)
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
# elif defined(_LIBCPP_VERSION)
# define BOOST_UNORDERED_STD_FORWARD_MOVE
# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
# define BOOST_UNORDERED_STD_FORWARD_MOVE
# endif
# elif defined(__STL_CONFIG_H)
# elif defined(__MSL_CPP__)
# elif defined(__IBMCPP__)
# elif defined(MSIPL_COMPILE_H)
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
// Visual C++. A version check would be a good idea.
# define BOOST_UNORDERED_STD_FORWARD_MOVE
# endif
#endif
namespace boost { namespace unordered { namespace detail {
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args&&... args
#define BOOST_UNORDERED_EMPLACE_FORWARD std::forward<Args>(args)...
#else
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
#define BOOST_UNORDERED_EMPLACE_FORWARD args
#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
#define BOOST_UNORDERED_EARGS(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
struct BOOST_PP_CAT(emplace_args, n) \
{ \
BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
BOOST_PP_CAT(emplace_args, n) ( \
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, B, a) \
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
{} \
\
}; \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
inline BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, a)); \
return e; \
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(B, n); \
BOOST_PP_CAT(B, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)( \
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(a, n)))
#else
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
BOOST_PP_CAT(B, n); \
BOOST_PP_CAT(B, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n))
#endif
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
_)
#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
#undef BOOST_UNORDERED_EARGS_MEMBER
#undef BOOST_UNORDERED_EARGS_INIT
#endif
////////////////////////////////////////////////////////////////////////////
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
// e.g. for int
#if !defined(BOOST_NO_RVALUE_REFERENCES)
# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
#else
struct please_ignore_this_overload {
typedef please_ignore_this_overload type;
};
template <typename T>
struct rv_ref_impl {
typedef BOOST_RV_REF(T) type;
};
template <typename T>
struct rv_ref :
boost::detail::if_true<
boost::is_class<T>::value
>::BOOST_NESTED_TEMPLATE then <
rv_ref_impl<T>,
please_ignore_this_overload
>::type
{};
# define BOOST_UNORDERED_RV_REF(T) \
typename ::boost::unordered::detail::rv_ref<T>::type
#endif
////////////////////////////////////////////////////////////////////////////
//
// Value Construction
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
template<typename T> \
void construct_from_tuple(T* ptr, namespace_::tuple<>) \
{ \
new ((void*) ptr) T(); \
} \
\
BOOST_PP_REPEAT_FROM_TO(1, n, \
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
void construct_from_tuple(T* ptr, \
namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
new ((void*) ptr) T( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
); \
}
#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
namespace_::get<n>(x)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
#elif defined(BOOST_HAS_TR1_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1)
#endif
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
#undef BOOST_UNORDERED_GET_TUPLE_ARG
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct emulation1 {
static choice1::type check(choice1, std::pair<A, B> const&);
static choice2::type check(choice2, A const&);
static choice3::type check(choice3, ...);
enum { value =
sizeof(check(choose(), make<A0>())) == sizeof(choice2::type) };
};
#endif
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct check3_base {
static choice1::type check(choice1,
boost::unordered::piecewise_construct_t);
static choice2::type check(choice2, A const&);
static choice3::type check(choice3, ...);
};
#else
template <typename A, typename B, typename A0>
struct check3_base {
static choice1::type check(choice1,
boost::unordered::piecewise_construct_t);
static choice3::type check(choice3, ...);
};
#endif
template <typename A, typename B, typename A0>
struct piecewise3 {
enum { value =
sizeof(check3_base<A,B,A0>::check(choose(), make<A0>())) ==
sizeof(choice1::type) };
};
template <typename A, typename B, typename A0>
struct emulation3 {
enum { value =
sizeof(check3_base<A,B,A0>::check(choose(), make<A0>())) ==
sizeof(choice2::type) };
};
template <typename A, typename B, typename A0>
struct normal3 {
enum { value =
sizeof(check3_base<A,B,A0>::check(choose(), make<A0>())) ==
sizeof(choice3::type) };
};
template <typename T, typename A0>
struct pair_construct1 {};
template <typename T, typename A0>
struct normal_construct1 { typedef void type; };
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct pair_construct1<std::pair<A, B>, A0>
: enable_if<emulation1<A, B, A0>, void> {};
template <typename A, typename B, typename A0>
struct normal_construct1<std::pair<A, B>, A0>
: disable_if<emulation1<A, B, A0>, void> {};
#endif
template <typename T, typename A0>
struct piecewise_construct3 {};
template <typename A, typename B, typename A0>
struct piecewise_construct3<std::pair<A, B>, A0>
: enable_if<piecewise3<A, B, A0>, void> {};
template <typename T, typename A0>
struct pair_construct3 {};
template <typename A, typename B, typename A0>
struct pair_construct3<std::pair<A, B>, A0>
: enable_if<emulation3<A, B, A0>, void> {};
template <typename T, typename A0>
struct normal_construct3 { typedef void type; };
template <typename A, typename B, typename A0>
struct normal_construct3<std::pair<A, B>, A0>
: enable_if<normal3<A, B, A0>, void> {};
template <typename T>
struct pair_construct_n {};
template <typename T>
struct normal_construct_n { typedef void type; };
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B>
struct pair_construct_n<std::pair<A, B> > { typedef void type; };
template <typename A, typename B>
struct normal_construct_n<std::pair<A, B> > {};
#endif
template <typename T, typename A0>
inline typename normal_construct1<T, A0>::type
construct_impl2(void* address, BOOST_FWD_REF(A0) a0)
{
new(address) T(
boost::forward<A0>(a0)
);
}
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
////////////////////////////////////////////////////////////////////////////////
// Construct from variadic parameters
template <typename T>
inline void construct_impl(void* address)
{
new(address) T();
}
template <typename T, typename A0>
inline typename normal_construct1<T, A0>::type
construct_impl(void* address, A0&& a0)
{
new(address) T(
boost::forward<A0>(a0)
);
}
template <typename T, typename A0>
inline typename pair_construct1<T, A0>::type
construct_impl(void* address, A0&& a0)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<A0>(a0));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type();
}
template <typename T, typename A0, typename A1>
inline void construct_impl(void* address, A0&& a0, A1&& a1)
{
new(address) T(
boost::forward<A0>(a0),
boost::forward<A1>(a1));
}
template <typename T, typename A0, typename A1, typename A2>
inline typename piecewise_construct3<T, A0>::type
construct_impl(void* address, A0&&, A1&& a1, A2&& a2)
{
construct_from_tuple(
boost::addressof(static_cast<T*>(address)->first), a1);
construct_from_tuple(
boost::addressof(static_cast<T*>(address)->second), a2);
}
template <typename T, typename A0, typename A1, typename A2>
inline typename pair_construct3<T, A0>::type
construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<A0>(a0));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type(
boost::forward<A1>(a1),
boost::forward<A2>(a2));
}
template <typename T, typename A0, typename A1, typename A2>
inline typename normal_construct3<T, A0>::type
construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2)
{
new(address) T(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2));
}
template <typename T, typename A0, typename A1, typename A2, typename A3,
typename... Args>
inline typename normal_construct_n<T>::type
construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2,
A3&& a3, Args&&... args)
{
new(address) T(
std::forward<A0>(a0),
std::forward<A1>(a1),
std::forward<A2>(a2),
std::forward<A3>(a3),
std::forward<Args>(args)...);
}
template <typename T, typename A0, typename A1, typename A2, typename A3,
typename... Args>
inline typename pair_construct_n<T>::type
construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2,
A3&& a3, Args&&... args)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
std::forward<A0>(a0));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type(
std::forward<A1>(a1),
std::forward<A2>(a2),
std::forward<A3>(a3),
std::forward<Args>(args)...);
}
#else
////////////////////////////////////////////////////////////////////////////////
// Construct with emplace_args
template <typename T, typename A0>
inline typename normal_construct1<T, A0>::type
construct_impl(void* address,
::boost::unordered::detail::emplace_args1<A0> const& args)
{
new(address) T(
boost::forward<A0>(args.a0)
);
}
template <typename T, typename A0>
inline typename pair_construct1<T, A0>::type
construct_impl(void* address, A0 const& a0)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<A0>(a0));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type();
}
template <typename T, typename A0>
inline typename pair_construct1<T, A0>::type
construct_impl(void* address,
::boost::unordered::detail::emplace_args1<A0> const& args)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<A0>(args.a0));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type();
}
template <typename T, typename A0, typename A1>
inline void construct_impl(void* address,
::boost::unordered::detail::emplace_args2<A0, A1> const& args)
{
new(address) T(
boost::forward<A0>(args.a0),
boost::forward<A1>(args.a1));
}
template <typename T, typename A0, typename A1, typename A2>
inline typename piecewise_construct3<T, A0>::type
construct_impl(void* address,
::boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
construct_from_tuple(
boost::addressof(static_cast<T*>(address)->first), args.a1);
construct_from_tuple(
boost::addressof(static_cast<T*>(address)->second), args.a2);
}
template <typename T, typename A0, typename A1, typename A2>
inline typename pair_construct3<T, A0>::type
construct_impl(void* address,
::boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
new((void*)(&static_cast<T*>(address)->first))
typename T::first_type(
boost::forward<A0>(args.a0));
new((void*)(&static_cast<T*>(address)->second))
typename T::second_type(
boost::forward<A1>(args.a1),
boost::forward<A2>(args.a2));
}
template <typename T, typename A0, typename A1, typename A2>
inline typename normal_construct3<T, A0>::type
construct_impl(void* address,
::boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
new(address) T(
boost::forward<A0>(args.a0),
boost::forward<A1>(args.a1),
boost::forward<A2>(args.a2));
}
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
template < \
typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline typename normal_construct_n<T>::type \
construct_impl(void* address, \
::boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
{ \
new(address) T( \
BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
args.a)); \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
template <typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline typename pair_construct_n<T>::type \
construct_impl(void* address, \
::boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
{ \
new((void*)(&static_cast<T*>(address)->first)) \
typename T::first_type( \
boost::forward<A0>(args.a0)); \
new((void*)(&static_cast<T*>(address)->second)) \
typename T::second_type( \
BOOST_PP_ENUM_SHIFTED_##z(num_params, \
BOOST_UNORDERED_CALL_FORWARD, args.a)); \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
#endif
}}}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif