Fully functional Any type with SOO, thanks Hopson's server for helping!
parent
9a46f2077d
commit
6579255b70
|
@ -14,14 +14,7 @@
|
|||
#pragma clang diagnostic pop
|
||||
|
||||
#include "StartGame.h"
|
||||
#include "util/Any.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// return StartGame(argc, argv);
|
||||
|
||||
auto a = Any::from<std::string>({"wee"});
|
||||
auto b = Any(a);
|
||||
b.set<int>(57);
|
||||
|
||||
std::cout << a.get<std::string>() << ", " << b.get_or<std::string>("fuck that") << std::endl;
|
||||
return StartGame(argc, argv);
|
||||
}
|
|
@ -4,27 +4,40 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <typeinfo>
|
||||
#include <functional>
|
||||
|
||||
class Any {
|
||||
constexpr static std::size_t STACK_SIZE = 32;
|
||||
public:
|
||||
Any() = default;
|
||||
|
||||
template <typename T> static Any from(const T& val) {
|
||||
Any a;
|
||||
a.set<T>(val);
|
||||
template<typename T, typename T_ = T> static Any from(T_&& val) {
|
||||
Any a {};
|
||||
a.set<T>(std::forward<T_>(val));
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename T> void set(const T& val) noexcept {
|
||||
data = std::make_shared<T>(std::move(val));
|
||||
template <typename T, typename T_ = T> void set(T_&& val) {
|
||||
type = typeid(T).hash_code();
|
||||
|
||||
if (sizeof(T) <= STACK_SIZE) {
|
||||
new(data.s) T(std::forward<T_>(val));
|
||||
stack_destructor = std::bind(&Any::delete_stack<T_>, this);
|
||||
}
|
||||
else {
|
||||
data.h = std::make_shared<T>(std::forward<T_>(val));
|
||||
stack_destructor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> const T& get() const {
|
||||
if (empty()) throw std::logic_error("Tried to get empty Any.");
|
||||
else if (type != typeid(T).hash_code()) throw std::logic_error("Any is not of type specified.");
|
||||
return *std::static_pointer_cast<T>(data);
|
||||
if (type != typeid(T).hash_code()) throw std::logic_error("Any is not of type specified.");
|
||||
|
||||
if (sizeof(T) <= STACK_SIZE) return *reinterpret_cast<T*>(const_cast<char*>(data.s));
|
||||
else return *std::static_pointer_cast<T>(data.h);
|
||||
}
|
||||
|
||||
template<typename T> const T& get_or(const T& other) const noexcept {
|
||||
|
@ -37,15 +50,33 @@ public:
|
|||
}
|
||||
|
||||
bool const empty() const noexcept {
|
||||
return !data;
|
||||
return type == 0;
|
||||
}
|
||||
|
||||
void reset() noexcept {
|
||||
data = nullptr;
|
||||
data.h = nullptr;
|
||||
stack_destructor = nullptr;
|
||||
type = 0;
|
||||
}
|
||||
|
||||
~Any() {
|
||||
if (stack_destructor) stack_destructor();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T> void delete_stack() {
|
||||
reinterpret_cast<T*>(data.s)->~T();
|
||||
}
|
||||
|
||||
std::size_t type = 0;
|
||||
std::shared_ptr<void> data = nullptr;
|
||||
std::function<void()> stack_destructor = nullptr;
|
||||
|
||||
union Data {
|
||||
char s[STACK_SIZE];
|
||||
std::shared_ptr<void> h;
|
||||
|
||||
Data() { this->h = nullptr; }
|
||||
Data(const Data& o) { memcpy(this->s, o.s, STACK_SIZE); }
|
||||
~Data() {};
|
||||
} data {};
|
||||
};
|
Loading…
Reference in New Issue