| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- #pragma once
- #include "common.h"
- #include "str.h"
- namespace pkpy {
- template<typename T>
- inline constexpr bool is_any_sso_v = is_pod_v<T> && sizeof(T) <= sizeof(void*);
- struct any{
- struct vtable{
- const std::type_index type;
- void (*deleter)(void*);
- template<typename T>
- inline static vtable* get(){
- static_assert(std::is_same_v<T, std::decay_t<T>>);
- if constexpr (is_any_sso_v<T>){
- static vtable vt{ typeid(T), nullptr };
- return &vt;
- }else{
- static vtable vt{ typeid(T), [](void* ptr){ delete static_cast<T*>(ptr); } };
- return &vt;
- }
- }
- };
- void* data;
- vtable* _vt;
- any() : data(nullptr), _vt(nullptr) {}
- explicit operator bool() const { return _vt != nullptr; }
- template<typename T>
- any(T&& value){
- using U = std::decay_t<T>;
- static_assert(!std::is_same_v<U, any>, "any(const any&) is deleted");
- static_assert(sizeof(U) == sizeof(T));
- if constexpr (is_any_sso_v<U>){
- memcpy(&data, &value, sizeof(U));
- }else{
- data = new U(std::forward<T>(value));
- }
- _vt = vtable::get<U>();
- }
- any(any&& other) noexcept;
- any& operator=(any&& other) noexcept;
- const std::type_index type_id() const{
- return _vt ? _vt->type : typeid(void);
- }
- any(const any& other) = delete;
- any& operator=(const any& other) = delete;
- ~any() { if(_vt && _vt->deleter) _vt->deleter(data); }
- template<typename T>
- T& _cast() const noexcept{
- static_assert(std::is_same_v<T, std::decay_t<T>>);
- if constexpr (is_any_sso_v<T>){
- return *((T*)(&data));
- }else{
- return *(static_cast<T*>(data));
- }
- }
- template<typename T>
- T& cast() const{
- static_assert(std::is_same_v<T, std::decay_t<T>>);
- if(type_id() != typeid(T)) __bad_any_cast(typeid(T), type_id());
- return _cast<T>();
- }
- static void __bad_any_cast(const std::type_index expected, const std::type_index actual);
- };
- template<typename T>
- struct function;
- template<typename Ret, typename... Params>
- struct function<Ret(Params...)>{
- any _impl;
- Ret (*_wrapper)(const any&, Params...);
- function(): _impl(), _wrapper(nullptr) {}
- explicit operator bool() const { return _wrapper != nullptr; }
- template<typename F>
- function(F&& f) : _impl(std::forward<F>(f)){
- _wrapper = [](const any& impl, Params... params) -> Ret{
- return impl._cast<std::decay_t<F>>()(std::forward<Params>(params)...);
- };
- }
- Ret operator()(Params... params) const{
- if(!_wrapper) throw std::runtime_error("empty function");
- return _wrapper(_impl, std::forward<Params>(params)...);
- }
- };
- } // namespace pkpy
|