Revert "Use placement new to avoid unique_ptr allocations"

This reverts commit 83281bff52a4ceb7a2a479a42efd5795c54924ac.
This commit is contained in:
Jason Turner 2015-06-24 11:25:56 -06:00
parent 1526ac96c1
commit 902f48cd4c

View File

@ -8,7 +8,6 @@
#define CHAISCRIPT_ANY_HPP_ #define CHAISCRIPT_ANY_HPP_
#include <utility> #include <utility>
#include <array>
namespace chaiscript { namespace chaiscript {
namespace detail { namespace detail {
@ -45,15 +44,6 @@ namespace chaiscript {
class Any { class Any {
private: private:
template<class T>
struct destruct {
void operator()(T *t) const {
t->~T();
}
};
struct Data struct Data
{ {
Data(const std::type_info &t_type) Data(const std::type_info &t_type)
@ -71,7 +61,7 @@ namespace chaiscript {
return m_type; return m_type;
} }
virtual void clone(void *t_ptr) const = 0; virtual std::unique_ptr<Data> clone() const = 0;
const std::type_info &m_type; const std::type_info &m_type;
}; };
@ -91,9 +81,9 @@ namespace chaiscript {
return &m_data; return &m_data;
} }
void clone(void *t_ptr) const CHAISCRIPT_OVERRIDE std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
{ {
new (t_ptr) Data_Impl<T>(m_data); return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
} }
Data_Impl &operator=(const Data_Impl&) = delete; Data_Impl &operator=(const Data_Impl&) = delete;
@ -101,70 +91,32 @@ namespace chaiscript {
T m_data; T m_data;
}; };
static const size_t buffersize = sizeof(Data_Impl<std::shared_ptr<int>>)>sizeof(Data_Impl<std::reference_wrapper<int>>)?sizeof(Data_Impl<std::shared_ptr<int>>):sizeof(Data_Impl<std::reference_wrapper<int>>); std::unique_ptr<Data> m_data;
bool m_constructed;
mutable std::array<uint8_t, buffersize> m_data_holder;
inline Data *data() const
{
return reinterpret_cast<Data*>(m_data_holder.data());
}
void call_destructor()
{
if (m_constructed)
{
m_constructed = false;
data()->~Data();
}
}
public: public:
Any()
: m_constructed(false)
{
}
// construct/copy/destruct // construct/copy/destruct
Any(const Any &t_any) Any() = default;
: m_constructed(false)
{ Any(const Any &t_any)
if (t_any.m_constructed) { {
t_any.data()->clone(m_data_holder.data()); if (!t_any.empty())
m_constructed = true; {
m_data = t_any.m_data->clone();
} else {
m_data.reset();
} }
} }
Any(Any &&t_any) #if !defined(_MSC_VER) || _MSC_VER != 1800
: m_constructed(false) Any(Any &&) = default;
{ Any &operator=(Any &&t_any) = default;
if (t_any.m_constructed) { #endif
t_any.m_constructed = false;
m_constructed = true;
m_data_holder = std::move(t_any.m_data_holder);
}
}
Any &operator=(Any &&t_any)
{
call_destructor();
if (t_any.m_constructed) {
t_any.m_constructed = false;
m_constructed = true;
m_data_holder = std::move(t_any.m_data_holder);
}
return *this;
}
template<typename ValueType, template<typename ValueType,
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type> typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
explicit Any(ValueType &&t_value) explicit Any(ValueType &&t_value)
: m_constructed(true) : m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value))))
{ {
static_assert(sizeof(Data_Impl<typename std::decay<ValueType>::type>) <= buffersize, "Buffer too small");
(void)(new (m_data_holder.data()) Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value)));
} }
@ -178,9 +130,9 @@ namespace chaiscript {
template<typename ToType> template<typename ToType>
ToType &cast() const ToType &cast() const
{ {
if (m_constructed && typeid(ToType) == data()->type()) if (m_data && typeid(ToType) == m_data->type())
{ {
return *static_cast<ToType *>(data()->data()); return *static_cast<ToType *>(m_data->data());
} else { } else {
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
@ -189,22 +141,26 @@ namespace chaiscript {
~Any() ~Any()
{ {
call_destructor();
} }
// modifiers // modifiers
Any & swap(Any &t_other) Any & swap(Any &t_other)
{ {
std::swap(t_other.m_data_holder, m_data_holder); std::swap(t_other.m_data, m_data);
std::swap(t_other.m_constructed, m_constructed);
return *this; return *this;
} }
// queries
bool empty() const
{
return !bool(m_data);
}
const std::type_info & type() const const std::type_info & type() const
{ {
if (m_constructed) { if (m_data)
return data()->type(); {
return m_data->type();
} else { } else {
return typeid(void); return typeid(void);
} }