[DEV] new etk::Function is now correct

This commit is contained in:
Edouard DUPIN 2017-09-11 13:27:23 +02:00
parent a19a120987
commit 5a245687f6
19 changed files with 515 additions and 366 deletions

View File

@ -110,6 +110,9 @@ void etest::init(int32_t _argc, const char** _argv) {
} else if (data == "--etest-list") { } else if (data == "--etest-list") {
listAllTest(); listAllTest();
exit(0); exit(0);
} else if (data == "--etest-filter=") {
ETEST_PRINT("Missing data in the filter list...");
exit(0);
} else if (data.startWith("--etest-filter=") == true) { } else if (data.startWith("--etest-filter=") == true) {
etk::String filter = &data[15]; etk::String filter = &data[15];
ETEST_PRINT(" Filter: " << filter); ETEST_PRINT(" Filter: " << filter);
@ -199,7 +202,7 @@ int32_t etest::runAllTest() {
} }
ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << ":"); ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << ":");
echrono::Steady ticGroup = echrono::Steady::now(); echrono::Steady ticGroup = echrono::Steady::now();
for (auto &it: getListOfTest()) { for (auto &it: runList) {
if (it->getTestGroup() != itGroup) { if (it->getTestGroup() != itGroup) {
continue; continue;
} }

View File

@ -151,7 +151,7 @@ namespace etest {
#define EXPECT_EQ(element, result) \ #define EXPECT_EQ(element, result) \
do { \ do { \
bool ETEST_VARIABLE_TMP_res = (element == result); \ bool ETEST_VARIABLE_TMP_res = ((element) == (result)); \
if (etest::g_currentTest == nullptr) { \ if (etest::g_currentTest == nullptr) { \
ETEST_CRITICAL("Not in a test"); \ ETEST_CRITICAL("Not in a test"); \
} else { \ } else { \
@ -166,7 +166,7 @@ namespace etest {
#define EXPECT_NE(element, result) \ #define EXPECT_NE(element, result) \
do { \ do { \
bool ETEST_VARIABLE_TMP_res = (element != result); \ bool ETEST_VARIABLE_TMP_res = ((element) != (result)); \
if (etest::g_currentTest == nullptr) { \ if (etest::g_currentTest == nullptr) { \
ETEST_CRITICAL("Not in a test"); \ ETEST_CRITICAL("Not in a test"); \
} else { \ } else { \

View File

@ -10,8 +10,6 @@
#include <etk/debug.hpp> #include <etk/debug.hpp>
#include <etk/stdTools.hpp> #include <etk/stdTools.hpp>
#include <etk/String.hpp> #include <etk/String.hpp>
#include <sstream>
#include <stdexcept>
class ColorList { class ColorList {
public: public:

View File

@ -10,7 +10,6 @@
#include <etk/String.hpp> #include <etk/String.hpp>
#include <etk/UString.hpp> #include <etk/UString.hpp>
#include <iomanip>
namespace etk { namespace etk {
/** /**

View File

@ -1,18 +1,22 @@
/** @file /** @file
* @author Edouard DUPIN * @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved * @copyright 2017, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file) * @license MPL v2.0 (see license file)
*/ */
#pragma once #pragma once
#include <etk/types.hpp> #include <etk/types.hpp>
//#include <ememory/UniquePtr.hpp> #include <etk/String.hpp>
//#define ETK_FUNCTION_ENABLE_NEW // TO facilitate debug when have a problem ...
#define ETK_FUNCTION_DEBUG(...) do {} while(false)
//#define ETK_FUNCTION_DEBUG printf
namespace etk { namespace etk {
template <typename ETK_TYPE_FUNCTOR, typename ETK_TYPE_FUNCTION>
class FunctionPrivateLambda;
template <typename ETK_TYPE_FUNCTION> template <typename ETK_TYPE_FUNCTION>
class FunctionPrivateSpecific; class FunctionPrivateFunction;
template <typename ETK_TYPE_FUNCTION> template <typename ETK_TYPE_FUNCTION>
class FunctionPrivate; class FunctionPrivate;
@ -22,241 +26,170 @@ namespace etk {
virtual ~FunctionPrivate() { virtual ~FunctionPrivate() {
} }
// other constructors, from nullptr, from function pointers
virtual ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const = 0; virtual ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const = 0;
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* copy() { virtual FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* copy() {
ETK_FUNCTION_DEBUG(" COPY NULLPTR \n");
return nullptr; return nullptr;
} }
}; };
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS> template <typename ETK_TYPE_FUNCTION_FUNCTOR, typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
class FunctionPrivateSpecific<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>: class FunctionPrivateLambda<ETK_TYPE_FUNCTION_FUNCTOR, ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>:
public FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> { public FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
private: private:
// function pointer types for the type-erasure behaviors ETK_TYPE_FUNCTION_FUNCTOR m_dataPointer;
// all these char* parameters are actually casted from some functor type
typedef ETK_TYPE_FUNCTION_RETURN (*invoke_fn_t)(void*, ETK_TYPE_FUNCTION_ARGS&&...);
#ifdef ETK_FUNCTION_ENABLE_NEW
typedef void* (*construct_fn_t)();
#endif
typedef void (*destroy_fn_t)(void*);
// 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)(etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
}
#ifdef ETK_FUNCTION_ENABLE_NEW
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
static void* construct_fn() {
// the functor type must be copy-constructible
return new ETK_TYPE_FUNCTION_FUNCTOR();
}
#endif
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) {
_functor->~ETK_TYPE_FUNCTION_FUNCTOR();
}
// These pointers are storing behaviors.
invoke_fn_t invoke_f;
#ifdef ETK_FUNCTION_ENABLE_NEW
construct_fn_t construct_f;
#endif
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
void* m_dataPointer;
public: public:
FunctionPrivateSpecific(): FunctionPrivateLambda(ETK_TYPE_FUNCTION_FUNCTOR _functor):
invoke_f(nullptr), m_dataPointer(_functor) {
#ifdef ETK_FUNCTION_ENABLE_NEW ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n");
construct_f(nullptr),
#endif
destroy_f(nullptr),
m_dataPointer(nullptr) {
} }
FunctionPrivateSpecific(etk::NullPtr):
invoke_f(nullptr),
#ifdef ETK_FUNCTION_ENABLE_NEW
construct_f(nullptr),
#endif
destroy_f(nullptr),
m_dataPointer(nullptr) {
}
#ifdef ETK_FUNCTION_ENABLE_NEW
// construct from any functor type
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
FunctionPrivateSpecific(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(nullptr) {
m_dataPointer = construct_f();
}
// copy constructor
/* /*
FunctionPrivateSpecific(const FunctionPrivateSpecific& _obj): FunctionPrivateLambda(const ETK_TYPE_FUNCTION_FUNCTOR& _functor):
invoke_f(_obj.invoke_f), m_dataPointer(_functor) {
construct_f(_obj.construct_f), ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n");
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
delete(m_dataPointer);
m_dataPointer = new char[m_dataSize];
construct_f(m_dataPointer, _obj.m_dataPointer);
}
} }
*/ */
#else ~FunctionPrivateLambda() {
// move from any functor type
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
FunctionPrivateSpecific(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>)),
#ifdef ETK_FUNCTION_ENABLE_NEW
construct_f(reinterpret_cast<construct_fn_t>(construct_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
#endif
destroy_f(reinterpret_cast<destroy_fn_t>(destroy_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
m_dataPointer(nullptr) {
m_dataPointer = etk::move(_functor);
} }
#endif
~FunctionPrivateSpecific() {
if (m_dataPointer != nullptr) {
destroy_f(m_dataPointer);
m_dataPointer = nullptr;
}
}
// other constructors, from nullptr, from function pointers
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const { ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const {
return invoke_f(m_dataPointer, return m_dataPointer(etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
} }
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* copy() {
bool operator!= (etk::NullPtr) const { ETK_FUNCTION_DEBUG(" COPY FunctionPrivateLambda \n");
return m_dataPointer != nullptr; return new FunctionPrivateLambda(m_dataPointer);
}
bool operator== (etk::NullPtr) const {
return m_dataPointer == nullptr;
} }
}; };
template <typename ETK_TYPE_FUNCTION> template <typename ETK_TYPE_FUNCTION>
class Function; class Function;
extern uint32_t MM___pppppp;
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS> template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> { class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
private: private:
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* m_pointerPrivate; FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* m_pointerPrivate;
uint32_t m_pppppp;
public: public:
Function(): Function():
m_pointerPrivate(nullptr) { m_pointerPrivate(nullptr) {
m_pppppp = MM___pppppp++;
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 1 \n", m_pppppp, (uint64_t)this);
} }
Function(etk::NullPtr): Function(const etk::NullPtr&):
m_pointerPrivate(nullptr) { m_pointerPrivate(nullptr) {
m_pppppp = MM___pppppp++;
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 2\n", m_pppppp, (uint64_t)this);
} }
#ifdef ETK_FUNCTION_ENABLE_NEW Function(const Function& _obj):
// construct from any functor type m_pointerPrivate(nullptr) {
template <typename ETK_TYPE_FUNCTION_FUNCTOR> m_pppppp = MM___pppppp++;
Function(ETK_TYPE_FUNCTION_FUNCTOR _functor): ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function (copy constructor) ---------------------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
m_pointerPrivate(new FunctionPrivateSpecific<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>(_functor)) {
}
// copy constructor
Function(const Function& _obj):
m_pointerPrivate(nullptr) {
if (_obj.m_pointerPrivate != nullptr) {
m_pointerPrivate = _obj.m_pointerPrivate->copy();
}
}
#else
// construct from any functor type
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
Function(ETK_TYPE_FUNCTION_FUNCTOR&& _functor):
m_pointerPrivate(new FunctionPrivateSpecific<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>(_functor)) {
}
#endif
// copy constructor
Function(Function&& _obj):
m_pointerPrivate(_obj.m_pointerPrivate) {
_obj.m_pointerPrivate = nullptr;
}
~Function() {
delete m_pointerPrivate;
m_pointerPrivate = nullptr;
}
// other constructors, from nullptr, from function pointers
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const {
if (m_pointerPrivate == nullptr) {
throw;
}
return (*m_pointerPrivate)(etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
}
bool operator!= (etk::NullPtr) const {
return m_pointerPrivate != nullptr;
}
bool operator== (etk::NullPtr) const {
return m_pointerPrivate == nullptr;
}
#ifdef ETK_FUNCTION_ENABLE_NEW
Function& operator= (const Function& _obj) {
delete m_pointerPrivate;
m_pointerPrivate = nullptr;
if (_obj.m_pointerPrivate != nullptr) { if (_obj.m_pointerPrivate != nullptr) {
m_pointerPrivate = _obj.m_pointerPrivate->copy(); m_pointerPrivate = _obj.m_pointerPrivate->copy();
} }
return *this; ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function (copy constructor) ------- (done) ------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
} }
#endif Function(Function&& _obj):
Function& operator= (Function&& _obj) { m_pointerPrivate(nullptr) {
m_pppppp = MM___pppppp++;
ETK_FUNCTION_DEBUG("[%d] new Function 2\n", m_pppppp);
_obj.swap(*this);
ETK_FUNCTION_DEBUG("[%d] new Function 2 (done)\n", m_pppppp);
}
template <typename ETK_TYPE_FUNCTION_FUNCTOR,
typename etk::EnableIf< !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,Function>::value
&& !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,etk::NullPtr>::value, int
>::type = 0
>
Function(ETK_TYPE_FUNCTION_FUNCTOR _functor):
m_pointerPrivate(nullptr) {
m_pppppp = MM___pppppp++;
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 \n", m_pppppp, (uint64_t)this);
m_pointerPrivate = new FunctionPrivateLambda<ETK_TYPE_FUNCTION_FUNCTOR, ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>(_functor);
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 (done)\n", m_pppppp, (uint64_t)this);
}
~Function() {
ETK_FUNCTION_DEBUG("[%d=0X%lx] DELETE Function \n", m_pppppp, (uint64_t)this);
delete m_pointerPrivate; delete m_pointerPrivate;
m_pointerPrivate = _obj.m_pointerPrivate; m_pointerPrivate = nullptr;
_obj.m_pointerPrivate = nullptr; }
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const {
if (m_pointerPrivate == nullptr) {
ETK_FUNCTION_DEBUG("[%d=0X%lx] call Function (With nullptr !!! ==> must assert ...)\n", m_pppppp, (uint64_t)this);
throw;
}
ETK_FUNCTION_DEBUG("[%d=0X%lx] call Function \n", m_pppppp, (uint64_t)this);
return (*m_pointerPrivate)(etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
}
Function& operator= (const Function& _obj){
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(set) Function [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
Function(_obj).swap(*this);
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(set) Function [%d=0X%lx] (done)\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
return *this; return *this;
} }
Function& operator= (Function&& _obj){
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(move) Function [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
Function(etk::move(_obj)).swap(*this);
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(move) Function [%d=0X%lx] (done)\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
return *this;
}
Function& operator= (etk::NullPtr _obj) {
delete m_pointerPrivate;
m_pointerPrivate = nullptr;
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = nullptr 0X%lx\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate);
return *this;
}
void swap(Function& _obj) {
ETK_FUNCTION_DEBUG("[%d=0X%lx] swap [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)_obj);
etk::swap(m_pointerPrivate, _obj.m_pointerPrivate);
etk::swap(m_pppppp, _obj.m_pppppp);
ETK_FUNCTION_DEBUG("[%d=0X%lx] swap [%d=0X%lx] (done)\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)_obj);
}
template <typename ETK_TYPE_FUNCTION_FUNCTOR,
typename etk::EnableIf< !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,Function>::value
&& !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,etk::NullPtr>::value, int
>::type = 0
>
Function& operator= (ETK_TYPE_FUNCTION_FUNCTOR&& _functor){
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = FUNCTOR \n", m_pppppp, (uint64_t)this);
Function(etk::forward<ETK_TYPE_FUNCTION_FUNCTOR>(_functor)).swap(*this);
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = FUNCTOR (done)\n", m_pppppp, (uint64_t)this);
return *this;
}
template <typename ETK_TYPE_FUNCTION_FUNCTOR,
typename etk::EnableIf< !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,Function>::value
&& !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,etk::NullPtr>::value, int
>::type = 0
>
Function& operator= (const ETK_TYPE_FUNCTION_FUNCTOR& _functor){
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = const FUNCTOR& \n", m_pppppp, (uint64_t)this);
Function(_functor).swap(*this);
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = const FUNCTOR& (done)\n", m_pppppp, (uint64_t)this);
return *this;
}
operator bool() const {
return m_pointerPrivate != nullptr;
}
bool operator!= (etk::NullPtr) const {
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator != nullptr ==> 0X%lx %s\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate, (m_pointerPrivate != nullptr)?"true":"false");
return m_pointerPrivate != nullptr;
}
bool operator== (etk::NullPtr) const {
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator == nullptr ==> 0X%lx %s\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate, (m_pointerPrivate == nullptr)?"true":"false");
return m_pointerPrivate == nullptr;
}
etk::String toString() const {
etk::String out = "etk::Function<..(...)>(@";
out += etk::toString((uint64_t)m_pointerPrivate);
out += ")";
return out;
}
}; };
//! @not_in_doc
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
etk::Stream& operator <<(etk::Stream& _os, const etk::Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>& _obj) {
_os << _obj.toString();
return _os;
}
} }
/*
// examples
int main()
{
int i = 0;
auto fn = [i](etk::String const& s) mutable
{
std::cout << ++i << ". " << s << std::endl;
};
fn("first"); // 1. first
fn("second"); // 2. second
// construct from lambda
::function<void(std::string const&)> f(fn);
f("third"); // 3. third
// copy from another function
::function<void(std::string const&)> g(f);
f("forth - f"); // 4. forth - f
g("forth - g"); // 4. forth - g
// capture and copy non-trivial types like std::string
std::string x("xxxx");
::function<void()> h([x]() { std::cout << x << std::endl; });
h();
::function<void()> k(h);
k();
return 0;
}
*/

79
etk/NullPtr.hpp Normal file
View File

@ -0,0 +1,79 @@
/** @file
* @author Edouard DUPIN
* @copyright 2017, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
namespace etk {
class NullPtr {
public:
template<class T>
operator T*() const {
return 0;
}
template<class C, class T>
operator T C::*() const {
return 0;
}
typedef void* (etk::NullPtr::*bool_)() const;
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) {
throw;
}
};
inline NullPtr getNullPointer() {
// etk::nullptr exists.
NullPtr n = { };
return n;
}
}
// If somebody hasn't already defined nullptr in a custom way...
#if !defined(nullptr)
#define nullptr etk::getNullPointer()
#endif
template<class T>
inline bool operator==(T* p, const etk::NullPtr) {
return p == 0;
}
template<class T>
inline bool operator==(const etk::NullPtr, T* p) {
return p == 0;
}
template<class T, class U>
inline bool operator==(T U::* p, const etk::NullPtr) {
return p == 0;
}
template<class T, class U>
inline bool operator==(const etk::NullPtr, T U::* p) {
return p == 0;
}
inline bool operator==(const etk::NullPtr, const etk::NullPtr) {
return true;
}
inline bool operator!=(const etk::NullPtr, const etk::NullPtr) {
return false;
}
inline bool operator<(const etk::NullPtr, const etk::NullPtr) {
return false;
}
inline bool operator>(const etk::NullPtr, const etk::NullPtr) {
return false;
}
inline bool operator<=(const etk::NullPtr, const etk::NullPtr) {
return true;
}
inline bool operator>=(const etk::NullPtr, const etk::NullPtr) {
return true;
}

View File

@ -13,7 +13,6 @@
#include <etk/String.hpp> #include <etk/String.hpp>
#include <etk/UString.hpp> #include <etk/UString.hpp>
#include <etk/Pair.hpp> #include <etk/Pair.hpp>
#include <memory>
#define TK_REG_DEBUG TK_HIDDEN #define TK_REG_DEBUG TK_HIDDEN
//#define TK_REG_DEBUG TK_VERBOSE //#define TK_REG_DEBUG TK_VERBOSE

View File

@ -316,11 +316,11 @@ const etk::String::Iterator etk::String::begin() const {
} }
etk::String::Iterator etk::String::end() { etk::String::Iterator etk::String::end() {
return position( size()-1 ); return position( size() );
} }
const etk::String::Iterator etk::String::end() const { const etk::String::Iterator etk::String::end() const {
return position( size()-1 ); return position( size() );
} }
void etk::String::resize(size_t _newSize, char _value) { void etk::String::resize(size_t _newSize, char _value) {

View File

@ -194,6 +194,9 @@ namespace etk {
m_string(const_cast<String*>(_obj)) { m_string(const_cast<String*>(_obj)) {
// nothing to do ... // nothing to do ...
} }
size_t getCurrent() const {
return m_current;
}
friend class String; friend class String;
}; };
private: private:
@ -359,30 +362,50 @@ namespace etk {
* @param[in] _nbElement Number of element to add in the String * @param[in] _nbElement Number of element to add in the String
*/ */
void insert(size_t _pos, const char* _item, size_t _nbElement); void insert(size_t _pos, const char* _item, size_t _nbElement);
//! @previous
void insert(const Iterator& _pos, const char* _item, size_t _nbElement) {
insert(_pos.getCurrent(), _item, _nbElement);
};
/** /**
* @brief Insert one element in the String at a specific position * @brief Insert one element in the String at a specific position
* @param[in] _pos Position to add the elements. * @param[in] _pos Position to add the elements.
* @param[in] _item Element to add. * @param[in] _item Element to add.
*/ */
void insert(size_t _pos, const char _item); void insert(size_t _pos, const char _item);
//! @previous
void insert(const Iterator& _pos, const char _item) {
insert(_pos.getCurrent(), _item);
}
/** /**
* @brief Insert one element in the String at a specific position * @brief Insert one element in the String at a specific position
* @param[in] _pos Position to add the elements. * @param[in] _pos Position to add the elements.
* @param[in] _item Element to add. * @param[in] _item Element to add.
*/ */
void insert(size_t _pos, const String& _value); void insert(size_t _pos, const String& _value);
//! @previous
void insert(const Iterator& _pos, const String& _value) {
insert(_pos.getCurrent(), _value);
}
/** /**
* @brief Remove N element * @brief Remove N element
* @param[in] _pos Position to remove the data * @param[in] _pos Position to remove the data
* @param[in] _nbElement number of element to remove * @param[in] _nbElement number of element to remove
*/ */
void erase(size_t _pos, size_t _nbElement=1); void erase(size_t _pos, size_t _nbElement=1);
//! @previous
void erase(const Iterator& _pos) {
erase(_pos.getCurrent(), 1);
}
/** /**
* @brief Remove N elements * @brief Remove N elements
* @param[in] _pos Position to remove the data * @param[in] _start Position to remove the data
* @param[in] _posEnd Last position number * @param[in] _stop Last position number
*/ */
void eraseRange(size_t _pos, size_t _posEnd); void eraseRange(size_t _start, size_t _stop);
//! @previous
void erase(const Iterator& _start, const Iterator& _stop) {
eraseRange(_start.getCurrent(), _stop.getCurrent());
}
/** /**
* @brief extract data between two point : * @brief extract data between two point :
* @param[in] _posStart start position to extract data * @param[in] _posStart start position to extract data
@ -390,6 +413,10 @@ namespace etk {
* @return the extracted string * @return the extracted string
*/ */
etk::String extract(size_t _posStart = 0, size_t _posEnd=etk::String::npos) const; etk::String extract(size_t _posStart = 0, size_t _posEnd=etk::String::npos) const;
//! @previous
etk::String extract(const Iterator& _start, const Iterator& _stop) const {
return extract(_start.getCurrent(), _stop.getCurrent());
}
/** /**
* @brief Get the pointer on the data * @brief Get the pointer on the data
* @return pointer on the "C" string * @return pointer on the "C" string
@ -401,18 +428,21 @@ namespace etk {
* @return The Iterator * @return The Iterator
*/ */
Iterator position(size_t _pos); Iterator position(size_t _pos);
//! @previous
const Iterator position(size_t _pos) const; const Iterator position(size_t _pos) const;
/** /**
* @brief Get an Iterator on the start position of the String * @brief Get an Iterator on the start position of the String
* @return The Iterator * @return The Iterator
*/ */
Iterator begin(); Iterator begin();
//! @previous
const Iterator begin() const; const Iterator begin() const;
/** /**
* @brief Get an Iterator on the end position of the String * @brief Get an Iterator on the end position of the String
* @return The Iterator * @return The Iterator
*/ */
Iterator end(); Iterator end();
//! @previous
const Iterator end() const; const Iterator end() const;
/** /**
* @brief Change the current size of the string * @brief Change the current size of the string
@ -465,6 +495,25 @@ namespace etk {
String operator+ (const char* _left, const String& _right); String operator+ (const char* _left, const String& _right);
String operator+ (const String& _left, char _right); String operator+ (const String& _left, char _right);
String operator+ (char _left, const String& _right); String operator+ (char _left, const String& _right);
inline bool operator== (const char* _left, const String& _right) {
return _right == _left;
}
inline bool operator!= (const char* _left, const String& _right) {
return _right != _left;
}
inline bool operator> (const char* _left, const String& _right) {
return _right > _left;
}
inline bool operator>= (const char* _left, const String& _right) {
return _right >= _left;
}
inline bool operator< (const char* _left, const String& _right) {
return _right < _left;
}
inline bool operator<= (const char* _left, const String& _right) {
return _right <= _left;
}
/** /**
* @brief Template to declare conversion from anything in etk::String * @brief Template to declare conversion from anything in etk::String
* @param[in] _variable Variable to convert * @param[in] _variable Variable to convert

View File

@ -195,6 +195,9 @@ namespace etk {
m_string(const_cast<UString*>(_obj)) { m_string(const_cast<UString*>(_obj)) {
// nothing to do ... // nothing to do ...
} }
size_t getCurrent() const {
return m_current;
}
friend class UString; friend class UString;
}; };
private: private:
@ -358,30 +361,50 @@ namespace etk {
* @param[in] _nbElement Number of element to add in the String * @param[in] _nbElement Number of element to add in the String
*/ */
void insert(size_t _pos, const char32_t* _item, size_t _nbElement); void insert(size_t _pos, const char32_t* _item, size_t _nbElement);
//! @previous
void insert(const Iterator& _pos, const char32_t* _item, size_t _nbElement) {
insert(_pos.getCurrent(), _item, _nbElement);
};
/** /**
* @brief Insert one element in the String at a specific position * @brief Insert one element in the String at a specific position
* @param[in] _pos Position to add the elements. * @param[in] _pos Position to add the elements.
* @param[in] _item Element to add. * @param[in] _item Element to add.
*/ */
void insert(size_t _pos, const char32_t _item); void insert(size_t _pos, const char32_t _item);
//! @previous
void insert(const Iterator& _pos, const char32_t _item) {
insert(_pos.getCurrent(), _item);
}
/** /**
* @brief Insert one element in the String at a specific position * @brief Insert one element in the String at a specific position
* @param[in] _pos Position to add the elements. * @param[in] _pos Position to add the elements.
* @param[in] _item Element to add. * @param[in] _item Element to add.
*/ */
void insert(size_t _pos, const etk::UString& _value); void insert(size_t _pos, const etk::UString& _value);
//! @previous
void insert(const Iterator& _pos, const UString& _value) {
insert(_pos.getCurrent(), _value);
}
/** /**
* @brief Remove N element * @brief Remove N element
* @param[in] _pos Position to remove the data * @param[in] _pos Position to remove the data
* @param[in] _nbElement number of element to remove * @param[in] _nbElement number of element to remove
*/ */
void erase(size_t _pos, size_t _nbElement=1); void erase(size_t _pos, size_t _nbElement=1);
//! @previous
void erase(const Iterator& _pos) {
erase(_pos.getCurrent(), 1);
}
/** /**
* @brief Remove N elements * @brief Remove N elements
* @param[in] _pos Position to remove the data * @param[in] _start Position to remove the data
* @param[in] _posEnd Last position number * @param[in] _stop Last position number
*/ */
void eraseRange(size_t _pos, size_t _posEnd); void eraseRange(size_t _start, size_t _stop);
//! @previous
void erase(const Iterator& _start, const Iterator& _stop) {
eraseRange(_start.getCurrent(), _stop.getCurrent());
}
/** /**
* @brief extract data between two point : * @brief extract data between two point :
* @param[in] _posStart start position to extract data * @param[in] _posStart start position to extract data
@ -389,6 +412,10 @@ namespace etk {
* @return the extracted string * @return the extracted string
*/ */
etk::UString extract(size_t _posStart = 0, size_t _posEnd=etk::UString::npos) const; etk::UString extract(size_t _posStart = 0, size_t _posEnd=etk::UString::npos) const;
//! @previous
etk::UString extract(const Iterator& _start, const Iterator& _stop) const {
return extract(_start.getCurrent(), _stop.getCurrent());
}
/** /**
* @brief Get the pointer on the data * @brief Get the pointer on the data
* @return pointer on the "C" string * @return pointer on the "C" string

View File

@ -10,9 +10,10 @@
#include <etk/debug.hpp> #include <etk/debug.hpp>
#include <elog/elog.hpp> #include <elog/elog.hpp>
#include <etk/os/FSNode.hpp> #include <etk/os/FSNode.hpp>
#include <etk/Function.hpp>
static int32_t nbTimeInit = 0; static int32_t nbTimeInit = 0;
uint32_t etk::MM___pppppp = 0;
void etk::unInit() { void etk::unInit() {
if (nbTimeInit > 1) { if (nbTimeInit > 1) {
nbTimeInit--; nbTimeInit--;

View File

@ -1,2 +1,35 @@
/** @file
* @author Edouard DUPIN
* @copyright 2017, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
namespace etk {
template <class TYPE> const TYPE& min(const TYPE& _val1, const TYPE& _val2) {
return (_val1 > _val2) ? _val2 : _val1;
}
template <class TYPE> const TYPE& max(const TYPE& _val1, const TYPE& _val2) {
return (_val1 > _val2) ? _val1 : _val2;
}
/**
* @brief in std, we have min, max but not avg ==> it is missing... the Define of avg template.
* @param[in] _min Minimum value of the range
* @param[in] _val The value that we want a min/max
* @param[in] _max Maximum value of the range
* @return Value that min/max applied
*/
template <class TYPE> const TYPE& avg(const TYPE& _min, const TYPE& _val, const TYPE& _max) {
return etk::min(etk::max(_min,_val),_max);
}
template<class ETK_ITERATOR_TYPE>
size_t distance(const ETK_ITERATOR_TYPE& _start, const ETK_ITERATOR_TYPE& _stop) {
size_t out = 0;
ETK_ITERATOR_TYPE tmp = _start;
while (tmp != _stop) {
out++;
++tmp;
}
return out;
}
}

View File

@ -109,4 +109,49 @@ namespace etk {
public etk::IntegralConstant<bool, __is_base_of(ETK_TYPE, ETK_TYPE_DERIVED)> { public etk::IntegralConstant<bool, __is_base_of(ETK_TYPE, ETK_TYPE_DERIVED)> {
}; };
template<typename>
struct IsFunction;
template<typename>
struct IsFunction :
public etk::typeFalse {
};
template<typename ETK_TYPE_RETURN, typename... ETK_TYPE_ARGS>
struct IsFunction<ETK_TYPE_RETURN(ETK_TYPE_ARGS...)>:
public etk::typeTrue {
};
template<typename ETK_TYPE_RETURN, typename... ETK_TYPE_ARGS>
struct IsFunction<ETK_TYPE_RETURN(ETK_TYPE_ARGS...)&>:
public etk::typeTrue {
};
template<typename ETK_TYPE_RETURN, typename... ETK_TYPE_ARGS>
struct IsFunction<ETK_TYPE_RETURN(ETK_TYPE_ARGS...)&&>:
public etk::typeTrue {
};
template<typename ETK_TYPE_RETURN, typename... ETK_TYPE_ARGS>
struct IsFunction<ETK_TYPE_RETURN(ETK_TYPE_ARGS...) const>:
public etk::typeTrue {
};
template<typename ETK_TYPE_RETURN, typename... ETK_TYPE_ARGS>
struct IsFunction<ETK_TYPE_RETURN(ETK_TYPE_ARGS...) const &>:
public etk::typeTrue {
};
template<typename ETK_TYPE_RETURN, typename... ETK_TYPE_ARGS>
struct IsFunction<ETK_TYPE_RETURN(ETK_TYPE_ARGS...) const &&>:
public etk::typeTrue {
};
} }

View File

@ -88,121 +88,8 @@ extern "C" {
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#if 0 #include <etk/NullPtr.hpp>
typedef decltype(nullptr) etk::NullPtr;
#else
namespace etk {
class NullPtr {
public:
// When tested a pointer, acts as 0.
template<class T>
operator T*() const {
return 0;
}
template<class C, class T> // When tested as a member pointer, acts as 0.
operator T C::*() const {
return 0;
}
typedef void* (etk::NullPtr::*bool_)() const;
// An rvalue of type etk::NullPtr can be converted to an rvalue of type bool; the resulting value is false.
/*
operator bool_() const {
// We can't use operator bool(){ return false; } because bool is convertable to int which breaks other required functionality.
return false;
}
*/
// We can't enable this without generating warnings about nullptr being uninitialized after being used when created without "= {}".
//void* mSizeofVoidPtr; // sizeof(etk::NullPtr) == sizeof(void*). Needs to be public if etk::NullPtr is to be a POD.
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) {
throw;
//return ETK_TYPE_FUNCTION_RETURN();
}
private:
//void operator&() const; // Address cannot be taken. ==> TODO: this is really bad, because this create an error in many code
};
inline NullPtr nullptrGet() {
// etk::nullptr exists.
NullPtr n = { };
return n;
}
}
// If somebody hasn't already defined nullptr in a custom way... #include <etk/stdTools.hpp>
#if !defined(nullptr)
#define nullptr etk::nullptrGet()
#endif
#endif
template<class T>
inline bool operator==(T* p, const etk::NullPtr) {
return p == 0;
}
template<class T>
inline bool operator==(const etk::NullPtr, T* p)
{ return p == 0; }
template<class T, class U>
inline bool operator==(T U::* p, const etk::NullPtr)
{ return p == 0; }
template<class T, class U>
inline bool operator==(const etk::NullPtr, T U::* p)
{ return p == 0; }
inline bool operator==(const etk::NullPtr, const etk::NullPtr)
{ return true; }
inline bool operator!=(const etk::NullPtr, const etk::NullPtr)
{ return false; }
inline bool operator<(const etk::NullPtr, const etk::NullPtr)
{ return false; }
inline bool operator>(const etk::NullPtr, const etk::NullPtr)
{ return false; }
inline bool operator<=(const etk::NullPtr, const etk::NullPtr)
{ return true; }
inline bool operator>=(const etk::NullPtr, const etk::NullPtr)
{ return true; }
// TODO: remove ...
// exported to global namespace.
//using etk::NullPtr;
namespace etk {
template <class TYPE> const TYPE& min(const TYPE& _val1, const TYPE& _val2) {
return (_val1 > _val2) ? _val2 : _val1;
}
template <class TYPE> const TYPE& max(const TYPE& _val1, const TYPE& _val2) {
return (_val1 > _val2) ? _val1 : _val2;
}
/**
* @brief in std, we have min, max but not avg ==> it is missing... the Define of avg template.
* @param[in] _min Minimum value of the range
* @param[in] _val The value that we want a min/max
* @param[in] _max Maximum value of the range
* @return Value that min/max applied
*/
template <class TYPE> const TYPE& avg(const TYPE& _min, const TYPE& _val, const TYPE& _max) {
return etk::min(etk::max(_min,_val),_max);
}
template<class ETK_ITERATOR_TYPE>
size_t distance(const ETK_ITERATOR_TYPE& _start, const ETK_ITERATOR_TYPE& _stop) {
size_t out = 0;
ETK_ITERATOR_TYPE tmp = _start;
while (tmp != _stop) {
out++;
++tmp;
}
return out;
}
}
#include <etk/move.hpp> #include <etk/move.hpp>
#include <etk/Stream.hpp> #include <etk/Stream.hpp>

View File

@ -51,6 +51,7 @@ def configure(target, my_module):
'etk/move.hpp', 'etk/move.hpp',
'etk/typeTrait.hpp', 'etk/typeTrait.hpp',
'etk/Function.hpp', 'etk/Function.hpp',
'etk/NullPtr.hpp',
]) ])
# build in C++ mode # build in C++ mode

View File

@ -42,6 +42,7 @@ def configure(target, my_module):
'test/testQuaternion.cpp', 'test/testQuaternion.cpp',
'test/testVector2_f.cpp', 'test/testVector2_f.cpp',
'test/testString.cpp', 'test/testString.cpp',
'test/testTrait.cpp',
]) ])
my_module.add_depend([ my_module.add_depend([
'etk', 'etk',

View File

@ -51,6 +51,7 @@ TEST(TestFunction, setALambda) {
etk::Function<void()> f_display = []() { print_num(642); };; etk::Function<void()> f_display = []() { print_num(642); };;
EXPECT_NE(f_display, nullptr); EXPECT_NE(f_display, nullptr);
} }
TEST(TestFunction, callAlLambda) { TEST(TestFunction, callAlLambda) {
globalValue = 0; globalValue = 0;
// Test contructor value // Test contructor value
@ -59,6 +60,58 @@ TEST(TestFunction, callAlLambda) {
EXPECT_EQ(globalValue, 42 + 1000); EXPECT_EQ(globalValue, 42 + 1000);
} }
class testObject {
private:
uint32_t m_id;
public:
testObject(int32_t iii) {
m_id = iii;
TEST_DEBUG("Call testObject Contructor " << m_id);
}
~testObject() {
TEST_DEBUG("Call testObject Destructor " << m_id);
}
void operator() (int32_t iii) {
globalValue = m_id + iii;
}
};
/*
TEST(TestFunction, setCallableObject) {
globalValue = 0;
// Test contructor value
testObject tmp(100000);
etk::Function<void(int32_t)> f_display = tmp;
EXPECT_NE(f_display, nullptr);
}
TEST(TestFunction, callCallableObject) {
globalValue = 0;
// Test contructor value
testObject tmp(550000);
etk::Function<void(int32_t)> f_display = tmp;
f_display(43);
EXPECT_EQ(globalValue, 43 + 550000);
}
*/
etk::Function<void(int32_t)> createTmpFunction(uint32_t _value) {
return [=](int32_t _data) { globalValue = _value + _data;};
}
TEST(TestFunction, setLambdaOnStack) {
globalValue = 0;
etk::Function<void(int32_t)> f_display = createTmpFunction(87000);
EXPECT_NE(f_display, nullptr);
}
TEST(TestFunction, callLambdaOnStack) {
globalValue = 0;
etk::Function<void(int32_t)> f_display = createTmpFunction(88000);
f_display(44);
EXPECT_EQ(globalValue, 44 + 88000);
}
/*
TEST(TestFunction, setAMemberFunction) { TEST(TestFunction, setAMemberFunction) {
globalValue = 0; globalValue = 0;
// Test contructor value // Test contructor value
@ -74,4 +127,5 @@ TEST(TestFunction, callAMemberFunction) {
f_display(foo, 16); f_display(foo, 16);
EXPECT_EQ(globalValue, 16 + 70000); EXPECT_EQ(globalValue, 16 + 70000);
} }
*/

View File

@ -11,30 +11,37 @@
TEST(typeTrait, RemoveConstVolatile_1) { TEST(typeTrait, RemoveConstVolatile_1) {
typedef std::remove_cv<const int>::type type1; typedef std::remove_cv<const int>::type type1;
EXPECT_EQ(etk::IsSame<int, type1>::value, true); auto ret = etk::IsSame<int, type1>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, RemoveConstVolatile_2) { TEST(typeTrait, RemoveConstVolatile_2) {
typedef std::remove_cv<volatile int>::type type1; typedef std::remove_cv<volatile int>::type type1;
EXPECT_EQ(etk::IsSame<int, type1>::value, true); auto ret = etk::IsSame<int, type1>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, RemoveConstVolatile_3) { TEST(typeTrait, RemoveConstVolatile_3) {
typedef std::remove_cv<const volatile int>::type type1; typedef std::remove_cv<const volatile int>::type type1;
EXPECT_EQ(etk::IsSame<int, type1>::value, true); auto ret = etk::IsSame<int, type1>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, RemoveConstVolatile_4) { TEST(typeTrait, RemoveConstVolatile_4) {
typedef std::remove_cv<const volatile int*>::type type1; typedef std::remove_cv<const volatile int*>::type type1;
EXPECT_EQ(etk::IsSame<const volatile int*, type1>::value, true); auto ret = etk::IsSame<const volatile int*, type1>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, RemoveConstVolatile_5) { TEST(typeTrait, RemoveConstVolatile_5) {
typedef std::remove_cv<int* const volatile>::type type1; typedef std::remove_cv<int* const volatile>::type type1;
EXPECT_EQ(etk::IsSame<int*, type1>::value, true); auto ret = etk::IsSame<int*, type1>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsVoid_1) { TEST(typeTrait, IsVoid_1) {
EXPECT_EQ(etk::IsVoid<void>::value, true); auto ret = etk::IsVoid<void>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsVoid_2) { TEST(typeTrait, IsVoid_2) {
EXPECT_EQ(etk::IsVoid<int>::value, false); auto ret = etk::IsVoid<int>::value;
EXPECT_EQ(ret, false);
} }
class A {}; class A {};
@ -44,52 +51,79 @@ class B : A {};
class C {}; class C {};
TEST(typeTrait, IsBaseOf_1) { TEST(typeTrait, IsBaseOf_1) {
EXPECT_EQ(etk::IsBaseOf<A, B>::value, true); auto ret = etk::IsBaseOf<A, B>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsBaseOf_2) { TEST(typeTrait, IsBaseOf_2) {
EXPECT_EQ(etk::IsBaseOf<B, A>::value, false); auto ret = etk::IsBaseOf<B, A>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsBaseOf_3) { TEST(typeTrait, IsBaseOf_3) {
EXPECT_EQ(etk::IsBaseOf<C, B>::value, false); auto ret = etk::IsBaseOf<C, B>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsBaseOf_4) { TEST(typeTrait, IsBaseOf_4) {
EXPECT_EQ(etk::IsBaseOf<C, C>::value, true); auto ret = etk::IsBaseOf<C, C>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, isSame_nullptr) {
typedef etk::NullPtr type1;
auto ret = etk::IsSame<etk::NullPtr, type1>::value;
EXPECT_EQ(ret, true);
}
/*
TEST(typeTrait, isSame_nullptr2) {
typedef etk::NullPtr type1;
auto ret = etk::IsSame<nullptr, type1>::value;
EXPECT_EQ(ret, true);
}
*/
TEST(typeTrait, IsSame_1) { TEST(typeTrait, IsSame_1) {
EXPECT_EQ(etk::IsSame<int, int32_t>::value, true); auto ret = etk::IsSame<int, int32_t>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsSame_2) { TEST(typeTrait, IsSame_2) {
EXPECT_EQ(etk::IsSame<int, int64_t>::value, false); auto ret = etk::IsSame<int, int64_t>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsSame_3) { TEST(typeTrait, IsSame_3) {
EXPECT_EQ(etk::IsSame<float, int32_t>::value, false); auto ret = etk::IsSame<float, int32_t>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsSame_4) { TEST(typeTrait, IsSame_4) {
EXPECT_EQ(etk::IsSame<int, int>::value, true); auto ret = etk::IsSame<int, int>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsSame_5) { TEST(typeTrait, IsSame_5) {
EXPECT_EQ(etk::IsSame<int, unsigned int>::value, false); auto ret = etk::IsSame<int, unsigned int>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsSame_6) { TEST(typeTrait, IsSame_6) {
EXPECT_EQ(etk::IsSame<int, signed int>::value, true); auto ret = etk::IsSame<int, signed int>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsSame_7) { TEST(typeTrait, IsSame_7) {
EXPECT_EQ(etk::IsSame<char, char>::value, true); auto ret = etk::IsSame<char, char>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsSame_8) { TEST(typeTrait, IsSame_8) {
EXPECT_EQ(etk::IsSame<char, unsigned char>::value, false); auto ret = etk::IsSame<char, unsigned char>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsSame_9) { TEST(typeTrait, IsSame_9) {
EXPECT_EQ(etk::IsSame<char, signed char>::value, false); auto ret = etk::IsSame<char, signed char>::value;
EXPECT_EQ(ret, false);
} }
@ -101,16 +135,20 @@ class K_B {};
enum class K_C {}; enum class K_C {};
TEST(typeTrait, IsClass_1) { TEST(typeTrait, IsClass_1) {
EXPECT_EQ(etk::IsClass<K_A>::value, true); auto ret = etk::IsClass<K_A>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsClass_2) { TEST(typeTrait, IsClass_2) {
EXPECT_EQ(etk::IsClass<K_B>::value, true); auto ret = etk::IsClass<K_B>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsClass_3) { TEST(typeTrait, IsClass_3) {
EXPECT_EQ(etk::IsClass<K_C>::value, false); auto ret = etk::IsClass<K_C>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsClass_4) { TEST(typeTrait, IsClass_4) {
EXPECT_EQ(etk::IsClass<int>::value, false); auto ret = etk::IsClass<int>::value;
EXPECT_EQ(ret, false);
} }
@ -129,16 +167,20 @@ struct J_C {
}; };
TEST(typeTrait, IsUnion_1) { TEST(typeTrait, IsUnion_1) {
EXPECT_EQ(etk::IsUnion<K_A>::value, false); auto ret = etk::IsUnion<K_A>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsUnion_2) { TEST(typeTrait, IsUnion_2) {
EXPECT_EQ(etk::IsUnion<K_B>::value, true); auto ret = etk::IsUnion<K_B>::value;
EXPECT_EQ(ret, true);
} }
TEST(typeTrait, IsUnion_3) { TEST(typeTrait, IsUnion_3) {
EXPECT_EQ(etk::IsUnion<K_C>::value, false); auto ret = etk::IsUnion<K_C>::value;
EXPECT_EQ(ret, false);
} }
TEST(typeTrait, IsUnion_4) { TEST(typeTrait, IsUnion_4) {
EXPECT_EQ(etk::IsUnion<int>::value, false); auto ret = etk::IsUnion<int>::value;
EXPECT_EQ(ret, false);
} }

View File

@ -32,8 +32,6 @@ TEST(TestVector2D_f, constructor) {
TEST(TestVector2D_f, constructorString) { TEST(TestVector2D_f, constructorString) {
etk::Vector2D<float> vect1("(4,-8.5)"); etk::Vector2D<float> vect1("(4,-8.5)");
EXPECT_EQ(vect1, etk::Vector2D<float>(4.0,-8.5)); EXPECT_EQ(vect1, etk::Vector2D<float>(4.0,-8.5));
EXPECT_FLOAT_EQ(vect1.y(), -8.5);
EXPECT_FLOAT_EQ(vect1.y(), -8.5);
etk::Vector2D<float> vect2("-6,5.5"); etk::Vector2D<float> vect2("-6,5.5");
EXPECT_FLOAT_EQ(vect2.x(), -6.0); EXPECT_FLOAT_EQ(vect2.x(), -6.0);
EXPECT_FLOAT_EQ(vect2.y(), 5.5); EXPECT_FLOAT_EQ(vect2.y(), 5.5);