-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
39 changed files
with
3,636 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
cmake_minimum_required(VERSION 3.11) | ||
|
||
project(hope-core-main) | ||
|
||
enable_testing() | ||
|
||
set(CMAKE_CXX_STANDARD 17) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
||
add_subdirectory(test) | ||
add_subdirectory(lib) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
cmake_minimum_required(VERSION 3.11) | ||
|
||
project(hope-core) | ||
|
||
set(CMAKE_CXX_STANDARD 17) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
||
file(GLOB HOPE_HEADERS | ||
hope_core/fsm*.h | ||
hope_core/switch_expression*.h | ||
hope_core/tuple*.h | ||
hope_core/type_traits*.h | ||
) | ||
|
||
add_library(hope-core INTERFACE ${HOPE_HEADERS}) | ||
target_include_directories(hope-core INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) | ||
|
||
set(CMAKE_INSTALL_DIRECTORY ${CMAKE_BINARY_DIR}) | ||
INSTALL(DIRECTORY hope_core/ DESTINATION ${CMAKE_INSTALL_DIRECTORY}/include/hope_core | ||
FILES_MATCHING PATTERN "*.h") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* Copyright (C) 2021 - 2024 Gleb Bezborodov - All Rights Reserved | ||
* You may use, distribute and modify this code under the | ||
* terms of the MIT license. | ||
* | ||
* You should have received a copy of the MIT license with | ||
* this file. If not, please write to: bezborodoff.gleb@gmail.com, or visit : https://github.com/glensand/hope-core | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "hope/tuple/flat_tuple.h" | ||
#include <variant> | ||
|
||
namespace hope::fsm { | ||
|
||
template <typename State> | ||
struct transit_to final { | ||
using target_state_t = State; | ||
}; | ||
|
||
template <typename, typename... Ts> | ||
class fsm; | ||
|
||
template <typename... States, typename... Handlers> | ||
class fsm<flat_tuple<States...>, Handlers...> final : public Handlers... { | ||
public: | ||
using Handlers::operator()...; | ||
|
||
constexpr explicit fsm(Handlers&&... handlers) | ||
: Handlers(std::forward<Handlers>(handlers))...{ } | ||
|
||
template<typename Event> | ||
void on_event(Event&& e) { | ||
std::size_t state_index{ 0 }; | ||
bool transition_done{ false }; | ||
for_each(states, [&] (auto&& state){ | ||
if(!transition_done && state_index == cur_state) { | ||
using state_t = std::decay_t<decltype(state)>; | ||
if constexpr (std::is_invocable_v<fsm, state_t, Event&&>) { | ||
using result_t = std::invoke_result_t<fsm, state_t, Event&&>; | ||
auto transition_res = this->operator()(state, std::forward<Event>(e)); | ||
(void)transition_res; // remove unused variable warning (var is handled 'cause it may be used later) | ||
if constexpr (!std::is_same_v<result_t, void>) { // move to next state | ||
cur_state = find<typename result_t::target_state_t>(type_list<States...>{}); | ||
transition_done = true; | ||
} | ||
} | ||
} | ||
++state_index; | ||
}); | ||
} | ||
|
||
[[nodiscard]] std::size_t get_cur_state() const noexcept { | ||
return cur_state; | ||
} | ||
|
||
private: | ||
flat_tuple<States...> states; | ||
std::size_t cur_state{ 0 }; | ||
}; | ||
|
||
template <typename... States, typename... Handlers> | ||
constexpr auto make(Handlers&&... handlers) { | ||
return fsm<flat_tuple<States...>, Handlers...>(std::forward<Handlers>(handlers)...); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* Copyright (C) 2021 - 2024 Gleb Bezborodov - All Rights Reserved | ||
* You may use, distribute and modify this code under the | ||
* terms of the MIT license. | ||
* | ||
* You should have received a copy of the MIT license with | ||
* this file. If not, please write to: bezborodoff.gleb@gmail.com, or visit : https://github.com/glensand/hope-core | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <tuple> | ||
#include "hope_core/type_traits/type_list.h" | ||
|
||
namespace hope { | ||
|
||
template<typename... Ts> | ||
class switch_expression_member final { | ||
static_assert(sizeof ...(Ts) > 0); | ||
public: | ||
explicit switch_expression_member(const Ts&... args) | ||
: expression(args...) { | ||
|
||
} | ||
|
||
template<typename TKey, typename TClass, typename... TVs> | ||
bool apply(TClass& instance, const TKey& key, TVs&&... args) { | ||
return evaluate(instance, key, std::make_index_sequence<sizeof ...(Ts)>{}, std::forward<TVs>(args)...); | ||
} | ||
|
||
private: | ||
template<typename TKey, typename TClass, std::size_t...Is, typename... TVs> | ||
bool evaluate(TClass& instance, const TKey key, std::index_sequence<Is...>, TVs&&... args) { | ||
return (... || try_apply<Is>(instance, key, std::forward<TVs>(args)...)); | ||
} | ||
|
||
template<std::size_t I, typename TKey, typename TClass, typename... TVs> | ||
bool try_apply(TClass& Instance, const TKey key, TVs&&... args) { | ||
if constexpr (I + 1 < sizeof ...(Ts)) { | ||
// Even is a key, odd is a function | ||
if constexpr (I % 2 == 0) { | ||
// todo:: check if callable | ||
if (key == std::get<I>(expression)) { | ||
auto* function = std::get<I + 1>(expression); | ||
(Instance.*function)(std::forward<TVs>(Args)...); | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
std::tuple<Ts...> expression; | ||
}; | ||
|
||
template<typename... Ts> | ||
switch_expression_member(Ts...) -> switch_expression_member<Ts...>; | ||
|
||
|
||
template<typename... Ts> | ||
class switch_expression_lambda final { | ||
static_assert(sizeof ...(Ts) > 0); | ||
|
||
public: | ||
explicit switch_expression_lambda(const Ts&... args) | ||
: expression(args...) { | ||
|
||
} | ||
|
||
template<typename TKey, typename... TVs> | ||
bool apply(const TKey& key, TVs&&... vals) { | ||
return evaluate(key, std::make_index_sequence<sizeof ...(Ts)>{}, std::forward<TVs>(vals)...); | ||
} | ||
|
||
private: | ||
template<typename TKey, std::size_t...Is, typename... TVs> | ||
bool evaluate(const TKey& key, std::index_sequence<Is...>, TVs&&... vals) { | ||
return (... || try_apply<Is>(key, std::forward<TVs>(vals)...)); | ||
} | ||
|
||
template<std::size_t I, typename TKey, typename... TVs> | ||
bool try_apply(const TKey& key, TVs&&... vals) { | ||
if constexpr (I + 1 < sizeof ...(Ts)) { | ||
// Even is a key, odd is a function | ||
if constexpr (I % 2 == 0) { | ||
// todo:: check if callable | ||
if (key == std::get<I>(expression)) { | ||
auto&& function = std::get<I + 1>(expression); | ||
function(std::forward<TVs>(vals)...); | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
std::tuple<Ts...> expression; | ||
}; | ||
|
||
template<typename... Ts> | ||
switch_expression_lambda(Ts...) -> switch_expression_lambda<Ts...>; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* Copyright (C) 2020 - 2024 Gleb Bezborodov - All Rights Reserved | ||
* You may use, distribute and modify this code under the | ||
* terms of the MIT license. | ||
* | ||
* You should have received a copy of the MIT license with | ||
* this file. If not, please write to: bezborodoff.gleb@gmail.com, or visit : https://github.com/glensand/hope-core | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "hope_core/tuple/tuple_from_struct.h" | ||
#include "hope_core/tuple/tuple_from_struct_unsafe.h" | ||
#include "hope_core/tuple/tuple_policy.h" | ||
#include "hope_core/type_traits/user_defined_types.h" | ||
#include "hope_core/type_traits/detector.h" | ||
|
||
/*! \defgroup <reflection> Static reflection | ||
@{ | ||
\file | ||
\brief the file contains several functions for recursively calculating the number of fields within the structure. | ||
Only user-defined types are computed recursively, the classes of the standard library are considered a single whole | ||
*/ | ||
|
||
namespace hope { | ||
|
||
/** | ||
* Implementation of the compile - time fields count computer. Is intended to use with c++ aggregates | ||
* @tparam TStructure Structure structure the number of fields to be calculated | ||
* @return Number of fields | ||
*/ | ||
template<typename TStructure> | ||
constexpr std::size_t compute_field_count_recursive_constexpr() { | ||
if constexpr (is_user_defined_type_v<TStructure>) { | ||
constexpr auto fields_count = detect_fields_count<TStructure>(); | ||
constexpr auto types = detail::extract_types<TStructure>(std::make_index_sequence<fields_count>()); | ||
std::size_t count{0}; | ||
for_each(types, [&](auto field) { | ||
using type_t = typename decltype(field)::Type; | ||
count += compute_field_count_recursive_constexpr<type_t>(); | ||
}); | ||
return count; | ||
} else { | ||
return 1u; | ||
} | ||
} | ||
|
||
/** | ||
* Implementation of the run - time fields count computer; NOTE: each subfield will be instantiated, | ||
* be aware of usages of this function for heavy - weight objects. | ||
* @tparam TStructure Structure structure the number of fields to be calculated | ||
* @return Number of fields | ||
*/ | ||
template<typename TStructure> | ||
std::size_t compute_field_count_recursive() { | ||
if constexpr(is_user_defined_type_v<TStructure>) { | ||
const TStructure object{}; | ||
auto tuple = tuple_from_struct(object, field_policy::reference{}); | ||
std::size_t count{0}; | ||
for_each(tuple, [&](auto &&field) { | ||
using type_t = std::decay_t<decltype(field)>; | ||
count += compute_field_count_recursive<type_t>(); | ||
}); | ||
return count; | ||
} else { | ||
return 1u; | ||
} | ||
} | ||
|
||
} | ||
|
||
/*! @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* Copyright (C) 2020 - 2024 Gleb Bezborodov - All Rights Reserved | ||
* You may use, distribute and modify this code under the | ||
* terms of the MIT license. | ||
* | ||
* You should have received a copy of the MIT license with | ||
* this file. If not, please write to: bezborodoff.gleb@gmail.com, or visit : https://github.com/glensand/hope-core | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <utility> | ||
|
||
/*! \defgroup <reflection> Static reflection | ||
@{ | ||
\file | ||
\brief This file consists of helper functions which is used to compute fields count (in general) | ||
And the only one function which computes count of the structure's fields (non - recursive) | ||
*/ | ||
|
||
namespace hope { | ||
namespace detail { | ||
|
||
/** | ||
* The only one reason of existing of this class is initialization of object of different types. | ||
* This is the same as ubiq from magic-get | ||
* @tparam TStruct Type to be converted to | ||
* @tparam I Index, is used to unambiguously define the type | ||
*/ | ||
template <typename TStruct, std::size_t I> | ||
struct any_convertible { | ||
template <typename T, typename = std::enable_if_t<!std::is_base_of_v<T, TStruct>>> | ||
constexpr operator T& () const noexcept; | ||
}; | ||
|
||
/** | ||
* This two functions is needed to determine whether object of corresponding type might be constructed with | ||
* specified count of objects or not. NOTE: uses aggregate initialization, only aggregate initialisable | ||
* classes are allowed. | ||
* @tparam TStruct type of the structure to check | ||
* @tparam Is Sequence of indexes to initialize | ||
* @return true if the type is initialisable with sizeof(Is...) objects | ||
*/ | ||
template <typename TStruct, std::size_t... Is> | ||
constexpr auto is_constructable_n(std::index_sequence<Is...>) | ||
->decltype(TStruct{ any_convertible<TStruct, Is>{}... }, bool()) { | ||
return true; | ||
} | ||
template <typename TStruct, std::size_t... Is> | ||
constexpr auto is_constructable_n(...) { | ||
return false; | ||
} | ||
|
||
/** | ||
* Implementation of the fields computation function. | ||
* @tparam TStructure Desired type | ||
* @tparam Is Indexes of the sequence | ||
* @param sequence Helper sequence of the indexes which might be used to compute fields count | ||
* @return Count of structure's fields | ||
*/ | ||
template <typename TStructure, std::size_t... Is> | ||
constexpr std::size_t detect_fields_count_impl(std::index_sequence<Is...> sequence) { | ||
bool bs[] = { is_constructable_n<TStructure>(std::make_index_sequence<Is>())... }; | ||
// since cxx20... msvc sucks | ||
//return std::distance(std::begin(bs), std::find( | ||
// std::begin(bs), std::end(bs), false) | ||
//); | ||
|
||
for (std::size_t i{ 1 }; i < sequence.size(); ++i) { | ||
if (!bs[i]) return i - 1; | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
/** | ||
* Interface of computation function, is intended to catch all the errors and show error reason. | ||
* @tparam TStructure Desired type to compute fields. | ||
* @return Number of fields | ||
*/ | ||
template <typename TStructure> | ||
constexpr std::size_t detect_fields_count() { | ||
static_assert(!std::is_polymorphic_v<TStructure>, "---- hope ---- Polymorphic types are not allowed"); | ||
static_assert(std::is_aggregate_v<TStructure>, "---- hope ---- Only aggregate initializable types are allowed"); | ||
|
||
constexpr auto size = sizeof(TStructure); | ||
return detail::detect_fields_count_impl<TStructure>(std::make_index_sequence<size + 2>()); | ||
} | ||
} | ||
|
||
/*! @} */ |
Oops, something went wrong.