any.hpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #pragma once
  2. #include <typeinfo>
  3. #include <nall/traits.hpp>
  4. namespace nall {
  5. struct any {
  6. any() = default;
  7. any(const any& source) { operator=(source); }
  8. any(any&& source) { operator=(move(source)); }
  9. template<typename T> any(const T& value) { operator=(value); }
  10. ~any() { reset(); }
  11. explicit operator bool() const { return container; }
  12. auto reset() -> void { if(container) { delete container; container = nullptr; } }
  13. auto type() const -> const std::type_info& {
  14. return container ? container->type() : typeid(void);
  15. }
  16. template<typename T> auto is() const -> bool {
  17. return type() == typeid(typename remove_reference<T>::type);
  18. }
  19. template<typename T> auto get() -> T& {
  20. if(!is<T>()) throw;
  21. return static_cast<holder<typename remove_reference<T>::type>*>(container)->value;
  22. }
  23. template<typename T> auto get() const -> const T& {
  24. if(!is<T>()) throw;
  25. return static_cast<holder<typename remove_reference<T>::type>*>(container)->value;
  26. }
  27. template<typename T> auto get(const T& fallback) const -> const T& {
  28. if(!is<T>()) return fallback;
  29. return static_cast<holder<typename remove_reference<T>::type>*>(container)->value;
  30. }
  31. template<typename T> auto operator=(const T& value) -> any& {
  32. using auto_t = typename conditional<is_array<T>::value, typename remove_extent<typename add_const<T>::type>::type*, T>::type;
  33. if(type() == typeid(auto_t)) {
  34. static_cast<holder<auto_t>*>(container)->value = (auto_t)value;
  35. } else {
  36. if(container) delete container;
  37. container = new holder<auto_t>((auto_t)value);
  38. }
  39. return *this;
  40. }
  41. auto operator=(const any& source) -> any& {
  42. if(container) { delete container; container = nullptr; }
  43. if(source.container) container = source.container->copy();
  44. return *this;
  45. }
  46. auto operator=(any&& source) -> any& {
  47. if(container) delete container;
  48. container = source.container;
  49. source.container = nullptr;
  50. return *this;
  51. }
  52. private:
  53. struct placeholder {
  54. virtual ~placeholder() = default;
  55. virtual auto type() const -> const std::type_info& = 0;
  56. virtual auto copy() const -> placeholder* = 0;
  57. };
  58. placeholder* container = nullptr;
  59. template<typename T> struct holder : placeholder {
  60. holder(const T& value) : value(value) {}
  61. auto type() const -> const std::type_info& { return typeid(T); }
  62. auto copy() const -> placeholder* { return new holder(value); }
  63. T value;
  64. };
  65. };
  66. }