ykiko 1c82060daf
Format the world. (#259)
* add some clang-format offs.

* add formats.

* format the world.

* AllowShortIfStatementsOnASingleLine

* off REGION.

* Rollback vm.hpp

* Disable insert.
2024-06-04 22:55:17 +08:00

114 lines
3.0 KiB
C++

#pragma once
#include "pocketpy/common/traits.hpp"
#include <typeindex>
#include <cassert>
#include <utility>
#include <cstdlib>
#include <cstring>
namespace pkpy {
template <typename T>
constexpr inline 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>) {
std::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 {
assert(_wrapper);
return _wrapper(_impl, std::forward<Params>(params)...);
}
};
} // namespace pkpy