#pragma once #ifndef SCRIPTARGUMENTS_H #define SCRIPTARGUMENTS_H #include #include #include #include "ScriptObject.h" class IScriptFunction; namespace detail { template inline void InvalidateBinding(T val) { } template inline void InvalidateBinding(IScriptObject* val) { // Decrease reference for wrapped objects val->decreaseReference(); } template inline void ValidateBinding(T val) { } template inline void ValidateBinding(IScriptObject* val) { // Increase reference for wrapped objects val->increaseReference(); } }; class IScriptArguments { public: IScriptArguments() = default; virtual ~IScriptArguments() = default; virtual bool Invoke(IScriptFunction *func, bool catchExceptions = false) = 0; }; template class ScriptArguments : public IScriptArguments { public: template ScriptArguments(Args&&... An) : IScriptArguments(), _resolved(false), _tuple(std::forward(An)...) { validate_args(std::index_sequence_for{}); } virtual ~ScriptArguments() { if (!_resolved) { invalidate_args(std::index_sequence_for{}); } } virtual bool Invoke(IScriptFunction *func, bool catchExceptions = false) = 0; inline size_t Count() const { return Argc; } inline const std::tuple & Args() const { return _tuple; } protected: static constexpr int Argc = (sizeof...(Ts)); bool _resolved; std::tuple _tuple; private: template inline void invalidate_args(std::index_sequence) { if constexpr (sizeof...(Is) > 0) { int unused[] = { ((detail::InvalidateBinding(std::get(_tuple))), void(), 0)... }; static_cast(unused); // Avoid warning for unused variable } } template inline void validate_args(std::index_sequence) { if constexpr (sizeof...(Is) > 0) { int unused[] = { ((detail::ValidateBinding(std::get(_tuple))), void(), 0)... }; static_cast(unused); // Avoid warning for unused variable } } }; #endif