Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <exception>
- #include <type_traits>
- #include <typeinfo>
- #include <utility>
- namespace details {
- struct any_value_base {
- virtual const type_info& type() const = 0;
- virtual any_value_base* clone() const = 0;
- virtual ~any_value_base() = default;
- };
- template<typename ValueType>
- struct any_value : any_value_base {
- any_value(const ValueType& value) : value(value) { }
- ValueType value;
- const type_info& type() const override {
- return typeid(ValueType);
- }
- any_value_base* clone() const override {
- return new any_value(value);
- }
- };
- }
- class bad_any_cast : std::exception {
- virtual const char* what() const noexcept override {
- return "invalid any_cast";
- }
- };
- class any {
- public:
- any() noexcept : value(nullptr) { }
- any(const any& other) {
- if(other.value != nullptr) {
- value = other.value->clone();
- } else {
- value = nullptr;
- }
- }
- any(any&& other) noexcept : value(other.value) {
- other.value = nullptr;
- }
- template<typename ValueType, typename = std::enable_if_t<!std::is_same<std::decay_t<ValueType>, any>::value>>
- any(ValueType&& value) : value(new details::any_value<std::decay_t<ValueType>>(std::forward<ValueType>(value))) {
- static_assert(std::is_copy_constructible<std::decay_t<ValueType>>::value,
- "std::decay_t<ValueType> does not satisfy CopyConstructible requirements");
- }
- ~any() {
- clear();
- }
- any& operator=(const any& other) {
- if(this != &other) {
- any(other).swap(*this);
- }
- return *this;
- }
- any& operator=(any&& other) noexcept {
- if(this != &other) {
- any(std::move(other)).swap(*this);
- }
- return *this;
- }
- template<typename ValueType>
- std::enable_if_t<!std::is_same<std::decay_t<ValueType>, any>::value, any&> operator=(ValueType&& value) {
- static_assert(std::is_copy_constructible<std::decay_t<ValueType>>::value,
- "std::decay_t<ValueType> does not satisfy CopyConstructible requirements");
- any(std::forward<ValueType>(value)).swap(*this);
- return *this;
- }
- void clear() noexcept {
- delete value;
- }
- void swap(any& other) noexcept {
- std::swap(value, other.value);
- }
- bool empty() const noexcept {
- return value == nullptr;
- }
- const std::type_info& type() const noexcept {
- if(empty()) {
- return typeid(void);
- }
- return value->type();
- }
- private:
- details::any_value_base* value;
- template<class ValueType>
- friend const ValueType* any_cast(const any* operand) noexcept;
- template<class ValueType>
- friend ValueType* any_cast(any* operand) noexcept;
- };
- void swap(any& lhs, any& rhs) noexcept {
- lhs.swap(rhs);
- }
- template<class ValueType>
- ValueType any_cast(const any& operand) {
- static_assert(std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value,
- "ValueType must be reference type or copy constructible type");
- if(operand.type() != typeid(std::remove_reference_t<ValueType>)) {
- throw bad_any_cast();
- }
- return *any_cast<std::add_const_t<std::remove_reference_t<ValueType>>>(&operand);
- }
- template<class ValueType>
- ValueType any_cast(any& operand) {
- static_assert(std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value,
- "ValueType must be reference type or copy constructible type");
- if(operand.type() != typeid(std::remove_reference_t<ValueType>)) {
- throw bad_any_cast();
- }
- return *any_cast<std::remove_reference_t<ValueType>>(&operand);
- }
- template<class ValueType>
- ValueType any_cast(any&& operand) {
- static_assert(std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value,
- "ValueType must be reference type or copy constructible type");
- if(operand.type() != typeid(std::remove_reference_t<ValueType>)) {
- throw bad_any_cast();
- }
- return *any_cast<std::remove_reference_t<ValueType>>(&operand);
- }
- template<class ValueType>
- const ValueType* any_cast(const any* operand) noexcept {
- if(operand != nullptr && operand->type() == typeid(ValueType)) {
- return &static_cast<details::any_value<ValueType>*>(operand->value)->value;
- }
- return nullptr;
- }
- template<class ValueType>
- ValueType* any_cast(any* operand) noexcept {
- if(operand != nullptr && operand->type() == typeid(ValueType)) {
- return &static_cast<details::any_value<ValueType>*>(operand->value)->value;
- }
- return nullptr;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement