[DEV] fork on etk::Function

This commit is contained in:
Edouard DUPIN 2017-09-02 23:20:24 +02:00
parent 4abbcad222
commit 69b8f326d4
5 changed files with 94 additions and 52 deletions

View File

@ -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)
// 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))
{
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)) {
// 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;
}
};
}

View File

@ -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);
}
}

View File

@ -4,15 +4,18 @@
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <cstdlib>
#include <cstdio>
#include <stdarg.h>
#include <cstring>
#include <cassert>
// defien type : uintXX_t and intXX_t
#define __STDC_LIMIT_MACROS
// note in android include the macro of min max are overwitten
#include <cstdint>
extern "C" {
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#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 <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;

View File

@ -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 {

View File

@ -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():