any.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #pragma once
  2. #include "common.h"
  3. #include "str.h"
  4. namespace pkpy {
  5. template<typename T>
  6. inline constexpr bool is_any_sso_v = is_pod_v<T> && sizeof(T) <= sizeof(void*);
  7. struct any{
  8. struct vtable{
  9. const std::type_index type;
  10. void (*deleter)(void*);
  11. template<typename T>
  12. inline static vtable* get(){
  13. static_assert(std::is_same_v<T, std::decay_t<T>>);
  14. if constexpr (is_any_sso_v<T>){
  15. static vtable vt{ typeid(T), nullptr };
  16. return &vt;
  17. }else{
  18. static vtable vt{ typeid(T), [](void* ptr){ delete static_cast<T*>(ptr); } };
  19. return &vt;
  20. }
  21. }
  22. };
  23. void* data;
  24. vtable* _vt;
  25. any() : data(nullptr), _vt(nullptr) {}
  26. explicit operator bool() const { return _vt != nullptr; }
  27. template<typename T>
  28. any(T&& value){
  29. using U = std::decay_t<T>;
  30. static_assert(!std::is_same_v<U, any>, "any(const any&) is deleted");
  31. static_assert(sizeof(U) == sizeof(T));
  32. if constexpr (is_any_sso_v<U>){
  33. memcpy(&data, &value, sizeof(U));
  34. }else{
  35. data = new U(std::forward<T>(value));
  36. }
  37. _vt = vtable::get<U>();
  38. }
  39. any(any&& other) noexcept;
  40. any& operator=(any&& other) noexcept;
  41. const std::type_index type_id() const{
  42. return _vt ? _vt->type : typeid(void);
  43. }
  44. any(const any& other) = delete;
  45. any& operator=(const any& other) = delete;
  46. ~any() { if(_vt && _vt->deleter) _vt->deleter(data); }
  47. template<typename T>
  48. T& _cast() const noexcept{
  49. static_assert(std::is_same_v<T, std::decay_t<T>>);
  50. if constexpr (is_any_sso_v<T>){
  51. return *((T*)(&data));
  52. }else{
  53. return *(static_cast<T*>(data));
  54. }
  55. }
  56. template<typename T>
  57. T& cast() const{
  58. static_assert(std::is_same_v<T, std::decay_t<T>>);
  59. if(type_id() != typeid(T)) __bad_any_cast(typeid(T), type_id());
  60. return _cast<T>();
  61. }
  62. static void __bad_any_cast(const std::type_index expected, const std::type_index actual);
  63. };
  64. template<typename T>
  65. struct function;
  66. template<typename Ret, typename... Params>
  67. struct function<Ret(Params...)>{
  68. any _impl;
  69. Ret (*_wrapper)(const any&, Params...);
  70. function(): _impl(), _wrapper(nullptr) {}
  71. explicit operator bool() const { return _wrapper != nullptr; }
  72. template<typename F>
  73. function(F&& f) : _impl(std::forward<F>(f)){
  74. _wrapper = [](const any& impl, Params... params) -> Ret{
  75. return impl._cast<std::decay_t<F>>()(std::forward<Params>(params)...);
  76. };
  77. }
  78. Ret operator()(Params... params) const{
  79. if(!_wrapper) throw std::runtime_error("empty function");
  80. return _wrapper(_impl, std::forward<Params>(params)...);
  81. }
  82. };
  83. } // namespace pkpy