flatten 20260225
This commit is contained in:
27
tjp/core/functions/Dispatch.h
Normal file
27
tjp/core/functions/Dispatch.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
struct DispatchException;
|
||||
|
||||
struct Variable;
|
||||
|
||||
template<typename T>
|
||||
struct StackVariable;
|
||||
|
||||
typedef std::function<void(Variable &result, Variable &¶m)> DispatchFunction;
|
||||
|
||||
template<typename R, typename T>
|
||||
DispatchFunction asDispatchFunction(std::function<R(T)> &&f);
|
||||
|
||||
struct FunctionDispatchOnParam;
|
||||
struct FunctionDispatchOnReturn;
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
199
tjp/core/functions/Dispatch.hpp
Normal file
199
tjp/core/functions/Dispatch.hpp
Normal file
@@ -0,0 +1,199 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Dispatch.h"
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
#include <tjp/core/exception/Exception.hpp>
|
||||
#include <tjp/core/rtti/RTTI.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
struct DispatchException : Exception
|
||||
{
|
||||
typedef Exception Super;
|
||||
DispatchException(const type_index &what) : Super("DispatchException") {}
|
||||
};
|
||||
|
||||
struct Variable
|
||||
{
|
||||
void *v;
|
||||
type_index type;
|
||||
|
||||
template<typename T>
|
||||
Variable(const T &t) :
|
||||
type(type_id<T>())
|
||||
{
|
||||
v = reinterpret_cast<void *>(const_cast<T *>(&t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T &deref ()
|
||||
{
|
||||
debug_assert(type_id<T>() == type);
|
||||
return *reinterpret_cast<T *>(v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T &&move ()
|
||||
{
|
||||
debug_assert(type_id<T>() == type);
|
||||
return std::move(*reinterpret_cast<T *>(v));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Variable &operator =(T &&t)
|
||||
{
|
||||
deref<T>() = std::move(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Variable &operator =(const T &t)
|
||||
{
|
||||
deref<T>() = t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
Variable () :
|
||||
v(nullptr),
|
||||
type(type_id<void>())
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
void ref(const T &t)
|
||||
{
|
||||
type = { type_id<T>() };
|
||||
v = reinterpret_cast<void *>(const_cast<T *>(&t));
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct StackVariable : Variable
|
||||
{
|
||||
T t;
|
||||
|
||||
StackVariable()
|
||||
{
|
||||
ref(t);
|
||||
}
|
||||
|
||||
operator T()
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
T &&move()
|
||||
{
|
||||
return std::move(t);
|
||||
}
|
||||
} ;
|
||||
|
||||
typedef std::function<void(Variable &result, Variable &¶m)> DispatchFunction;
|
||||
|
||||
template<typename R, typename T>
|
||||
DispatchFunction asDispatchFunction(std::function<R(T)> &&f)
|
||||
{
|
||||
return [f](Variable &result, Variable &¶m) -> void {
|
||||
auto v = f(param.deref<T>());
|
||||
auto &r = result.deref<R>();
|
||||
r = v;
|
||||
} ;
|
||||
}
|
||||
|
||||
struct FunctionDispatchOnParam
|
||||
{
|
||||
std::map<type_index, DispatchFunction> dispatch;
|
||||
|
||||
void execute(Variable &result, Variable &¶m)
|
||||
{
|
||||
auto &type = param.type;
|
||||
|
||||
auto i = dispatch.find(type);
|
||||
if (i == dispatch.end())
|
||||
{
|
||||
debug_assert(false);
|
||||
throw DispatchException(type);
|
||||
}
|
||||
|
||||
i->second(result, std::move(param));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T execute(Variable &¶m)
|
||||
{
|
||||
StackVariable<T> result;
|
||||
execute(result, std::move(param));
|
||||
return result;
|
||||
}
|
||||
|
||||
void bind(const type_index &type, DispatchFunction &&f)
|
||||
{
|
||||
dispatch[type] = std::move(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bind(std::function<void(Variable &result, Variable &¶m)> &&f)
|
||||
{
|
||||
bind(type_id<T>(), std::move(f));
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
void bind(std::function<R(const T&)> &&f)
|
||||
{
|
||||
bind(type_id<T>(), asDispatchFunction<R, T>(f));
|
||||
}
|
||||
} ;
|
||||
|
||||
struct FunctionDispatchOnReturn
|
||||
{
|
||||
std::map<type_index, DispatchFunction> dispatch;
|
||||
|
||||
void execute(Variable &result, Variable &¶m)
|
||||
{
|
||||
auto &type = result.type;
|
||||
auto i = dispatch.find(type);
|
||||
if (i == dispatch.end())
|
||||
{
|
||||
debug_assert(false);
|
||||
throw DispatchException(type);
|
||||
}
|
||||
|
||||
i->second(result, std::move(param));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T execute(Variable &¶m)
|
||||
{
|
||||
StackVariable<T> result;
|
||||
execute(result, std::move(param));
|
||||
return result;
|
||||
}
|
||||
|
||||
void bind(const type_index &type, DispatchFunction &&f)
|
||||
{
|
||||
dispatch[type] = f;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void bind(std::function<void(Variable &result, Variable &¶m)> &&f)
|
||||
{
|
||||
bind(type_id<R>(), std::move(f));
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
void bind(std::function<R(const T&)> &&f)
|
||||
{
|
||||
bind(type_id<R>(), asDispatchFunction<R, T>(f));
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
18
tjp/core/functions/optional_function.h
Normal file
18
tjp/core/functions/optional_function.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename R>
|
||||
struct optional_function_result;
|
||||
|
||||
template<>
|
||||
struct optional_function_result<void>;
|
||||
|
||||
template<typename F>
|
||||
class optional_function;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
132
tjp/core/functions/optional_function.hpp
Normal file
132
tjp/core/functions/optional_function.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "optional_function.h"
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef SYS_LINUX
|
||||
//#define HAS_OPTIONAL
|
||||
#endif
|
||||
|
||||
#ifdef HAS_OPTIONAL
|
||||
#include <experimental/optional>
|
||||
#endif
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
#ifdef HAS_OPTIONAL
|
||||
|
||||
template<typename T>
|
||||
using optional_type = std::optional<T>;
|
||||
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
struct optional_type {
|
||||
T t;
|
||||
|
||||
optional_type() {}
|
||||
optional_type(T &&t_) : t(t_) { hasResult = true; }
|
||||
|
||||
T &operator *() { return t; }
|
||||
const T &operator *() const { return t; }
|
||||
|
||||
bool hasResult = false;
|
||||
bool has_result() const { return hasResult; }
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
template<typename R>
|
||||
struct optional_function_result : optional_type<R> {
|
||||
typedef optional_type<R> super_type;
|
||||
|
||||
optional_function_result() :
|
||||
super_type() {}
|
||||
|
||||
optional_function_result(R &&result_) :
|
||||
super_type(std::forward<R>(result_)) {}
|
||||
|
||||
bool executed() const { return this->has_result(); }
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct optional_function_result<void>
|
||||
{
|
||||
bool executed_;
|
||||
|
||||
optional_function_result(bool &&executed__) :
|
||||
executed_ (executed__) {}
|
||||
|
||||
bool executed() const { return executed_; }
|
||||
} ;
|
||||
|
||||
template<typename F>
|
||||
class optional_function
|
||||
{
|
||||
public:
|
||||
typedef std::function<F> function_type;
|
||||
typedef typename std::function<F>::result_type function_result_type;
|
||||
typedef optional_function_result<typename function_type::result_type> result_type;
|
||||
|
||||
protected:
|
||||
function_type f;
|
||||
|
||||
public:
|
||||
|
||||
template<typename Fn>
|
||||
optional_function operator=(const Fn &f_)
|
||||
{
|
||||
f = f_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Fn>
|
||||
optional_function operator=(Fn &&f_)
|
||||
{
|
||||
f = std::forward<Fn>(f_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return (bool)f;
|
||||
}
|
||||
|
||||
template<
|
||||
typename ... Args,
|
||||
typename FR=function_result_type,
|
||||
typename std::enable_if<!std::is_void<FR>::value, FR>::type* = nullptr
|
||||
>
|
||||
result_type operator()(Args... args) const
|
||||
{
|
||||
if (f)
|
||||
return {
|
||||
std::forward<typename function_type::result_type>(f(args...))
|
||||
};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<
|
||||
typename ... Args,
|
||||
typename FR=function_result_type,
|
||||
typename std::enable_if<std::is_void<FR>::value, FR>::type* = nullptr
|
||||
>
|
||||
result_type operator()(Args... args) const
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
f(args...);
|
||||
return { true };
|
||||
}
|
||||
|
||||
return { false };
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user