Added foundation for future reflection code.
This commit is contained in:
parent
50c6c7d6d2
commit
433c3b4633
71
include/iwa/class.hpp
Normal file
71
include/iwa/class.hpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(IWA_CLASS_HPP_INCLUDED)
|
||||||
|
#define IWA_CLASS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace iwa
|
||||||
|
{
|
||||||
|
struct Function
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClassCreationArgs
|
||||||
|
{
|
||||||
|
const class Class* parent = nullptr;
|
||||||
|
std::string name;
|
||||||
|
std::vector<Function> functions;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Class
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const Class* mParent;
|
||||||
|
std::string mName;
|
||||||
|
std::vector<Function> mFunctions;
|
||||||
|
public:
|
||||||
|
explicit Class(ClassCreationArgs args) noexcept : mParent(args.parent), mName(std::move(args.name)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& getName() const noexcept { return mName; }
|
||||||
|
[[nodiscard]] const Class* getParent() const noexcept { return mParent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClassBuilder
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const Class* mParent = nullptr;
|
||||||
|
std::string mName;
|
||||||
|
std::vector<Function> mFunctions;
|
||||||
|
public:
|
||||||
|
explicit ClassBuilder(std::string name) noexcept : mName(std::move(name)) {}
|
||||||
|
|
||||||
|
ClassBuilder& setParent(const Class* parent) noexcept
|
||||||
|
{
|
||||||
|
mParent = parent;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class make() noexcept
|
||||||
|
{
|
||||||
|
return Class({
|
||||||
|
.parent = mParent,
|
||||||
|
.name = std::move(mName),
|
||||||
|
.functions = std::move(mFunctions)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TFunction>
|
||||||
|
ClassBuilder& addFunction(const char* name, TFunction func)
|
||||||
|
{
|
||||||
|
(void) func;
|
||||||
|
mFunctions.push_back({.name = name});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(IWA_CLASS_HPP_INCLUDED)
|
@ -110,6 +110,9 @@ public:
|
|||||||
}
|
}
|
||||||
return static_cast<TExtension&>(*extensionPtr);
|
return static_cast<TExtension&>(*extensionPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reflection
|
||||||
|
static inline void buildClass(ClassBuilder& builder) noexcept;
|
||||||
private:
|
private:
|
||||||
void runDeleters(bool runAll = false);
|
void runDeleters(bool runAll = false);
|
||||||
|
|
||||||
@ -152,6 +155,13 @@ mijin::FuturePtr<std::invoke_result_t<TFunction>> Instance::runOnMainThread(TFun
|
|||||||
}
|
}
|
||||||
}(std::forward<TFunction>(function)));
|
}(std::forward<TFunction>(function)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Instance::buildClass(ClassBuilder& builder) noexcept
|
||||||
|
{
|
||||||
|
super_t::buildClass(builder);
|
||||||
|
|
||||||
|
builder.addFunction("isQuitRequested", &Instance::isQuitRequested);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // IWA_VULKAN_INSTANCE_HPP_INCLUDED
|
#endif // IWA_VULKAN_INSTANCE_HPP_INCLUDED
|
||||||
|
@ -9,10 +9,13 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <source_location>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mijin/detect.hpp>
|
||||||
#include <mijin/debug/assert.hpp>
|
#include <mijin/debug/assert.hpp>
|
||||||
|
#include "iwa/class.hpp"
|
||||||
|
|
||||||
#if !defined(IWA_OBJECTPTR_TRACKING)
|
#if !defined(IWA_OBJECTPTR_TRACKING)
|
||||||
# if !defined(KAZAN_RELEASE)
|
# if !defined(KAZAN_RELEASE)
|
||||||
@ -305,6 +308,25 @@ namespace impl
|
|||||||
void registerObject(BaseObject* object) noexcept;
|
void registerObject(BaseObject* object) noexcept;
|
||||||
void unregisterObject(BaseObject* object) noexcept;
|
void unregisterObject(BaseObject* object) noexcept;
|
||||||
[[nodiscard]] ObjectPtr<BaseObject> getRegisteredObject(object_id_t objectId) noexcept;
|
[[nodiscard]] ObjectPtr<BaseObject> getRegisteredObject(object_id_t objectId) noexcept;
|
||||||
|
[[nodiscard]] constexpr std::string getClassNameFromSourceLocation(const std::source_location& sourceLocation) noexcept
|
||||||
|
{
|
||||||
|
const char* ERROR_NAME = "<error detecting class name>";
|
||||||
|
#if MIJIN_COMPILER == MIJIN_COMPILER_GCC || MIJIN_COMPILER == MIJIN_COMPILER_CLANG
|
||||||
|
const std::string_view functionName = sourceLocation.function_name();
|
||||||
|
const std::size_t pos = functionName.find("TConcrete = ");
|
||||||
|
if (pos == std::string_view::npos) {
|
||||||
|
return ERROR_NAME;
|
||||||
|
}
|
||||||
|
const std::size_t begin = pos + 12;
|
||||||
|
const std::size_t end = functionName.find(';', begin);
|
||||||
|
if (end == std::string_view::npos) {
|
||||||
|
return ERROR_NAME;
|
||||||
|
}
|
||||||
|
return std::string(functionName.substr(begin, end - begin));
|
||||||
|
#else
|
||||||
|
return "<unsupported compiler family>";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BaseObject
|
class BaseObject
|
||||||
@ -339,6 +361,8 @@ public:
|
|||||||
[[nodiscard]] inline object_id_t getId() const noexcept { return mId; }
|
[[nodiscard]] inline object_id_t getId() const noexcept { return mId; }
|
||||||
[[nodiscard]] inline ObjectPtr<BaseObject> getPointer(bool skipCheck = false) noexcept;
|
[[nodiscard]] inline ObjectPtr<BaseObject> getPointer(bool skipCheck = false) noexcept;
|
||||||
[[nodiscard]] inline WeakObjectPtr<BaseObject> getWeakPointer() noexcept;
|
[[nodiscard]] inline WeakObjectPtr<BaseObject> getWeakPointer() noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual const Class& getClass() const = 0;
|
||||||
protected:
|
protected:
|
||||||
inline void increaseReferenceCount() noexcept
|
inline void increaseReferenceCount() noexcept
|
||||||
{
|
{
|
||||||
@ -393,6 +417,30 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Class& getClass() const override
|
||||||
|
{
|
||||||
|
return getClassObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Class& getClassObject() noexcept
|
||||||
|
{
|
||||||
|
static const Class myClass = [](std::string&& name)
|
||||||
|
{
|
||||||
|
ClassBuilder builder(std::move(name));
|
||||||
|
TConcrete::buildClass(builder);
|
||||||
|
return builder.make();
|
||||||
|
}(impl::getClassNameFromSourceLocation(std::source_location::current()));
|
||||||
|
return myClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buildClass(ClassBuilder& builder) noexcept
|
||||||
|
{
|
||||||
|
if constexpr (!std::is_same_v<TBase, BaseObject>)
|
||||||
|
{
|
||||||
|
builder.setParent(&TBase::getClassObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
template<typename... TArgs>
|
template<typename... TArgs>
|
||||||
static ObjectPtr<TConcrete> create(TArgs&&... args);
|
static ObjectPtr<TConcrete> create(TArgs&&... args);
|
||||||
@ -411,6 +459,30 @@ public:
|
|||||||
[[nodiscard]] TOwner* getOwner() const noexcept { return static_cast<TOwner*>(TBase::mOwner.getRaw()); }
|
[[nodiscard]] TOwner* getOwner() const noexcept { return static_cast<TOwner*>(TBase::mOwner.getRaw()); }
|
||||||
[[nodiscard]] ObjectPtr<TConcrete> getPointer(bool skipCheck = false) noexcept { return static_cast<ObjectPtr<TConcrete>>(BaseObject::getPointer(skipCheck)); }
|
[[nodiscard]] ObjectPtr<TConcrete> getPointer(bool skipCheck = false) noexcept { return static_cast<ObjectPtr<TConcrete>>(BaseObject::getPointer(skipCheck)); }
|
||||||
[[nodiscard]] WeakObjectPtr<TConcrete> getWeakPointer() noexcept { return static_cast<WeakObjectPtr<TConcrete>>(BaseObject::getWeakPointer()); }
|
[[nodiscard]] WeakObjectPtr<TConcrete> getWeakPointer() noexcept { return static_cast<WeakObjectPtr<TConcrete>>(BaseObject::getWeakPointer()); }
|
||||||
|
|
||||||
|
const Class& getClass() const override
|
||||||
|
{
|
||||||
|
return getClassObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Class& getClassObject() noexcept
|
||||||
|
{
|
||||||
|
static const Class myClass = [](std::string&& name)
|
||||||
|
{
|
||||||
|
ClassBuilder builder(std::move(name));
|
||||||
|
TConcrete::buildClass(builder);
|
||||||
|
return builder.make();
|
||||||
|
}(impl::getClassNameFromSourceLocation(std::source_location::current()));
|
||||||
|
return myClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buildClass(ClassBuilder& builder) noexcept
|
||||||
|
{
|
||||||
|
if constexpr (!std::is_same_v<TBase, BaseObject>)
|
||||||
|
{
|
||||||
|
builder.setParent(&TBase::getClassObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TObject>
|
template<typename TObject>
|
||||||
@ -543,6 +615,7 @@ struct std::hash<iwa::ObjectPtr<TObject>> // NOLINT false positive
|
|||||||
std::size_t operator()(const iwa::ObjectPtr<TObject>& ptr) const noexcept
|
std::size_t operator()(const iwa::ObjectPtr<TObject>& ptr) const noexcept
|
||||||
{
|
{
|
||||||
return std::hash<void*>()(ptr.getRaw());
|
return std::hash<void*>()(ptr.getRaw());
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user