[DEV] fork on etk::Function
This commit is contained in:
parent
4abbcad222
commit
69b8f326d4
@ -5,12 +5,14 @@
|
||||
*/
|
||||
|
||||
#include <etk/types.hpp>
|
||||
//#include <ememory/UniquePtr.hpp>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace etk {
|
||||
template <typename ETK_TYPE_FUNCTION>
|
||||
class Function;
|
||||
|
||||
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
|
||||
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
|
||||
// function pointer types for the type-erasure behaviors
|
||||
@ -18,24 +20,23 @@ namespace etk {
|
||||
typedef ETK_TYPE_FUNCTION_RETURN (*invoke_fn_t)(char*, ETK_TYPE_FUNCTION_ARGS&&...);
|
||||
typedef void (*construct_fn_t)(char*, char*);
|
||||
typedef void (*destroy_fn_t)(char*);
|
||||
|
||||
// type-aware generic functions for invoking
|
||||
// the specialization of these functions won't be capable with
|
||||
// the above function pointer types, so we need some cast
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
static ETK_TYPE_FUNCTION_RETURN invoke_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor,
|
||||
ETK_TYPE_FUNCTION_ARGS&&... _args) {
|
||||
return (*_functor)(std::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
|
||||
return (*_functor)(etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
|
||||
}
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
static void construct_fn(ETK_TYPE_FUNCTION_FUNCTOR* _constructDestination,
|
||||
ETK_TYPE_FUNCTION_FUNCTOR* _constructSource) {
|
||||
// the functor type must be copy-constructible
|
||||
new (_constructDestination) Functor(*_constructSource);
|
||||
new (_constructDestination) Function(*_constructSource);
|
||||
}
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) {
|
||||
_functor->~Functor();
|
||||
_functor->~Function();
|
||||
}
|
||||
// These pointers are storing behaviors.
|
||||
invoke_fn_t invoke_f;
|
||||
@ -43,10 +44,10 @@ namespace etk {
|
||||
destroy_fn_t destroy_f;
|
||||
// Erase the type of any functor and store it into a char*
|
||||
// so the storage size should be obtained as well
|
||||
std::unique_ptr<char[]> m_dataPointer;
|
||||
char* m_dataPointer;
|
||||
size_t m_dataSize;
|
||||
public:
|
||||
function()
|
||||
Function()
|
||||
: invoke_f(nullptr)
|
||||
, construct_f(nullptr)
|
||||
, destroy_f(nullptr)
|
||||
@ -56,42 +57,45 @@ namespace etk {
|
||||
|
||||
// construct from any functor type
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
Function(ETK_TYPE_FUNCTION_FUNCTOR _funtor)
|
||||
Function(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
||||
// specialize functions and erase their type info by casting
|
||||
: invoke_f(reinterpret_cast<invoke_fn_t>(invoke_fn<ETK_TYPE_FUNCTION_FUNCTOR>))
|
||||
, construct_f(reinterpret_cast<construct_fn_t>(construct_fn<ETK_TYPE_FUNCTION_FUNCTOR>))
|
||||
, destroy_f(reinterpret_cast<destroy_fn_t>(destroy_fn<ETK_TYPE_FUNCTION_FUNCTOR>))
|
||||
, m_dataPointer(new char[sizeof(ETK_TYPE_FUNCTION_FUNCTOR)])
|
||||
, m_dataSize(sizeof(ETK_TYPE_FUNCTION_FUNCTOR))
|
||||
{
|
||||
invoke_f(reinterpret_cast<invoke_fn_t>(invoke_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
|
||||
construct_f(reinterpret_cast<construct_fn_t>(construct_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
|
||||
destroy_f(reinterpret_cast<destroy_fn_t>(destroy_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
|
||||
m_dataPointer(new char[sizeof(ETK_TYPE_FUNCTION_FUNCTOR)]),
|
||||
m_dataSize(sizeof(ETK_TYPE_FUNCTION_FUNCTOR)) {
|
||||
// copy the functor to internal storage
|
||||
this->construct_f(this->m_dataPointer.get(), reinterpret_cast<char*>(&_functor));
|
||||
construct_f(m_dataPointer, reinterpret_cast<char*>(&_functor));
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
Function(Function const& rhs):
|
||||
invoke_f(rhs.invoke_f),
|
||||
construct_f(rhs.construct_f)
|
||||
destroy_f(rhs.destroy_f),
|
||||
dataSize(rhs.dataSize) {
|
||||
if (this->invoke_f) {
|
||||
Function(Function const& _obj):
|
||||
invoke_f(_obj.invoke_f),
|
||||
construct_f(_obj.construct_f),
|
||||
destroy_f(_obj.destroy_f),
|
||||
m_dataSize(_obj.m_dataSize) {
|
||||
if (invoke_f) {
|
||||
// when the source is not a null function, copy its internal functor
|
||||
this->m_dataPointer.reset(new char[this->m_dataSize]);
|
||||
this->construct_f(this->m_dataPointer.get(), rhs.m_dataPointer.get());
|
||||
delete(m_dataPointer);
|
||||
m_dataPointer = new char[m_dataSize];
|
||||
construct_f(m_dataPointer, _obj.m_dataPointer);
|
||||
}
|
||||
}
|
||||
|
||||
~Function() {
|
||||
if (m_dataPointer != nullptr) {
|
||||
this->destroy_f(this->m_dataPointer.get());
|
||||
destroy_f(m_dataPointer);
|
||||
delete m_dataPointer;
|
||||
}
|
||||
}
|
||||
|
||||
// other constructors, from nullptr, from function pointers
|
||||
|
||||
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS&&... _args) {
|
||||
return this->invoke_f(this->m_dataPointer.get(),
|
||||
std::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
|
||||
return invoke_f(m_dataPointer,
|
||||
etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
|
||||
}
|
||||
bool operator!= (nullptr_t) const {
|
||||
return m_dataPointer != nullptr;
|
||||
}
|
||||
bool operator== (nullptr_t) const {
|
||||
return m_dataPointer == nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
47
etk/move.hpp
47
etk/move.hpp
@ -8,25 +8,62 @@
|
||||
|
||||
namespace etk {
|
||||
template<class ETK_MOVE_TYPE>
|
||||
struct _Remove_reference {
|
||||
struct RemoveReference {
|
||||
// remove reference
|
||||
typedef ETK_MOVE_TYPE m_type;
|
||||
};
|
||||
template<class ETK_MOVE_TYPE>
|
||||
struct _Remove_reference<ETK_MOVE_TYPE&> {
|
||||
struct RemoveReference<ETK_MOVE_TYPE&> {
|
||||
// remove reference
|
||||
typedef ETK_MOVE_TYPE m_type;
|
||||
};
|
||||
template<class ETK_MOVE_TYPE>
|
||||
struct _Remove_reference<ETK_MOVE_TYPE&&> {
|
||||
struct RemoveReference<ETK_MOVE_TYPE&&> {
|
||||
// remove rvalue reference
|
||||
typedef ETK_MOVE_TYPE m_type;
|
||||
};
|
||||
|
||||
template<class ETK_MOVE_TYPE> inline
|
||||
typename etk::_Remove_reference<ETK_MOVE_TYPE>::m_type&& move(ETK_MOVE_TYPE&& _obj) {
|
||||
typename etk::RemoveReference<ETK_MOVE_TYPE>::m_type&& move(ETK_MOVE_TYPE&& _obj) {
|
||||
// forward _Arg as movable
|
||||
return ((typename etk::_Remove_reference<ETK_MOVE_TYPE>::m_type&&)_obj);
|
||||
return ((typename etk::RemoveReference<ETK_MOVE_TYPE>::m_type&&)_obj);
|
||||
}
|
||||
template<typename ETK_SWAP_TYPE>
|
||||
inline void swap(ETK_SWAP_TYPE& _obj1, ETK_SWAP_TYPE& _obj2) {
|
||||
ETK_SWAP_TYPE tmp = etk::move(_obj1);
|
||||
_obj1 = etk::move(_obj2);
|
||||
_obj2 = etk::move(tmp);
|
||||
}
|
||||
|
||||
template<class ETK_TYPE, ETK_TYPE v>
|
||||
struct integralConstant {
|
||||
static constexpr ETK_TYPE value = v;
|
||||
typedef ETK_TYPE typeValue;
|
||||
// using injected-class-name
|
||||
typedef integralConstant type;
|
||||
constexpr operator typeValue() const noexcept {
|
||||
return value;
|
||||
}
|
||||
constexpr typeValue operator()() const noexcept {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
typedef etk::integralConstant<bool, true> typeTrue;
|
||||
typedef etk::integralConstant<bool, false> typeFalse;
|
||||
|
||||
template<class ETK_TYPE>
|
||||
struct isLeftValueReference : etk::typeFalse {};
|
||||
template<class ETK_TYPE>
|
||||
struct isLeftValueReference<ETK_TYPE&> : etk::typeTrue {};
|
||||
|
||||
template <class ETK_FORWARD_TYPE>
|
||||
inline ETK_FORWARD_TYPE&& forward(typename etk::RemoveReference<ETK_FORWARD_TYPE>::m_type& _obj) noexcept {
|
||||
return static_cast<ETK_FORWARD_TYPE&&>(_obj);
|
||||
}
|
||||
template <class ETK_FORWARD_TYPE>
|
||||
inline ETK_FORWARD_TYPE&& forward(typename etk::RemoveReference<ETK_FORWARD_TYPE>::m_type&& _obj) noexcept {
|
||||
static_assert(!etk::isLeftValueReference<ETK_FORWARD_TYPE>::type, "Can not forward an rvalue as an lvalue.");
|
||||
return static_cast<ETK_FORWARD_TYPE&&>(_obj);
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,18 @@
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
// defien type : uintXX_t and intXX_t
|
||||
#define __STDC_LIMIT_MACROS
|
||||
// note in android include the macro of min max are overwitten
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
}
|
||||
// in case of android error ...
|
||||
#ifdef __TARGET_OS__Android
|
||||
#if __ANDROID_BOARD_ID__ <= 20
|
||||
@ -42,7 +45,9 @@
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cmath>
|
||||
extern "C" {
|
||||
#include <math.h>
|
||||
}
|
||||
#ifndef _MATH_H_MATHDEF
|
||||
//! @brief Generate a basic type for floating point unit selection (not finished)
|
||||
using float_t = float;
|
||||
|
@ -8,11 +8,6 @@
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <etk/stdTools.hpp>
|
||||
|
||||
namespace etk {
|
||||
|
@ -33,6 +33,7 @@ def configure(target, my_module):
|
||||
'etk/utf8.cpp',
|
||||
'etk/stdTools.cpp',
|
||||
'etk/Stream.cpp',
|
||||
'etk/Function.cpp',
|
||||
])
|
||||
|
||||
my_module.add_header_file([
|
||||
@ -47,6 +48,7 @@ def configure(target, my_module):
|
||||
'etk/Pair.hpp',
|
||||
'etk/Map.hpp',
|
||||
'etk/move.hpp',
|
||||
'etk/Function.hpp',
|
||||
])
|
||||
|
||||
# build in C++ mode
|
||||
@ -56,7 +58,6 @@ def configure(target, my_module):
|
||||
'c',
|
||||
'm',
|
||||
"pthread",
|
||||
"cxx",
|
||||
])
|
||||
|
||||
if "Android" in target.get_type():
|
||||
|
Loading…
x
Reference in New Issue
Block a user