mirror of
https://github.com/boostorg/any.git
synced 2026-07-21 13:03:30 +00:00
unique_any now could take over ownership of boost::any content
This commit is contained in:
+5
-12
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <boost/any/bad_any_cast.hpp>
|
||||
#include <boost/any/fwd.hpp>
|
||||
#include <boost/any/detail/placeholder.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
@@ -240,20 +241,10 @@ namespace boost
|
||||
public: // types (public so any_cast can be non-friend)
|
||||
#endif
|
||||
/// @cond
|
||||
class BOOST_SYMBOL_VISIBLE placeholder
|
||||
class BOOST_SYMBOL_VISIBLE placeholder: public boost::anys::detail::placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
virtual ~placeholder()
|
||||
{
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0;
|
||||
|
||||
public:
|
||||
virtual placeholder * clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
@@ -302,6 +293,8 @@ namespace boost
|
||||
template<typename ValueType>
|
||||
friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT;
|
||||
|
||||
friend class boost::anys::unique_any;
|
||||
|
||||
#else
|
||||
|
||||
public: // representation (public so any_cast can be non-friend)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright Antony Polukhin, 2021-2023.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_ANY_ANYS_DETAIL_PLACEHOLDER_HPP
|
||||
#define BOOST_ANY_ANYS_DETAIL_PLACEHOLDER_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
/// @cond
|
||||
namespace boost {
|
||||
namespace anys {
|
||||
namespace detail {
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE placeholder {
|
||||
public:
|
||||
virtual ~placeholder() {}
|
||||
virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace anys
|
||||
} // namespace boost
|
||||
/// @endcond
|
||||
|
||||
#endif // #ifndef BOOST_ANY_ANYS_DETAIL_PLACEHOLDER_HPP
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
|
||||
defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \
|
||||
defined(BOOST_NO_CXX11_CONSTEXPR) || \
|
||||
defined(BOOST_NO_CXX11_NULLPTR) || \
|
||||
defined(BOOST_NO_CXX11_NOEXCEPT) || \
|
||||
defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \
|
||||
defined(BOOST_NO_CXX11_FINAL) || \
|
||||
@@ -48,10 +50,10 @@ template<std::size_t OptimizeForSize = sizeof(void*), std::size_t OptimizeForAli
|
||||
class basic_any;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct is_basic_any: public boost::false_type {};
|
||||
|
||||
|
||||
template<std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
|
||||
struct is_basic_any<boost::anys::basic_any<OptimizeForSize, OptimizeForAlignment> > : public boost::true_type {};
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <boost/any/fwd.hpp>
|
||||
#include <boost/any/bad_any_cast.hpp>
|
||||
#include <boost/any/detail/placeholder.hpp>
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
@@ -78,7 +79,7 @@ public:
|
||||
/// \throws std::bad_alloc or any exceptions arising from the move or
|
||||
/// copy constructor of the contained type.
|
||||
template<typename T>
|
||||
unique_any(T&& value)
|
||||
unique_any(T&& value, typename std::enable_if<!std::is_same<T&&, boost::any&&>::value>::type* = nullptr)
|
||||
: content(new holder< typename std::decay<T>::type >(std::forward<T>(value)))
|
||||
{
|
||||
static_assert(
|
||||
@@ -87,10 +88,26 @@ public:
|
||||
);
|
||||
|
||||
static_assert(
|
||||
!boost::anys::detail::is_some_any< typename std::decay<T>::type >::value,
|
||||
"unique_any could be only moved and could not be constructoed from "
|
||||
"other types of any."
|
||||
!std::is_same<unique_any, typename std::decay<T>::type >::value,
|
||||
"boost::anys::unique_any could not be copied, only moved."
|
||||
);
|
||||
|
||||
static_assert(
|
||||
!std::is_same<boost::any, typename std::decay<T>::type >::value,
|
||||
"boost::anys::unique_any could be constructed from an rvalue of boost::any, "
|
||||
"not a lvalue."
|
||||
);
|
||||
}
|
||||
|
||||
/// Moves the content of `boost::any` into *this.
|
||||
///
|
||||
/// \throws Nothing.
|
||||
/// \post `value.empty()` is true.
|
||||
template <class BoostAny>
|
||||
unique_any(BoostAny&& value, typename std::enable_if<std::is_same<BoostAny&&, boost::any&&>::value>::type* = nullptr) noexcept
|
||||
{
|
||||
content.reset(value.content);
|
||||
value.content = nullptr;
|
||||
}
|
||||
|
||||
/// Inplace constructs `T` from forwarded `args...`,
|
||||
@@ -156,7 +173,7 @@ public:
|
||||
template<class T, class... Args>
|
||||
typename std::decay<T>::type& emplace(Args&&... args) {
|
||||
auto* raw_ptr = new holder<typename std::decay<T>::type>(std::forward<Args>(args)...);
|
||||
content = std::unique_ptr<placeholder>(raw_ptr);
|
||||
content = std::unique_ptr<boost::anys::detail::placeholder>(raw_ptr);
|
||||
return raw_ptr->held;
|
||||
}
|
||||
|
||||
@@ -170,7 +187,7 @@ public:
|
||||
template<class T, class U, class... Args>
|
||||
typename std::decay<T>::type& emplace(std::initializer_list<U> il, Args&&... args) {
|
||||
auto* raw_ptr = new holder<typename std::decay<T>::type>(il, std::forward<Args>(args)...);
|
||||
content = std::unique_ptr<placeholder>(raw_ptr);
|
||||
content = std::unique_ptr<boost::anys::detail::placeholder>(raw_ptr);
|
||||
return raw_ptr->held;
|
||||
}
|
||||
|
||||
@@ -209,18 +226,8 @@ public:
|
||||
|
||||
private: // types
|
||||
/// @cond
|
||||
class BOOST_SYMBOL_VISIBLE placeholder
|
||||
{
|
||||
public:
|
||||
virtual ~placeholder()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const boost::typeindex::type_info& type() const noexcept = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class holder final: public placeholder
|
||||
class holder final: public boost::anys::detail::placeholder
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
@@ -248,7 +255,7 @@ private: // representation
|
||||
template<typename T>
|
||||
friend T * unsafe_any_cast(unique_any *) noexcept;
|
||||
|
||||
std::unique_ptr<placeholder> content;
|
||||
std::unique_ptr<boost::anys::detail::placeholder> content;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ test-suite unique_any :
|
||||
[ run move.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : no_rtti_unique_move ]
|
||||
[ run emplace.cpp : : : : unique_emplace ]
|
||||
[ run emplace.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : no_rtti_unique_emplace ]
|
||||
[ run from_any.cpp : : : : unique_from_any ]
|
||||
[ run from_any.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : no_rtti_unique_from_any ]
|
||||
[ compile-fail any_cast_cv_failed.cpp : : unique_any_cast_cd_failed ]
|
||||
[ compile-fail temporary_to_ref_failed.cpp : : unique_temporary_to_ref_failed ]
|
||||
[ compile-fail cv_to_rv_failed.cpp : : unique_cv_to_rv_failed ]
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright Antony Polukhin, 2013-2023.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/any/unique_any.hpp>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
void test_basic() {
|
||||
boost::any from = 42;
|
||||
|
||||
boost::anys::unique_any a(std::move(from));
|
||||
BOOST_TEST(from.empty());
|
||||
BOOST_TEST(a.has_value());
|
||||
|
||||
BOOST_TEST_EQ(boost::any_cast<int>(a), 42);
|
||||
BOOST_TEST_EQ(boost::anys::any_cast<int>(a), 42);
|
||||
BOOST_TEST_EQ(boost::any_cast<int&>(a), 42);
|
||||
BOOST_TEST_EQ(boost::anys::any_cast<int&>(a), 42);
|
||||
|
||||
boost::anys::unique_any b = std::move(a);
|
||||
BOOST_TEST(!a.has_value());
|
||||
BOOST_TEST(b.has_value());
|
||||
BOOST_TEST_EQ(boost::any_cast<int&>(b), 42);
|
||||
|
||||
b.reset();
|
||||
BOOST_TEST(!b.has_value());
|
||||
}
|
||||
|
||||
void test_const() {
|
||||
boost::any from = 42;
|
||||
|
||||
const boost::anys::unique_any a = std::move(from);
|
||||
BOOST_TEST(a.has_value());
|
||||
BOOST_TEST_EQ(boost::any_cast<int>(a), 42);
|
||||
BOOST_TEST_EQ(boost::anys::any_cast<int>(a), 42);
|
||||
BOOST_TEST_EQ(boost::any_cast<const int&>(a), 42);
|
||||
BOOST_TEST_EQ(boost::anys::any_cast<const int&>(a), 42);
|
||||
}
|
||||
|
||||
void test_bad_any_cast() {
|
||||
boost::any from = 42;
|
||||
|
||||
const boost::anys::unique_any a = std::move(from);
|
||||
try {
|
||||
boost::any_cast<char>(a);
|
||||
BOOST_TEST(false);
|
||||
} catch (const boost::bad_any_cast&) {
|
||||
}
|
||||
|
||||
try {
|
||||
boost::any_cast<int*>(a);
|
||||
BOOST_TEST(false);
|
||||
} catch (const boost::bad_any_cast&) {
|
||||
}
|
||||
}
|
||||
|
||||
struct counting_destroy {
|
||||
static int destructor_called;
|
||||
|
||||
~counting_destroy() {
|
||||
++destructor_called;
|
||||
}
|
||||
};
|
||||
|
||||
int counting_destroy::destructor_called = 0;
|
||||
|
||||
void test_destructor() {
|
||||
boost::any from = counting_destroy{};
|
||||
BOOST_TEST_EQ(counting_destroy::destructor_called, 1);
|
||||
boost::anys::unique_any a = std::move(from);
|
||||
BOOST_TEST_EQ(counting_destroy::destructor_called, 1);
|
||||
|
||||
a.reset();
|
||||
BOOST_TEST_EQ(counting_destroy::destructor_called, 2);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_basic();
|
||||
test_const();
|
||||
test_bad_any_cast();
|
||||
test_destructor();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user