1 Star 0 Fork 6

kevinying16/cpp-any

forked from shaoguangcn/cpp-any 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
any.h 27.57 KB
一键复制 编辑 原始数据 按行查看 历史
shaoguangcn 提交于 2022-06-04 22:12 . update namespace
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
/************************************************************************************
**
** Copyright 2021 Shaoguang
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is furnished
** to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE.
**
************************************************************************************/
#ifndef ANY_H
#define ANY_H
#include <new>
#include <typeinfo>
#include <utility>
/**
* \def ANY_NAMESPACE
* In order to avoid symbol clashes and/or "One Definition Rule" errors between
* multiple inclusions of (different versions of) basic_string_view in a single binary,
* users can customize the name of the main basic_string_view namespace.
*/
#ifndef ANY_NAMESPACE
# define ANY_NAMESPACE core
#endif
/**
* \def ANY_NAMESPACE_BEGIN
* provide custom basic_string_view namespace (opening expression)
*/
#ifndef ANY_NAMESPACE_BEGIN
# define ANY_NAMESPACE_BEGIN namespace ANY_NAMESPACE {
#endif
/**
* \def ANY_NAMESPACE_END
* provide custom basic_string_view namespace (closing expression)
*/
#ifndef ANY_NAMESPACE_END
# define ANY_NAMESPACE_END }
#endif
ANY_NAMESPACE_BEGIN
namespace detail {
template <bool B>
using _bool_constant = std::integral_constant<bool, B>;
// _or
template<typename...>
struct _or;
template<>
struct _or<>
: public std::false_type
{ };
template<typename _B1>
struct _or<_B1>
: public _B1
{ };
template<typename _B1, typename _B2>
struct _or<_B1, _B2>
: public std::conditional<_B1::value, _B1, _B2>::type
{ };
template<typename _B1, typename _B2, typename _B3, typename... _Bn>
struct _or<_B1, _B2, _B3, _Bn...>
: public std::conditional<_B1::value, _B1, _or<_B2, _B3, _Bn...>>::type
{ };
// _and
template<typename...>
struct _and;
template<>
struct _and<>
: public std::true_type
{ };
template<typename _B1>
struct _and<_B1>
: public _B1
{ };
template<typename _B1, typename _B2>
struct _and<_B1, _B2>
: public std::conditional<_B1::value, _B2, _B1>::type
{ };
template<typename _B1, typename _B2, typename _B3, typename... _Bn>
struct _and<_B1, _B2, _B3, _Bn...>
: public std::conditional<_B1::value, _and<_B2, _B3, _Bn...>, _B1>::type
{ };
// _and_v
template<typename... _Bn>
constexpr bool _and_v() noexcept
{
return _and<_Bn...>::value;
}
// _not
template<typename _Pp>
struct _not
: public _bool_constant<!bool(_Pp::value)>
{ };
// _in_place_type_t
template<typename _Tp>
struct _in_place_type_t
{
explicit _in_place_type_t() = default;
};
// _is_in_place_type
template<typename>
struct _is_in_place_type_impl : std::false_type
{ };
template<typename _Tp>
struct _is_in_place_type_impl<_in_place_type_t<_Tp>> : std::true_type
{ };
template<typename _Tp>
struct _is_in_place_type
: public _is_in_place_type_impl<_Tp>
{ };
} // namespace detail
/**
* \class bad_any_cast
* \brief Exception thrown by the value-returning forms of any_cast on a type mismatch.
*
* Defines a type of object to be thrown by the value-returning forms of any_cast on failure.
*/
class bad_any_cast : public std::bad_cast
{
public:
/**
* Returns an explanatory string.
*/
virtual const char* what() const noexcept;
};
[[noreturn]] inline void throw_bad_any_cast()
{
throw bad_any_cast{};
}
/**
* \class any
* \brief The class any describes a type-safe container for single values of any type.
*
* An object of class any stores an instance of any type that satisfies the constructor requirements or is empty,
* and this is referred to as the state of the class any object. The stored instance is called the contained object.
* Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
*
* The non-member any_cast functions provide type-safe access to the contained object.
*
* \sa make_any(), any_cast()
*/
class any
{
// Holds either pointer to a heap object or the contained object itself.
union Storage
{
constexpr Storage()
: m_ptr(nullptr) {}
// Prevent trivial copies of this type, buffer might hold a non-POD.
Storage(const Storage&) = delete;
Storage& operator=(const Storage&) = delete;
void* m_ptr;
std::aligned_storage<sizeof(m_ptr), alignof(void*)>::type m_buffer;
};
template<typename _Tp, typename _Safe = std::is_nothrow_move_constructible<_Tp>,
bool _Fits = (sizeof(_Tp) <= sizeof(Storage)) && (alignof(_Tp) <= alignof(Storage))>
using Internal = std::integral_constant<bool, _Safe::value && _Fits>;
template<typename _Tp>
struct Manager_internal; // uses small-object optimization
template<typename _Tp>
struct Manager_external; // creates contained object on the heap
template<typename _Tp>
using Manager = typename std::conditional<Internal<_Tp>::value,
Manager_internal<_Tp>, Manager_external<_Tp>>::type;
template<typename _Tp, typename _Decayed = typename std::decay<_Tp>::type>
using Decay = typename std::enable_if<!std::is_same<_Decayed, any>::value, _Decayed>::type;
/** Emplace with an object created from \a args as the contained object. */
template <typename _Tp, typename... _Args, typename Mgr = Manager<_Tp>>
void _do_emplace(_Args&&... args)
{
reset();
Mgr::S_create(m_storage, std::forward<_Args>(args)...);
m_manager = &Mgr::S_manage;
}
/** Emplace with an object created from \a list and \a list as the contained object. */
template <typename _Tp, typename _Up, typename... _Args,
typename Mgr = Manager<_Tp>>
void _do_emplace(std::initializer_list<_Up> list, _Args&&... args)
{
reset();
Mgr::S_create(m_storage, list, std::forward<_Args>(args)...);
m_manager = &Mgr::S_manage;
}
public:
//
// construct/destruct
//
/**
* Default constructor, creates an empty object.
*
* \note Because the default constructor is constexpr, static anys are initialized as part
* of [static non-local initialization](https://en.cppreference.com/w/cpp/language/initialization),
* before any dynamic non-local initialization begins. This makes it safe to use an object of
* type any in a constructor of any static object.
*/
constexpr any() noexcept;
/**
* Copies content of \a other into a new instance, so that any content is equivalent in both type
* and value to those of \a other prior to the constructor call, or empty if \a other is empty.
*
* Formally, If \a other is empty, the constructed object is empty. Otherwise, equivalent
* to <code>any(std::in_place_type<T>, std::any_cast<const T&>(other))</code>,
* where \c T is the type of the object contained in \a other.
*
* \exception Throws any exception thrown by the constructor of the contained type.
*/
any(const any& other);
/**
* Moves content of \a other into a new instance, so that any content is equivalent in both type
* and value to those of \a other prior to the constructor call, or empty if \a other is empty.
*
* Formally, If \a other is empty, the constructed object is empty. Otherwise, the constructed
* object contains either the object contained in other, or an object of the same type constructed
* from the object contained in other, considering that object as an rvalue.
*/
any(any&& other) noexcept;
template <typename _Res, typename _Tp, typename... _Args>
using _any_constructible = std::enable_if<detail::_and<std::is_copy_constructible<_Tp>,
std::is_constructible<_Tp, _Args...>>::value, _Res>;
template <typename _Tp, typename... _Args>
using _any_constructible_t = typename _any_constructible<bool, _Tp, _Args...>::type;
/**
* Constructs an object with initial content an object of type \c std::decay_t<_ValueType> ,
* [direct-initialized](https://en.cppreference.com/w/cpp/language/direct_initialization) from
* std::forward<_ValueType>(value). If std::is_copy_constructible<std::decay_t<_ValueType>>::value
* is false, the program is ill-formed.
*
* - This overload only participates in overload resolution if \c std::decay_t<_ValueType> is not
* the same type as any nor a specialization of \c std::in_place_type_t ,
* and \c std::is_copy_constructible_v<std::decay_t<_ValueType>> is true.
*
* \exception Throws any exception thrown by the constructor of the contained type.
*/
template <typename _ValueType, typename _Tp = Decay<_ValueType>,
typename Mgr = Manager<_Tp>,
_any_constructible_t<_Tp, _ValueType&&> = true,
typename std::enable_if<!detail::_is_in_place_type<_Tp>::value, bool>::type = true>
any(_ValueType&& value)
: m_manager(&Mgr::S_manage)
{
Mgr::S_create(m_storage, std::forward<_ValueType>(value));
}
/**
* Constructs an object with initial content an object of type \c std::decay_t<_ValueType> ,
* [direct-initialized](https://en.cppreference.com/w/cpp/language/direct_initialization) from
* std::forward<_ValueType>(value). If std::is_copy_constructible<std::decay_t<_ValueType>>::value
* is false, the program is ill-formed.
*
* - This overload only participates in overload resolution if \c std::decay_t<_ValueType> is not
* the same type as any nor a specialization of \c std::in_place_type_t ,
* and \c std::is_copy_constructible_v<std::decay_t<_ValueType>> is true.
*
* \exception Throws any exception thrown by the constructor of the contained type.
*/
template <typename _ValueType, typename _Tp = Decay<_ValueType>,
typename Mgr = Manager<_Tp>,
typename std::enable_if<detail::_and_v<std::is_copy_constructible<_Tp>,
detail::_not<std::is_constructible<_Tp, _ValueType&&>>,
detail::_not<detail::_is_in_place_type<_Tp>>>(), bool>::value = false>
any(_ValueType&& value)
: m_manager(&Mgr::S_manage)
{
Mgr::S_create(m_storage, value);
}
/**
* Constructs an object with initial content an object of type \c std::decay_t<_ValueType> ,
* [direct-non-list-initialized](https://en.cppreference.com/w/cpp/language/direct_initialization) from
* \c std::forward<Args>(args)....
*
* - This overload only participates in overload resolution if
* <code>std::is_constructible_v<std::decay_t<_ValueType>, Args...></code> and
* \c std::is_copy_constructible_v<std::decay_t<_ValueType>> are both true.
*
* \exception Throws any exception thrown by the constructor of the contained type.
*/
template <typename _ValueType, typename... _Args,
typename _Tp = Decay<_ValueType>,
typename Mgr = Manager<_Tp>,
_any_constructible_t<_Tp, _Args&& ... > = false>
explicit any(detail::_in_place_type_t<_ValueType>, _Args&&... args)
: m_manager(&Mgr::S_manage)
{
Mgr::S_create(m_storage, std::forward<_Args>(args)...);
}
/**
* Construct with an object created from \a list and \a args as the contained object.
*
* Constructs an object with initial content an object of type std::decay_t<_ValueType>,
* [direct-non-list-initialized](https://en.cppreference.com/w/cpp/language/direct_initialization) from
* \a list, </code>std::forward<_Args>(args)....</code>
*
* - This overload participates in overload resolution only if <code>std::is_constructible_v<std::decay_t<_ValueType></code>,
* <code>std::initializer_list<_Up>&, _Args...></code> and
* <code>std::is_copy_constructible_v<std::decay_t<_ValueType>></code> are both true.
*
* \exception Throws any exception thrown by the constructor of the contained type.
*/
template <typename _ValueType, typename _Up, typename... _Args,
typename _Tp = Decay<_ValueType>, typename Mgr = Manager<_Tp>,
_any_constructible_t<_Tp, std::initializer_list<_Up>, _Args&&...> = false>
explicit any(detail::_in_place_type_t<_ValueType>, std::initializer_list<_Up> list, _Args&&... args)
: m_manager(&Mgr::S_manage)
{
Mgr::S_create(m_storage, list, std::forward<_Args>(args)...);
}
/**
* Destroys the contained object, if any, as if by a call to reset().
*/
~any();
//
// assignments
//
/**
* Assigns by copying the state of \a rhs, as if by any(rhs).swap(*this).
*
* \exception bad_alloc or any exception thrown by the constructor of the contained type.
* If an exception is thrown, there are no effects (strong exception guarantee).
*/
any& operator=(const any& rhs);
/**
* Assigns by moving the state of \a rhs, as if by any(std::move(rhs)).swap(*this).
* \a rhs is left in a valid but unspecified state after the assignment.
*/
any& operator=(any&& rhs) noexcept;
/**
* Assigns the type and value of rhs, as if by <code>any(std::forward<_ValueType>(rhs)).swap(*this)</code>.
* This overload participates in overload resolution only if \c std::decay_t<_ValueType> is not the same
* type as any and <code>std::is_copy_constructible_v<std::decay_t<_ValueType>></code> is true.
*
* \exception bad_alloc or any exception thrown by the constructor of the contained type.
* If an exception is thrown, there are no effects (strong exception guarantee).
*
* \note \c std::decay_t<_ValueType> must meet the requirements of
* [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible).
*/
template<typename _ValueType>
typename std::enable_if<std::is_copy_constructible<Decay<_ValueType>>::value, any&>::type
operator=(_ValueType&& rhs)
{
*this = any(std::forward<_ValueType>(rhs));
return *this;
}
/**
* Changes the contained object to one of type \c std::decay_t<_ValueType> constructed from the arguments.
* First destroys the current contained object (if any) by reset(), then:
* constructs an object of type std::decay_t<_ValueType>,
* [direct-non-list-initialized](https://en.cppreference.com/w/cpp/language/direct_initialization) from
* <code>std::forward<Args>(args)...</code>, as the contained object.
*
* - This overload only participates in overload resolution if
* <code>std::is_constructible_v<std::decay_t<_ValueType>, _Args...></code> and
* <code>std::is_copy_constructible_v<std::decay_t<_ValueType>></code> are both true.
*
* \exception Throws any exception thrown by T's constructor. If an exception is thrown,
* the previously contained object (if any) has been destroyed, and *this does not contain a value.
*
* \note \c std::decay_t<_ValueType> must meet the requirements of
* [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible).
*/
template <typename _ValueType, typename... _Args>
typename _any_constructible<Decay<_ValueType>&, Decay<_ValueType>, _Args&&...>::type
emplace(_Args&&... args)
{
_do_emplace<Decay<_ValueType>>(std::forward<_Args>(args)...);
any::ManageArg marg;
this->m_manager(any::MOAccess, this, &marg);
return *static_cast<Decay<_ValueType>*>(marg._obj);
}
/**
* Changes the contained object to one of type \c std::decay_t<_ValueType> constructed from the arguments.
* First destroys the current contained object (if any) by reset(), then:
* constructs an object of type <code>std::decay_t<_ValueType></code>,
* [direct-non-list-initialized](https://en.cppreference.com/w/cpp/language/direct_initialization) from
* \a list, <code>std::forward<_Args>(args)...</code>, as the contained object.
*
* - This overload only participates in overload resolution if
* <code>std::is_constructible_v<std::decay_t<_ValueType>, std::initializer_list<_Up>&, _Args...></code> and
* <code>std::is_copy_constructible_v<std::decay_t<_ValueType>></code> are both true.
*
* \exception Throws any exception thrown by T's constructor. If an exception is thrown,
* the previously contained object (if any) has been destroyed, and *this does not contain a value.
*
* \note \c std::decay_t<_ValueType> must meet the requirements of
* [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible).
*/
template <typename _ValueType, typename _Up, typename... _Args>
typename _any_constructible<Decay<_ValueType>&, Decay<_ValueType>,
std::initializer_list<_Up>, _Args&&...>::type
emplace(std::initializer_list<_Up> list, _Args&&... args)
{
_do_emplace<Decay<_ValueType>, _Up>(list, std::forward<_Args>(args)...);
any::ManageArg marg;
this->m_manager(any::MOAccess, this, &marg);
return *static_cast<Decay<_ValueType>*>(marg._obj);
}
//
// modifiers
//
/**
* If not empty, destroy the contained object.
*/
void reset() noexcept;
/**
* Swaps the content of two any objects.
*/
void swap(any& rhs) noexcept;
//
// observers
//
/**
* Checks whether the object contains a value.
*
* \return \c true if instance contains a value, otherwise \c false.
*/
bool has_value() const noexcept;
#if __cpp_rtti
/**
* Returns the typeid of the contained value.
*
* \return The typeid of the contained value if instance is non-empty, otherwise \c typeid(void).
*/
const std::type_info& type() const noexcept;
#endif
template<typename _Tp>
static constexpr bool _is_valid_cast()
{
return detail::_or<std::is_reference<_Tp>, std::is_copy_constructible<_Tp>>::value;
}
private:
enum ManageOption {
MOAccess,
MOGetTypeInfo,
MOClone,
MODestroy,
MOXfer
};
union ManageArg
{
void* _obj;
const std::type_info* _typeinfo;
any* _any;
};
void(*m_manager)(ManageOption, const any*, ManageArg*);
Storage m_storage;
template<typename _Tp>
friend void* _any_caster(const any* __any);
// Manage in-place contained object.
template<typename _Tp>
struct Manager_internal
{
static void S_manage(ManageOption which, const any* anyp, ManageArg* arg);
template<typename _Up>
static void S_create(Storage& storage, _Up&& value)
{
void* addr = &storage.m_buffer;
::new (addr) _Tp(std::forward<_Up>(value));
}
template<typename... _Args>
static void S_create(Storage& storage, _Args&&... args)
{
void* addr = &storage.m_buffer;
::new (addr) _Tp(std::forward<_Args>(args)...);
}
};
// Manage external contained object.
template<typename _Tp>
struct Manager_external
{
static void S_manage(ManageOption __which, const any* __anyp, ManageArg* __arg);
template<typename _Up>
static void S_create(Storage& storage, _Up&& value)
{
storage.m_ptr = new _Tp(std::forward<_Up>(value));
}
template<typename... _Args>
static void S_create(Storage& storage, _Args&&... __args)
{
storage.m_ptr = new _Tp(std::forward<_Args>(__args)...);
}
};
};
/**
* Swaps the content of two any objects by calling <code> lhs.swap(rhs) </code>.
*/
inline void swap(any& lhs, any& rhs) noexcept
{
lhs.swap(rhs);
}
/**
* Constructs an any object containing an object of type _Tp, passing the provided arguments to _Tp's constructor.
*
* Equivalent to return <code> any(std::in_place_type<_Tp>, std::forward<_Args>(args)...); </code>
*/
template <typename _Tp, typename... _Args>
any make_any(_Args&&... args)
{
constexpr detail::_in_place_type_t<_Tp> __in_place_type;
return any(__in_place_type, std::forward<_Args>(args)...);
}
/**
* Constructs an any object containing an object of type _Tp, passing the provided arguments to _Tp's constructor.
*
* Equivalent to <code> return std::any(std::in_place_type<_Tp>, list, std::forward<_Args>(args)...); </code>
*/
template <typename _Tp, typename _Up, typename... _Args>
any make_any(std::initializer_list<_Up> list, _Args&&... args)
{
return any(detail::_in_place_type_t<_Tp>(), list, std::forward<_Args>(args)...);
}
/**
* Performs type-safe access to the contained object.
*
* Let U be <code> std::remove_cv_t<std::remove_reference_t<_ValueType>> </code>.
*
* The program is ill-formed if <code>std::is_constructible_v<_ValueType, const U&></code> is false.
*
* \exception bad_any_cast if the typeid of the requested _ValueType does not match that of the contents of \a operand.
*
* \return static_cast<_ValueType>(*any_cast<U>(&operand))
*/
template<typename _ValueType>
inline _ValueType any_cast(const any& operand)
{
using _Up = typename std::remove_cv<_ValueType>::type;
static_assert(any::_is_valid_cast<_ValueType>(),
"Template argument must be a reference or CopyConstructible type");
static_assert(std::is_constructible<_ValueType, const _Up&>::value,
"Template argument must be constructible from a const value.");
auto resultp = any_cast<_Up>(&operand);
if (resultp) {
return static_cast<_ValueType>(*resultp);
}
throw_bad_any_cast();
}
/**
* Performs type-safe access to the contained object.
*
* Let U be <code> std::remove_cv_t<std::remove_reference_t<_ValueType>> </code>.
*
* The program is ill-formed if <code>std::is_constructible_v<_ValueType, U&></code> is false.
*
* \exception bad_any_cast if the typeid of the requested _ValueType does not match that of the contents of \a operand.
*
* \return static_cast<_ValueType>(*any_cast<U>(&operand))
*/
template<typename _ValueType>
inline _ValueType any_cast(any& operand)
{
using _Up = typename std::remove_cv<_ValueType>::type;
static_assert(any::_is_valid_cast<_ValueType>(),
"Template argument must be a reference or CopyConstructible type");
static_assert(std::is_constructible<_ValueType, _Up&>::value,
"Template argument must be constructible from an lvalue.");
auto resultp = any_cast<_Up>(&operand);
if (resultp) {
return static_cast<_ValueType>(*resultp);
}
throw_bad_any_cast();
}
/**
* Performs type-safe access to the contained object.
*
* Let U be <code> std::remove_cv_t<std::remove_reference_t<_ValueType>> </code>.
*
* The program is ill-formed if <code>std::is_constructible_v<_ValueType, U></code> is false.
*
* \exception bad_any_cast if the typeid of the requested _ValueType does not match that of the contents of \a operand.
*
* \return static_cast<_ValueType>(std::move(*any_cast<U>(&operand))).
*/
template<typename _ValueType>
inline _ValueType any_cast(any&& operand)
{
using _Up = typename std::remove_cv<_ValueType>::type;
static_assert(any::_is_valid_cast<_ValueType>(),
"Template argument must be a reference or CopyConstructible type");
static_assert(std::is_constructible<_ValueType, _Up>::value,
"Template argument must be constructible from an rvalue.");
auto resultp = any_cast<_Up>(&operand);
if (resultp) {
return static_cast<_ValueType>(std::move(*resultp));
}
throw_bad_any_cast();
}
/// \cond undocumented
template<typename _Tp>
void* _any_caster(const any* a)
{
// any_cast<T> returns non-null if __any->type() == typeid(T) and
// typeid(T) ignores cv-qualifiers so remove them:
using _Up = typename std::remove_cv<_Tp>::type;
// The contained value has a decayed type, so if decay_t<U> is not U,
// then it's not possible to have a contained value of type U:
if (!std::is_same<typename std::decay<_Up>::type, _Up>::value) {
return nullptr;
}
// Only copy constructible types can be used for contained values:
else if (!std::is_copy_constructible<_Up>::value) {
return nullptr;
}
// First try comparing function addresses, which works without RTTI
else if (a->m_manager == &any::Manager<_Up>::S_manage
#if __cpp_rtti
|| a->type() == typeid(_Tp)
#endif
)
{
any::ManageArg marg;
a->m_manager(any::MOAccess, a, &marg);
return marg._obj;
}
return nullptr;
}
/// @endcond
/**
* Performs type-safe access to the contained object.
*
* \return If operand is not a null pointer, and the typeid of the requested \c _ValueType matches that
* of the contents of \a operand, a pointer to the value contained by \a operand, otherwise a null pointer.
*/
template<typename _ValueType>
inline const _ValueType* any_cast(const any* operand) noexcept
{
if (std::is_object<_ValueType>::value) {
if (operand) {
return static_cast<_ValueType*>(_any_caster<_ValueType>(operand));
}
}
return nullptr;
}
/**
* Performs type-safe access to the contained object.
*
* \return If operand is not a null pointer, and the typeid of the requested \c _ValueType matches that
* of the contents of \a operand, a pointer to the value contained by \a operand, otherwise a null pointer.
*/
template<typename _ValueType>
inline _ValueType* any_cast(any* operand) noexcept
{
if (std::is_object<_ValueType>::value) {
if (operand) {
return static_cast<_ValueType*>(_any_caster<_ValueType>(operand));
}
}
return nullptr;
}
/** @} */
template<typename _Tp>
void any::Manager_internal<_Tp>::S_manage(ManageOption which, const any* a, ManageArg* arg)
{
// The contained object is in _M_storage._M_buffer
auto ptr = reinterpret_cast<const _Tp*>(&a->m_storage.m_buffer);
switch (which)
{
case MOAccess:
arg->_obj = const_cast<_Tp*>(ptr);
break;
case MOGetTypeInfo:
#if __cpp_rtti
arg->_typeinfo = &typeid(_Tp);
#endif
break;
case MOClone:
::new(&arg->_any->m_storage.m_buffer) _Tp(*ptr);
arg->_any->m_manager = a->m_manager;
break;
case MODestroy:
ptr->~_Tp();
break;
case MOXfer:
::new(&arg->_any->m_storage.m_buffer) _Tp
(std::move(*const_cast<_Tp*>(ptr)));
ptr->~_Tp();
arg->_any->m_manager = a->m_manager;
const_cast<any*>(a)->m_manager = nullptr;
break;
}
}
template<typename _Tp>
void any::Manager_external<_Tp>::S_manage(ManageOption which, const any* a, ManageArg* arg)
{
// The contained object is *_M_storage._M_ptr
auto ptr = static_cast<const _Tp*>(a->m_storage.m_ptr);
switch (which)
{
case MOAccess:
arg->_obj = const_cast<_Tp*>(ptr);
break;
case MOGetTypeInfo:
#if __cpp_rtti
arg->_typeinfo = &typeid(_Tp);
#endif
break;
case MOClone:
arg->_any->m_storage.m_ptr = new _Tp(*ptr);
arg->_any->m_manager = a->m_manager;
break;
case MODestroy:
delete ptr;
break;
case MOXfer:
arg->_any->m_storage.m_ptr = a->m_storage.m_ptr;
arg->_any->m_manager = a->m_manager;
const_cast<any*>(a)->m_manager = nullptr;
break;
}
}
ANY_NAMESPACE_END
#endif // ANY_H
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/kevinying16/cpp-any.git
git@gitee.com:kevinying16/cpp-any.git
kevinying16
cpp-any
cpp-any
master

搜索帮助