* Updated project structuremaster
| @@ -1,3 +1,3 @@ | |||||
| [submodule "cmake/modules"] | [submodule "cmake/modules"] | ||||
| path = cmake/modules | path = cmake/modules | ||||
| url = https://git.bergmann89.de/cpp/CmakeModules.git | |||||
| url = b3rgmann@git.bergmann89.de:cpp/CMakeModules.git | |||||
| @@ -1,63 +1,63 @@ | |||||
| # Initialize CMake ################################################################################ | # Initialize CMake ################################################################################ | ||||
| CMake_Minimum_Required ( VERSION 3.12.0 FATAL_ERROR ) | |||||
| CMake_Minimum_Required ( VERSION 3.12.0 FATAL_ERROR ) | |||||
| # Set CMAKE_BUILD_TYPE | # Set CMAKE_BUILD_TYPE | ||||
| If ( NOT CMAKE_BUILD_TYPE ) | |||||
| Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE ) | |||||
| EndIf ( NOT CMAKE_BUILD_TYPE ) | |||||
| Set_Property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel ) | |||||
| If ( NOT CMAKE_BUILD_TYPE ) | |||||
| Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE ) | |||||
| EndIf ( NOT CMAKE_BUILD_TYPE ) | |||||
| Set_Property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel ) | |||||
| # Set CMAKE_MODULE_PATH | # Set CMAKE_MODULE_PATH | ||||
| If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||||
| "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| EndIf ( ) | |||||
| If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||||
| "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ) | |||||
| EndIf ( ) | |||||
| If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||||
| "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| EndIf ( ) | |||||
| If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/cmake" ) | |||||
| Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||||
| "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/cmake" ) | |||||
| EndIf ( ) | |||||
| # Project ######################################################################################### | # Project ######################################################################################### | ||||
| Include ( GNUInstallDirs ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-options.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-const.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-var.cmake ) | |||||
| Project ( ${CPPRTTI_PROJECT_NAME} | |||||
| DESCRIPTION "${CPPRTTI_PROJECT_DESCRIPTION}" | |||||
| VERSION "${CPPRTTI_VERSION}" ) | |||||
| Include ( CTest ) | |||||
| Include ( GNUInstallDirs ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-options.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-const.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-var.cmake ) | |||||
| Project ( ${CPPRTTI_PROJECT_NAME} | |||||
| DESCRIPTION "${CPPRTTI_PROJECT_DESCRIPTION}" | |||||
| VERSION "${CPPRTTI_VERSION}" ) | |||||
| Include ( CTest ) | |||||
| # Subdirectories | # Subdirectories | ||||
| Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src ) | |||||
| Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test ) | |||||
| Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src ) | |||||
| Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test ) | |||||
| # Install | # Install | ||||
| If ( NOT CPPRTTI_HAS_EXPORT | |||||
| OR NOT CPPRTTI_INSTALL_PACKAGE ) | |||||
| Return ( ) | |||||
| EndIf ( ) | |||||
| Include ( CMakePackageConfigHelpers ) | |||||
| Write_Basic_Package_Version_File ( "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config-version.cmake" | |||||
| VERSION ${CPPRTTI_VERSION} | |||||
| COMPATIBILITY AnyNewerVersion ) | |||||
| Configure_File ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-config.cmake" | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config.cmake" | |||||
| @ONLY ) | |||||
| Set ( ConfigPackageLocation "${CPPRTTI_INSTALL_DIR_SHARE}/cmake" ) | |||||
| Install ( EXPORT | |||||
| cpprtti | |||||
| NAMESPACE | |||||
| cpprtti:: | |||||
| DESTINATION | |||||
| ${ConfigPackageLocation} ) | |||||
| Install ( FILES | |||||
| If ( NOT CPPRTTI_HAS_EXPORT | |||||
| OR NOT CPPRTTI_INSTALL_PACKAGE ) | |||||
| Return ( ) | |||||
| EndIf ( ) | |||||
| Include ( CMakePackageConfigHelpers ) | |||||
| Write_Basic_Package_Version_File ( "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config-version.cmake" | |||||
| VERSION ${CPPRTTI_VERSION} | |||||
| COMPATIBILITY AnyNewerVersion ) | |||||
| Configure_File ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpprtti-config.cmake" | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config.cmake" | "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config.cmake" | ||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config-version.cmake" | |||||
| DESTINATION | |||||
| ${ConfigPackageLocation} | |||||
| COMPONENT | |||||
| Devel ) | |||||
| @ONLY ) | |||||
| Set ( ConfigPackageLocation "${CPPRTTI_INSTALL_DIR_SHARE}/cmake" ) | |||||
| Install ( EXPORT | |||||
| cpprtti | |||||
| NAMESPACE | |||||
| cpprtti:: | |||||
| DESTINATION | |||||
| ${ConfigPackageLocation} ) | |||||
| Install ( FILES | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config.cmake" | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpprtti-config-version.cmake" | |||||
| DESTINATION | |||||
| ${ConfigPackageLocation} | |||||
| COMPONENT | |||||
| Devel ) | |||||
| @@ -0,0 +1,3 @@ | |||||
| # cpprtti | |||||
| C++ run time type information library. | |||||
| @@ -25,7 +25,7 @@ If ( NOT ${CHECKOUT_RET} EQUAL 0 ) | |||||
| EndIf ( ) | EndIf ( ) | ||||
| # Include Cloned Repository | # Include Cloned Repository | ||||
| Include ( ${CMAKE_CURRENT_LIST_DIR}/modules/find_local_module.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_LIST_DIR}/modules/cmake/find_local_module.cmake ) | |||||
| FindLocalModule ( cppcore ${CPPCORE_CHECKOUT_DIR} ) | FindLocalModule ( cppcore ${CPPCORE_CHECKOUT_DIR} ) | ||||
| # Create Alias Targets | # Create Alias Targets | ||||
| @@ -25,7 +25,7 @@ If ( NOT ${CHECKOUT_RET} EQUAL 0 ) | |||||
| EndIf ( ) | EndIf ( ) | ||||
| # Include Cloned Repository | # Include Cloned Repository | ||||
| Include ( ${CMAKE_CURRENT_LIST_DIR}/modules/find_local_module.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_LIST_DIR}/modules/cmake/find_local_module.cmake ) | |||||
| FindLocalModule ( cppmp ${CPPMP_CHECKOUT_DIR} ) | FindLocalModule ( cppmp ${CPPMP_CHECKOUT_DIR} ) | ||||
| # Create Alias Targets | # Create Alias Targets | ||||
| @@ -1,28 +1,28 @@ | |||||
| # This file contains constant variables that are fixed to this project | # This file contains constant variables that are fixed to this project | ||||
| # Version | # Version | ||||
| Set ( CPPRTTI_VERSION_MAJOR 1 ) | |||||
| Set ( CPPRTTI_VERSION_MINOR 0 ) | |||||
| Set ( CPPRTTI_VERSION_PATCH 0 ) | |||||
| Set ( CPPRTTI_VERSION_BUILD 0 ) | |||||
| Set ( CPPRTTI_VERSION_HASH "" ) | |||||
| Set ( CPPRTTI_VERSION_BEHIND 0 ) | |||||
| Set ( CPPRTTI_VERSION_DIRTY 0 ) | |||||
| Set ( CPPRTTI_VERSION_MAJOR 1 ) | |||||
| Set ( CPPRTTI_VERSION_MINOR 0 ) | |||||
| Set ( CPPRTTI_VERSION_PATCH 0 ) | |||||
| Set ( CPPRTTI_VERSION_BUILD 0 ) | |||||
| Set ( CPPRTTI_VERSION_HASH "" ) | |||||
| Set ( CPPRTTI_VERSION_BEHIND 0 ) | |||||
| Set ( CPPRTTI_VERSION_DIRTY 0 ) | |||||
| # Names | # Names | ||||
| Set ( CPPRTTI_PROJECT_NAME "cpprtti" ) | |||||
| Set ( CPPRTTI_PROJECT_DESCRIPTION "A simple hello world library" ) | |||||
| Set ( CPPRTTI_PROJECT_NAME "cpprtti" ) | |||||
| Set ( CPPRTTI_PROJECT_DESCRIPTION "C++ run time type information library" ) | |||||
| # Include generated variables for further usage | # Include generated variables for further usage | ||||
| Include ( ${CMAKE_CURRENT_LIST_DIR}/cpprtti-var.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_LIST_DIR}/cpprtti-var.cmake ) | |||||
| # Install directories | # Install directories | ||||
| Set ( CPPRTTI_INSTALL_DIR_INCLUDE "${CMAKE_INSTALL_INCLUDEDIR}/${CPPRTTI_NAME}" ) | |||||
| Set ( CPPRTTI_INSTALL_DIR_LIB "${CMAKE_INSTALL_LIBDIR}" ) | |||||
| Set ( CPPRTTI_INSTALL_DIR_SHARE "${CMAKE_INSTALL_DATAROOTDIR}/${CPPRTTI_NAME}" ) | |||||
| Set ( CPPRTTI_INSTALL_DIR_INCLUDE "${CMAKE_INSTALL_INCLUDEDIR}/${CPPRTTI_NAME}" ) | |||||
| Set ( CPPRTTI_INSTALL_DIR_LIB "${CMAKE_INSTALL_LIBDIR}" ) | |||||
| Set ( CPPRTTI_INSTALL_DIR_SHARE "${CMAKE_INSTALL_DATAROOTDIR}/${CPPRTTI_NAME}" ) | |||||
| # C Standard | # C Standard | ||||
| Set ( CMAKE_C_STANDARD 11 ) | |||||
| Set ( CMAKE_CXX_STANDARD 17 ) | |||||
| Set ( CMAKE_C_STANDARD_REQUIRED ON ) | |||||
| Set ( CMAKE_CXX_STANDARD_REQUIRED ON ) | |||||
| Set ( CMAKE_C_STANDARD 11 ) | |||||
| Set ( CMAKE_CXX_STANDARD 17 ) | |||||
| Set ( CMAKE_C_STANDARD_REQUIRED ON ) | |||||
| Set ( CMAKE_CXX_STANDARD_REQUIRED ON ) | |||||
| @@ -1,23 +1,11 @@ | |||||
| # This file contains options that can be passed to the cmake command | # This file contains options that can be passed to the cmake command | ||||
| Option ( CPPRTTI_INSTALL_HEADER | |||||
| "Install headers of cpprtti." | |||||
| ON ) | |||||
| Option ( CPPRTTI_INSTALL_STATIC | |||||
| "Install static library of cpprtti." | |||||
| ON ) | |||||
| Option ( CPPRTTI_INSTALL_SHARED | |||||
| "Install shared library of cpprtti." | |||||
| ON ) | |||||
| Option ( CPPRTTI_INSTALL_DEBUG | |||||
| "Install the stripped debug informations of cpprtti." | |||||
| OFF ) | |||||
| Option ( CPPRTTI_INSTALL_PACKAGE | |||||
| "Install the cmake package of cpprtti." | |||||
| ON ) | |||||
| Option ( CPPRTTI_NO_STRIP | |||||
| "Do not strip debug symbols from binary." | |||||
| OFF ) | |||||
| Option ( CPPRTTI_USE_GIT_VERSION | |||||
| "Read the git tags to get the version of cpprtti" | |||||
| ON ) | |||||
| Option ( CPPRTTI_INSTALL_HEADER | |||||
| "Install headers of cpprtti." | |||||
| ON ) | |||||
| Option ( CPPRTTI_INSTALL_PACKAGE | |||||
| "Install the cmake package of cpprtti." | |||||
| ON ) | |||||
| Option ( CPPRTTI_USE_GIT_VERSION | |||||
| "Read the git tags to get the version of cpprtti" | |||||
| ON ) | |||||
| @@ -1,26 +1,32 @@ | |||||
| # This file contains generated variables that are needed for the project | # This file contains generated variables that are needed for the project | ||||
| # Git Version | # Git Version | ||||
| If ( CPPRTTI_USE_GIT_VERSION ) | |||||
| Include ( git_helper OPTIONAL RESULT_VARIABLE HAS_GIT_HELPER ) | |||||
| If ( HAS_GIT_HELPER ) | |||||
| GitGetVersion ( ${CMAKE_CURRENT_LIST_DIR}/.. | |||||
| CPPRTTI_VERSION_MAJOR | |||||
| CPPRTTI_VERSION_MINOR | |||||
| CPPRTTI_VERSION_PATCH | |||||
| CPPRTTI_VERSION_BUILD | |||||
| CPPRTTI_VERSION_HASH | |||||
| CPPRTTI_VERSION_BEHIND | |||||
| CPPRTTI_VERSION_DIRTY ) | |||||
| EndIf ( ) | |||||
| EndIf ( ) | |||||
| If ( CPPRTTI_USE_GIT_VERSION ) | |||||
| Include ( git_helper OPTIONAL RESULT_VARIABLE HAS_GIT_HELPER ) | |||||
| If ( HAS_GIT_HELPER ) | |||||
| GitGetVersion ( ${CMAKE_CURRENT_LIST_DIR}/.. | |||||
| CPPRTTI_VERSION_MAJOR | |||||
| CPPRTTI_VERSION_MINOR | |||||
| CPPRTTI_VERSION_PATCH | |||||
| CPPRTTI_VERSION_BUILD | |||||
| CPPRTTI_VERSION_HASH | |||||
| CPPRTTI_VERSION_BEHIND | |||||
| CPPRTTI_VERSION_DIRTY ) | |||||
| EndIf ( ) | |||||
| EndIf ( ) | |||||
| # Strings | # Strings | ||||
| Set ( CPPRTTI_VERSION_SHORT "${CPPRTTI_VERSION_MAJOR}.${CPPRTTI_VERSION_MINOR}" ) | |||||
| Set ( CPPRTTI_VERSION "${CPPRTTI_VERSION_SHORT}.${CPPRTTI_VERSION_PATCH}.${CPPRTTI_VERSION_BUILD}" ) | |||||
| Set ( CPPRTTI_VERSION_COMPLETE "${CPPRTTI_VERSION}" ) | |||||
| Set ( CPPRTTI_NAME "${CPPRTTI_PROJECT_NAME}-${CPPRTTI_VERSION_SHORT}" ) | |||||
| Set ( CPPRTTI_OUTPUTNAME "${CPPRTTI_PROJECT_NAME}" ) | |||||
| If ( CPPRTTI_VERSION_BEHIND ) | |||||
| Set ( CPPRTTI_VERSION_COMPLETE "${CPPRTTI_VERSION_COMPLETE}+${CPPRTTI_VERSION_BEHIND}" ) | |||||
| EndIf ( ) | |||||
| Set ( CPPRTTI_VERSION_SHORT | |||||
| "${CPPRTTI_VERSION_MAJOR}.${CPPRTTI_VERSION_MINOR}" ) | |||||
| Set ( CPPRTTI_VERSION | |||||
| "${CPPRTTI_VERSION_SHORT}.${CPPRTTI_VERSION_PATCH}.${CPPRTTI_VERSION_BUILD}" ) | |||||
| Set ( CPPRTTI_VERSION_COMPLETE | |||||
| "${CPPRTTI_VERSION}" ) | |||||
| Set ( CPPRTTI_NAME | |||||
| "${CPPRTTI_PROJECT_NAME}-${CPPRTTI_VERSION_SHORT}" ) | |||||
| Set ( CPPRTTI_OUTPUTNAME | |||||
| "${CPPRTTI_PROJECT_NAME}" ) | |||||
| If ( CPPRTTI_VERSION_BEHIND ) | |||||
| Set ( CPPRTTI_VERSION_COMPLETE | |||||
| "${CPPRTTI_VERSION_COMPLETE}+${CPPRTTI_VERSION_BEHIND}" ) | |||||
| EndIf ( ) | |||||
| @@ -1 +1 @@ | |||||
| Subproject commit ebbae4fbb42d671331b4c6e9d1d142f41dcacc1b | |||||
| Subproject commit 94b9877d65e46c9d8169ebc46f163d02e4d9dcf3 | |||||
| @@ -4,3 +4,5 @@ | |||||
| #include <cpprtti/registry.h> | #include <cpprtti/registry.h> | ||||
| #include <cpprtti/traits.h> | #include <cpprtti/traits.h> | ||||
| #include <cpprtti/types.h> | #include <cpprtti/types.h> | ||||
| #include <cpprtti/registry.inl> | |||||
| @@ -2,8 +2,10 @@ | |||||
| #include "misc/exception.h" | #include "misc/exception.h" | ||||
| #include "misc/helper.h" | #include "misc/helper.h" | ||||
| #include "misc/storage.h" | |||||
| #include "misc/variant.h" | #include "misc/variant.h" | ||||
| #include "misc/exception.inl" | #include "misc/exception.inl" | ||||
| #include "misc/helper.inl" | #include "misc/helper.inl" | ||||
| #include "misc/storage.inl" | |||||
| #include "misc/variant.inl" | #include "misc/variant.inl" | ||||
| @@ -23,11 +23,15 @@ namespace cpprtti | |||||
| /* variant */ | /* variant */ | ||||
| variant_error = 2000, | variant_error = 2000, | ||||
| variant_is_empty, //!< The variant does not store any value! | variant_is_empty, //!< The variant does not store any value! | ||||
| variant_is_const, //!< The value stored in the variant is const! | |||||
| variant_type_mismatch, //!< The variant does not store the requested type! | variant_type_mismatch, //!< The variant does not store the requested type! | ||||
| variant_invalid_cast, //!< The value stored in the variant could not be cast to the requested type! | variant_invalid_cast, //!< The value stored in the variant could not be cast to the requested type! | ||||
| variant_convert_to, //!< No known conversion for the passed types. | |||||
| variant_assign, //!< Variant is not copy assignable. | |||||
| /* class */ | /* class */ | ||||
| class_error = 3000, | class_error = 3000, | ||||
| class_member_does_not_exist, //!< The requested member does not exist. | |||||
| class_member_already_exists, //!< Unable to create member: Name is already in use! | class_member_already_exists, //!< Unable to create member: Name is already in use! | ||||
| class_type_mismatch, //!< Type does not match the. | class_type_mismatch, //!< Type does not match the. | ||||
| class_member_not_readable, //!< Member variable is not readable! | class_member_not_readable, //!< Member variable is not readable! | ||||
| @@ -72,5 +76,3 @@ namespace cpprtti | |||||
| }; | }; | ||||
| } | } | ||||
| #include "exception.inl" | |||||
| @@ -7,6 +7,13 @@ namespace cpprtti | |||||
| { | { | ||||
| using type_id = size_t; | using type_id = size_t; | ||||
| using storage_id = size_t; | |||||
| /** | |||||
| * @brief Get the ID of a certain C++ storage class. | |||||
| */ | |||||
| template<typename X> | |||||
| inline storage_id get_storage_id(); | |||||
| /** | /** | ||||
| * @brief Get the ID of a certain C++ type. | * @brief Get the ID of a certain C++ type. | ||||
| @@ -21,5 +28,3 @@ namespace cpprtti | |||||
| inline const std::string& get_type_name(); | inline const std::string& get_type_name(); | ||||
| } | } | ||||
| #include "helper.inl" | |||||
| @@ -10,7 +10,11 @@ namespace cpprtti | |||||
| namespace __impl | namespace __impl | ||||
| { | { | ||||
| inline type_id create_type_id() | |||||
| struct tag_type_id { }; | |||||
| struct tag_storage_id { }; | |||||
| template<typename...> | |||||
| inline type_id create_id() | |||||
| { | { | ||||
| static type_id value { }; | static type_id value { }; | ||||
| return ++value; | return ++value; | ||||
| @@ -26,10 +30,19 @@ namespace cpprtti | |||||
| } | } | ||||
| template<typename X> | |||||
| storage_id get_storage_id() | |||||
| { | |||||
| using namespace __impl; | |||||
| static const auto value = create_id<tag_storage_id>(); | |||||
| return value; | |||||
| } | |||||
| template<typename X> | template<typename X> | ||||
| type_id get_type_id() | type_id get_type_id() | ||||
| { | { | ||||
| static const auto value = __impl::create_type_id(); | |||||
| using namespace __impl; | |||||
| static const auto value = create_id<tag_type_id>(); | |||||
| return value; | return value; | ||||
| } | } | ||||
| @@ -0,0 +1,46 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <vector> | |||||
| #include "helper.h" | |||||
| namespace cpprtti | |||||
| { | |||||
| struct storage_container | |||||
| { | |||||
| private: | |||||
| using item_ptr_s = std::shared_ptr<void>; | |||||
| using item_vector = std::vector<item_ptr_s>; | |||||
| private: | |||||
| item_vector _items; | |||||
| public: | |||||
| /** | |||||
| * @brief Get the requested storage or nullptr if the storage does not exist. | |||||
| */ | |||||
| template<typename T> | |||||
| T* storage(); | |||||
| /** | |||||
| * @brief Get the requested storage or nullptr if the storage does not exist. | |||||
| */ | |||||
| template<typename T> | |||||
| T* storage(bool can_create); | |||||
| /** | |||||
| * @brief Create a new storage. | |||||
| */ | |||||
| template<typename T> | |||||
| T* storage(const std::shared_ptr<T>& item); | |||||
| /** | |||||
| * @brief Get the requested storage or nullptr if the storage does not exist. | |||||
| */ | |||||
| template<typename T> | |||||
| const T* storage() const; | |||||
| }; | |||||
| } | |||||
| @@ -0,0 +1,61 @@ | |||||
| #pragma once | |||||
| #include <cppmp/core/modifier.h> | |||||
| #include "storage.h" | |||||
| namespace cpprtti | |||||
| { | |||||
| /* storage_container */ | |||||
| template<typename T> | |||||
| T* storage_container::storage() | |||||
| { | |||||
| using storage_type = cppmp::decay_t<T>; | |||||
| auto id = get_storage_id<storage_type>(); | |||||
| return (id < _items.size()) | |||||
| ? static_cast<storage_type*>(_items[id].get()) | |||||
| : nullptr; | |||||
| } | |||||
| template<typename T> | |||||
| T* storage_container::storage(bool can_create) | |||||
| { | |||||
| using storage_type = cppmp::decay_t<T>; | |||||
| auto id = get_storage_id<storage_type>(); | |||||
| if ( can_create | |||||
| && ( id >= _items.size() | |||||
| || !_items[id])) | |||||
| { | |||||
| _items.resize(id + 1); | |||||
| _items[id] = std::make_shared<storage_type>(); | |||||
| } | |||||
| return (id < _items.size()) | |||||
| ? static_cast<storage_type*>(_items[id].get()) | |||||
| : nullptr; | |||||
| } | |||||
| template<typename T> | |||||
| T* storage_container::storage(const std::shared_ptr<T>& item) | |||||
| { | |||||
| using storage_type = cppmp::decay_t<T>; | |||||
| auto id = get_storage_id<storage_type>(); | |||||
| _items.resize(id + 1); | |||||
| _items[id] = item; | |||||
| return (id < _items.size()) | |||||
| ? static_cast<storage_type*>(_items[id].get()) | |||||
| : nullptr; | |||||
| } | |||||
| template<typename T> | |||||
| const T* storage_container::storage() const | |||||
| { | |||||
| using storage_type = cppmp::decay_t<T>; | |||||
| auto id = get_storage_id<storage_type>(); | |||||
| return (id < _items.size()) | |||||
| ? static_cast<storage_type*>(_items[id].get()) | |||||
| : nullptr; | |||||
| } | |||||
| } | |||||
| @@ -5,11 +5,13 @@ | |||||
| #include <cppmp/misc/generic_predicate.h> | #include <cppmp/misc/generic_predicate.h> | ||||
| #include "helper.h" | #include "helper.h" | ||||
| #include "../types/type.h" | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| struct type; | |||||
| struct variant; | |||||
| namespace __impl | namespace __impl | ||||
| { | { | ||||
| @@ -22,18 +24,36 @@ namespace cpprtti | |||||
| struct variant_impl | struct variant_impl | ||||
| { | { | ||||
| public: | |||||
| const type& type; | const type& type; | ||||
| void * data { nullptr }; | void * data { nullptr }; | ||||
| bool is_const { false }; | bool is_const { false }; | ||||
| bool is_reference { false }; | bool is_reference { false }; | ||||
| public: | |||||
| /** | /** | ||||
| * @brief Constructor. | * @brief Constructor. | ||||
| */ | */ | ||||
| inline variant_impl(const cpprtti::type& p_type); | inline variant_impl(const cpprtti::type& p_type); | ||||
| /** | |||||
| * @brief Destructor. | |||||
| */ | |||||
| virtual ~variant_impl() = default; | |||||
| /** | |||||
| * @brief Assign a new value. | |||||
| */ | |||||
| inline void assign(const variant& v); | |||||
| private: | |||||
| /** | |||||
| * @brief Actual implementation of the assign method. | |||||
| */ | |||||
| virtual void assign_impl(const variant& v) = 0; | |||||
| }; | }; | ||||
| using variant_impl_ptr_s = std::shared_ptr<const variant_impl>; | |||||
| using variant_impl_ptr_s = std::shared_ptr<variant_impl>; | |||||
| } | } | ||||
| @@ -81,7 +101,23 @@ namespace cpprtti | |||||
| /** | /** | ||||
| * @brief Check if the variant contains a value. | * @brief Check if the variant contains a value. | ||||
| */ | */ | ||||
| inline bool empty(); | |||||
| inline bool empty() const; | |||||
| /** | |||||
| * @brief Convert this variant to another type. | |||||
| */ | |||||
| template<typename T_to> | |||||
| inline variant to() const; | |||||
| /** | |||||
| * @brief Convert this variant to another type. | |||||
| */ | |||||
| inline variant to(const cpprtti::type& t) const; | |||||
| /** | |||||
| * @brief Assign the value of this variant from another variant. | |||||
| */ | |||||
| inline void assign(const variant& v); | |||||
| /** | /** | ||||
| * @brief Check if the variant contains a value. | * @brief Check if the variant contains a value. | ||||
| @@ -98,5 +134,3 @@ namespace cpprtti | |||||
| constexpr decltype(auto) make_variant = cppmp::generic_predicate<__impl::variant_builder> { }; | constexpr decltype(auto) make_variant = cppmp::generic_predicate<__impl::variant_builder> { }; | ||||
| } | } | ||||
| #include "variant.inl" | |||||
| @@ -2,6 +2,7 @@ | |||||
| #include <cppcore/misc/string_builder.h> | #include <cppcore/misc/string_builder.h> | ||||
| #include <cppmp/core/types.h> | |||||
| #include <cppmp/core/checker.h> | #include <cppmp/core/checker.h> | ||||
| #include <cppmp/core/modifier.h> | #include <cppmp/core/modifier.h> | ||||
| #include <cppmp/core/conditionals.h> | #include <cppmp/core/conditionals.h> | ||||
| @@ -24,6 +25,44 @@ namespace cpprtti | |||||
| : type(p_type) | : type(p_type) | ||||
| { } | { } | ||||
| void variant_impl::assign(const variant& v) | |||||
| { | |||||
| if (is_const) | |||||
| { | |||||
| throw exception( | |||||
| error_code::variant_is_const, | |||||
| "The value stored in the variant is const!"); | |||||
| } | |||||
| if (v.empty()) | |||||
| { | |||||
| throw exception( | |||||
| error_code::variant_is_empty, | |||||
| "The passed variant does not store any value!"); | |||||
| } | |||||
| if (type.id() != v.type().id()) | |||||
| { | |||||
| auto converter = v.type().convert_to(type.id()); | |||||
| if (!converter) | |||||
| { | |||||
| throw exception( | |||||
| error_code::variant_convert_to, | |||||
| cppcore::string_builder() | |||||
| << "No known conversion from type '" | |||||
| << v.type().name() | |||||
| << "' to type '" | |||||
| << type.name() | |||||
| << "'!"); | |||||
| } | |||||
| this->assign_impl((*converter)(v)); | |||||
| } | |||||
| else | |||||
| { | |||||
| this->assign_impl(v); | |||||
| } | |||||
| } | |||||
| /* variant_builder - default */ | /* variant_builder - default */ | ||||
| template<typename X, typename> | template<typename X, typename> | ||||
| @@ -61,6 +100,11 @@ namespace cpprtti | |||||
| is_const = cppmp::is_const_v<cppmp::remove_reference_t<T>>; | is_const = cppmp::is_const_v<cppmp::remove_reference_t<T>>; | ||||
| is_reference = false; | is_reference = false; | ||||
| } | } | ||||
| void assign_impl(const variant& v) override | |||||
| { | |||||
| *static_cast<cppmp::decay_t<T>*>(data) = v.get<const T&>(); | |||||
| }; | |||||
| }; | }; | ||||
| template<typename X_registry, typename X> | template<typename X_registry, typename X> | ||||
| @@ -94,6 +138,30 @@ namespace cpprtti | |||||
| is_const = cppmp::is_const_v<cppmp::remove_reference_t<T>>; | is_const = cppmp::is_const_v<cppmp::remove_reference_t<T>>; | ||||
| is_reference = true; | is_reference = true; | ||||
| } | } | ||||
| void assign_impl(const variant& v) override | |||||
| { | |||||
| }; | |||||
| template<typename X = cppmp::decay_t<T>> | |||||
| cppmp::enable_if_t<cppmp::is_copy_assignable_v<X>> | |||||
| assign_helper(const variant& v) | |||||
| { | |||||
| *static_cast<cppmp::decay_t<T>*>(data) = v.get<const T&>(); | |||||
| } | |||||
| template<typename X = cppmp::decay_t<T>> | |||||
| cppmp::enable_if_t<!cppmp::is_copy_assignable_v<X>> | |||||
| assign_helper(const variant& v) | |||||
| { | |||||
| throw exception( | |||||
| error_code::variant_assign, | |||||
| cppcore::string_builder() | |||||
| << "Value of type '" | |||||
| << type.name() | |||||
| << "' is not copy assignable!"); | |||||
| } | |||||
| }; | }; | ||||
| template<typename X_registry, typename X> | template<typename X_registry, typename X> | ||||
| @@ -121,6 +189,19 @@ namespace cpprtti | |||||
| { return std::forward<X>(x); } | { return std::forward<X>(x); } | ||||
| }; | }; | ||||
| /* variant_builder - type, variant (convert_from) */ | |||||
| template<typename T_registry, typename... T_args> | |||||
| struct variant_builder< | |||||
| cppmp::list<T_registry, const type&, T_args...>, | |||||
| void | |||||
| > | |||||
| { | |||||
| template<typename X_registry, typename... X_args> | |||||
| static constexpr decltype(auto) apply(X_registry& p_registry, const type& t, X_args&&... args) | |||||
| { return make_variant(std::forward<X_args>(args)...).to(t.id()); } | |||||
| }; | |||||
| /* value_extractor - default */ | /* value_extractor - default */ | ||||
| template<typename X, typename = void> | template<typename X, typename = void> | ||||
| @@ -234,12 +315,50 @@ namespace cpprtti | |||||
| << ")"); | << ")"); | ||||
| } | } | ||||
| return __impl::extract_value(*_impl, cppmp::type_v<T>); | |||||
| auto& impl = static_cast<const __impl::variant_impl&>(*_impl); | |||||
| return __impl::extract_value(impl, cppmp::type_v<T>); | |||||
| } | } | ||||
| bool variant::empty() | |||||
| bool variant::empty() const | |||||
| { return !static_cast<bool>(_impl); } | { return !static_cast<bool>(_impl); } | ||||
| template<typename T_to> | |||||
| variant variant::to() const | |||||
| { | |||||
| using to_type = cppmp::decay_t<T_to>; | |||||
| return to(get_type_id<to_type>()); | |||||
| } | |||||
| variant variant::to(const cpprtti::type& t) const | |||||
| { | |||||
| check_impl(); | |||||
| auto& type = _impl->type; | |||||
| if (t.id() == type.id()) | |||||
| return *this; | |||||
| auto* converter = type.convert_to(t.id()); | |||||
| if (!converter) | |||||
| { | |||||
| throw exception( | |||||
| error_code::variant_is_empty, | |||||
| cppcore::string_builder() | |||||
| << "No known conversion from type '" | |||||
| << type.name() | |||||
| << "' to type '" | |||||
| << t.name() | |||||
| << "'!"); | |||||
| } | |||||
| return (*converter)(*this); | |||||
| } | |||||
| inline void variant::assign(const variant& v) | |||||
| { | |||||
| check_impl(); | |||||
| _impl->assign(v); | |||||
| } | |||||
| variant::operator bool() const | variant::operator bool() const | ||||
| { return static_cast<bool>(_impl); } | { return static_cast<bool>(_impl); } | ||||
| @@ -4,6 +4,7 @@ | |||||
| #include <memory> | #include <memory> | ||||
| #include "types/type.h" | #include "types/type.h" | ||||
| #include "types/type_decorator.h" | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| @@ -88,9 +89,7 @@ namespace cpprtti | |||||
| * @brief Create a new type for the passed C++ type with the passed implementation type. | * @brief Create a new type for the passed C++ type with the passed implementation type. | ||||
| */ | */ | ||||
| template<typename T_impl> | template<typename T_impl> | ||||
| inline T_impl& create(); | |||||
| inline type_decorator<T_impl>& create(); | |||||
| }; | }; | ||||
| } | } | ||||
| #include "registry.inl" | |||||
| @@ -18,7 +18,8 @@ namespace cpprtti | |||||
| template<typename T_type> | template<typename T_type> | ||||
| const auto& registry::get() const | const auto& registry::get() const | ||||
| { | { | ||||
| using impl_type = default_type_t<T_type>; | |||||
| using impl_type = default_type_t<T_type>; | |||||
| using decorated_type = type_decorator<impl_type>; | |||||
| auto * t = find<T_type>(); | auto * t = find<T_type>(); | ||||
| @@ -31,7 +32,7 @@ namespace cpprtti | |||||
| << get_type_name<T_type>()); | << get_type_name<T_type>()); | ||||
| } | } | ||||
| auto * ret = dynamic_cast<const impl_type *>(t); | |||||
| auto * ret = dynamic_cast<const decorated_type *>(t); | |||||
| if (!ret) | if (!ret) | ||||
| { | { | ||||
| throw exception( | throw exception( | ||||
| @@ -47,11 +48,14 @@ namespace cpprtti | |||||
| template<typename T_type, typename T_impl> | template<typename T_type, typename T_impl> | ||||
| auto& registry::get() | auto& registry::get() | ||||
| { | { | ||||
| using impl_type = T_impl; | |||||
| using decorated_type = type_decorator<impl_type>; | |||||
| auto * t = find<T_type>(); | auto * t = find<T_type>(); | ||||
| if (!t) | if (!t) | ||||
| t = &create<T_impl>(); | |||||
| t = &create<impl_type>(); | |||||
| auto * ret = dynamic_cast<T_impl *>(t); | |||||
| auto * ret = dynamic_cast<decorated_type *>(t); | |||||
| if (!ret) | if (!ret) | ||||
| { | { | ||||
| throw exception( | throw exception( | ||||
| @@ -105,9 +109,11 @@ namespace cpprtti | |||||
| } | } | ||||
| template<typename T_impl> | template<typename T_impl> | ||||
| T_impl& registry::create() | |||||
| type_decorator<T_impl>& registry::create() | |||||
| { | { | ||||
| auto impl = std::make_shared<T_impl>(*this); | |||||
| using decorated_type = type_decorator<T_impl>; | |||||
| auto impl = std::make_shared<decorated_type>(*this); | |||||
| auto id_it = _id_map.find(impl->id()); | auto id_it = _id_map.find(impl->id()); | ||||
| if (id_it != _id_map.end()) | if (id_it != _id_map.end()) | ||||
| @@ -10,5 +10,3 @@ namespace cpprtti | |||||
| using default_type_t = typename default_type_trait<cppmp::decay_t<T>>::type; | using default_type_t = typename default_type_trait<cppmp::decay_t<T>>::type; | ||||
| } | } | ||||
| #include "default_type.inl" | |||||
| @@ -5,10 +5,12 @@ | |||||
| #include "types/fundamental_type_tpl.h" | #include "types/fundamental_type_tpl.h" | ||||
| #include "types/fundamental_type.h" | #include "types/fundamental_type.h" | ||||
| #include "types/member.h" | #include "types/member.h" | ||||
| #include "types/type_decorator.h" | |||||
| #include "types/type.h" | #include "types/type.h" | ||||
| #include "types/class_type_tpl.inl" | #include "types/class_type_tpl.inl" | ||||
| #include "types/class_type.inl" | #include "types/class_type.inl" | ||||
| #include "types/fundamental_type_tpl.inl" | #include "types/fundamental_type_tpl.inl" | ||||
| #include "types/fundamental_type.inl" | #include "types/fundamental_type.inl" | ||||
| #include "types/type_decorator.inl" | |||||
| #include "types/type.inl" | #include "types/type.inl" | ||||
| @@ -31,13 +31,18 @@ namespace cpprtti | |||||
| /** | /** | ||||
| * @brief Get a map of all registered members. | * @brief Get a map of all registered members. | ||||
| */ | */ | ||||
| const member_map& members() const; | |||||
| inline const member& member(const std::string& p_name) const; | |||||
| /** | |||||
| * @brief Get a map of all registered members. | |||||
| */ | |||||
| inline const member_map& members() const; | |||||
| /** | /** | ||||
| * @brief Register a new member variable. | * @brief Register a new member variable. | ||||
| */ | */ | ||||
| template<typename... T_args> | template<typename... T_args> | ||||
| auto& add_member_variable( | |||||
| inline auto& add_member_variable( | |||||
| const std::string& p_name, | const std::string& p_name, | ||||
| T_args&&... p_args); | T_args&&... p_args); | ||||
| @@ -45,11 +50,9 @@ namespace cpprtti | |||||
| * @brief Register a new member method. | * @brief Register a new member method. | ||||
| */ | */ | ||||
| template<typename... T_args> | template<typename... T_args> | ||||
| auto& add_member_method( | |||||
| inline auto& add_member_method( | |||||
| const std::string& p_name, | const std::string& p_name, | ||||
| T_args&&... p_args); | T_args&&... p_args); | ||||
| }; | }; | ||||
| } | } | ||||
| #include "class_type.inl" | |||||
| @@ -16,6 +16,22 @@ namespace cpprtti | |||||
| : type(p_registry, p_id, p_name, rtti_type_t::class_type) | : type(p_registry, p_id, p_name, rtti_type_t::class_type) | ||||
| { } | { } | ||||
| const member& class_type::member( | |||||
| const std::string& p_name) const | |||||
| { | |||||
| auto it = _members.find(p_name); | |||||
| if (it == _members.end()) | |||||
| { | |||||
| throw exception( | |||||
| error_code::class_member_does_not_exist, | |||||
| cppcore::string_builder() | |||||
| << "Member with the name '" | |||||
| << p_name | |||||
| << "' does not exists"); | |||||
| } | |||||
| return *it->second; | |||||
| } | |||||
| const class_type::member_map& class_type | const class_type::member_map& class_type | ||||
| ::members() const | ::members() const | ||||
| { return _members; } | { return _members; } | ||||
| @@ -21,5 +21,3 @@ namespace cpprtti | |||||
| }; | }; | ||||
| } | } | ||||
| #include "class_type_tpl.inl" | |||||
| @@ -19,5 +19,3 @@ namespace cpprtti | |||||
| }; | }; | ||||
| } | } | ||||
| #include "fundamental_type.inl" | |||||
| @@ -21,5 +21,3 @@ namespace cpprtti | |||||
| }; | }; | ||||
| } | } | ||||
| #include "fundamental_type_tpl.inl" | |||||
| @@ -3,6 +3,7 @@ | |||||
| #include <string> | #include <string> | ||||
| #include "../../types/type.h" | #include "../../types/type.h" | ||||
| #include "../../misc/storage.h" | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| @@ -15,6 +16,7 @@ namespace cpprtti | |||||
| }; | }; | ||||
| struct member | struct member | ||||
| : public storage_container | |||||
| { | { | ||||
| protected: | protected: | ||||
| cpprtti::type& _owner; | cpprtti::type& _owner; | ||||
| @@ -52,5 +54,3 @@ namespace cpprtti | |||||
| }; | }; | ||||
| } | } | ||||
| #include "member.inl" | |||||
| @@ -3,6 +3,7 @@ | |||||
| #include <cppmp/misc/generic_predicate.h> | #include <cppmp/misc/generic_predicate.h> | ||||
| #include "member.h" | #include "member.h" | ||||
| #include "../../misc/variant.h" | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| @@ -42,5 +43,3 @@ namespace cpprtti | |||||
| constexpr decltype(auto) make_member_method = cppmp::generic_predicate<__impl::member_method_builder> { }; | constexpr decltype(auto) make_member_method = cppmp::generic_predicate<__impl::member_method_builder> { }; | ||||
| } | } | ||||
| #include "member_method.inl" | |||||
| @@ -3,6 +3,7 @@ | |||||
| #include <cppmp/traits/lambda_traits.h> | #include <cppmp/traits/lambda_traits.h> | ||||
| #include "member_method.h" | #include "member_method.h" | ||||
| #include "../../misc/variant.h" | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| @@ -36,17 +36,17 @@ namespace cpprtti | |||||
| /** | /** | ||||
| * @brief RTTI type of that member represents. | * @brief RTTI type of that member represents. | ||||
| */ | */ | ||||
| const cpprtti::type& type() const; | |||||
| inline const cpprtti::type& type() const; | |||||
| /** | /** | ||||
| * @brief Check if the variable is readable. | * @brief Check if the variable is readable. | ||||
| */ | */ | ||||
| bool is_readale() const; | |||||
| inline bool is_readale() const; | |||||
| /** | /** | ||||
| * @brief Check if the variable is writable. | * @brief Check if the variable is writable. | ||||
| */ | */ | ||||
| bool is_writable() const; | |||||
| inline bool is_writable() const; | |||||
| /** | /** | ||||
| * @brief Get the current value of the member. | * @brief Get the current value of the member. | ||||
| @@ -75,5 +75,3 @@ namespace cpprtti | |||||
| constexpr decltype(auto) make_member_variable = cppmp::generic_predicate<__impl::member_variable_builder> { }; | constexpr decltype(auto) make_member_variable = cppmp::generic_predicate<__impl::member_variable_builder> { }; | ||||
| } | } | ||||
| #include "member_variable.inl" | |||||
| @@ -86,7 +86,8 @@ namespace cpprtti | |||||
| static constexpr decltype(auto) is_read_only_v = | static constexpr decltype(auto) is_read_only_v = | ||||
| cppmp::is_const_v<cppmp::remove_reference_t<object_type>> | cppmp::is_const_v<cppmp::remove_reference_t<object_type>> | ||||
| || cppmp::is_const_v<cppmp::remove_reference_t<value_type>>; | |||||
| || cppmp::is_const_v<cppmp::remove_reference_t<value_type>> | |||||
| || !cppmp::is_copy_assignable_v<value_type>; | |||||
| }; | }; | ||||
| /* setter_info_trait */ | /* setter_info_trait */ | ||||
| @@ -1,8 +1,12 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <map> | |||||
| #include <string> | #include <string> | ||||
| #include <functional> | |||||
| #include <cpprtti/misc/helper.h> | #include <cpprtti/misc/helper.h> | ||||
| #include <cpprtti/misc/variant.h> | |||||
| #include <cpprtti/misc/storage.h> | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| @@ -22,12 +26,21 @@ namespace cpprtti | |||||
| * @brief represents any C++ type | * @brief represents any C++ type | ||||
| */ | */ | ||||
| struct type | struct type | ||||
| : public storage_container | |||||
| { | { | ||||
| public: | |||||
| using converter = std::function<variant(variant)>; | |||||
| using converter_map = std::map<type_id, converter>; | |||||
| template<typename T_base> | |||||
| friend struct type_decorator; | |||||
| protected: | protected: | ||||
| cpprtti::registry& _registry; //!< Type registry this type belongs to. | cpprtti::registry& _registry; //!< Type registry this type belongs to. | ||||
| type_id _id; //!< Unique ID | type_id _id; //!< Unique ID | ||||
| std::string _name; //!< Name of the type. | std::string _name; //!< Name of the type. | ||||
| rtti_type_t _rtti_type; //!< Type specialization | |||||
| rtti_type_t _rtti_type; //!< Type specialization. | |||||
| converter_map _converters; //!< Convert this type to another type. | |||||
| public: | public: | ||||
| /** | /** | ||||
| @@ -68,8 +81,28 @@ namespace cpprtti | |||||
| * @brief Get the RTTI type of this type object. | * @brief Get the RTTI type of this type object. | ||||
| */ | */ | ||||
| inline rtti_type_t rtti_type() const; | inline rtti_type_t rtti_type() const; | ||||
| /** | |||||
| * @brief Get a converter that can convert this type to the passed type. | |||||
| */ | |||||
| template<typename T_to> | |||||
| inline const converter* convert_to() const; | |||||
| /** | |||||
| * @brief Get a converter that can convert this type to the passed type ID. | |||||
| */ | |||||
| inline const converter* convert_to(type_id id) const; | |||||
| /** | |||||
| * @brief Get a converter that can convert the passed type to this type. | |||||
| */ | |||||
| template<typename T_from> | |||||
| inline const converter* convert_from() const; | |||||
| /** | |||||
| * @brief Get a converter that can convert the passed type ID to this type. | |||||
| */ | |||||
| inline const converter* convert_from(type_id id) const; | |||||
| }; | }; | ||||
| } | } | ||||
| #include "type.inl" | |||||
| @@ -1,6 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "type.h" | #include "type.h" | ||||
| #include "../registry.h" | |||||
| namespace cpprtti | namespace cpprtti | ||||
| { | { | ||||
| @@ -33,4 +34,38 @@ namespace cpprtti | |||||
| rtti_type_t type::rtti_type() const | rtti_type_t type::rtti_type() const | ||||
| { return _rtti_type; } | { return _rtti_type; } | ||||
| template<typename T_to> | |||||
| const type::converter* type::convert_to() const | |||||
| { | |||||
| using to_type = cppmp::decay_t<T_to>; | |||||
| return convert_to(get_type_id<to_type>()); | |||||
| } | |||||
| const type::converter* type::convert_to(type_id id) const | |||||
| { | |||||
| auto it = _converters.find(id); | |||||
| return it == _converters.end() | |||||
| ? nullptr | |||||
| : &it->second; | |||||
| } | |||||
| template<typename T_from> | |||||
| const type::converter* type::convert_from() const | |||||
| { | |||||
| using from_type = cppmp::decay_t<T_from>; | |||||
| return convert_from(get_type_id<from_type>()); | |||||
| } | |||||
| const type::converter* type::convert_from(type_id id) const | |||||
| { | |||||
| auto* type = _registry.find(id); | |||||
| if (!type) | |||||
| return nullptr; | |||||
| auto it = type->_converters.find(this->_id); | |||||
| return it == type->_converters.end() | |||||
| ? nullptr | |||||
| : &it->second; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,32 @@ | |||||
| #pragma once | |||||
| #include "type.h" | |||||
| namespace cpprtti | |||||
| { | |||||
| template<typename T_base> | |||||
| struct type_decorator | |||||
| : public T_base | |||||
| { | |||||
| public: | |||||
| using base_type = T_base; | |||||
| using converter = typename type::converter; | |||||
| public: | |||||
| using base_type::base_type; | |||||
| /** | |||||
| * @brief Set the converter that can convert this type to the passed type. | |||||
| */ | |||||
| template<typename T_to> | |||||
| inline auto& convert_to(const converter& p_converter); | |||||
| /** | |||||
| * @brief Set the converter that can convert the passed type to this type. | |||||
| */ | |||||
| template<typename T_from> | |||||
| inline auto& convert_from(const converter& p_converter); | |||||
| }; | |||||
| } | |||||
| @@ -0,0 +1,39 @@ | |||||
| #pragma once | |||||
| #include <cppmp/core/modifier.h> | |||||
| #include "type_decorator.h" | |||||
| #include "../misc/helper.h" | |||||
| namespace cpprtti | |||||
| { | |||||
| /* type_decorator */ | |||||
| template<typename T_base> | |||||
| template<typename T_to> | |||||
| auto& type_decorator<T_base> | |||||
| ::convert_to(const converter& p_converter) | |||||
| { | |||||
| using to_type = cppmp::decay_t<T_to>; | |||||
| auto id = get_type_id<to_type>(); | |||||
| this->_converters[id] = p_converter; | |||||
| return *this; | |||||
| } | |||||
| template<typename T_base> | |||||
| template<typename T_from> | |||||
| auto& type_decorator<T_base> | |||||
| ::convert_from(const converter& p_converter) | |||||
| { | |||||
| using from_type = T_from; | |||||
| auto& type = this->_registry.template get<from_type>(); | |||||
| type._converters[this->_id] = p_converter; | |||||
| return *this; | |||||
| } | |||||
| } | |||||
| @@ -1,38 +1,37 @@ | |||||
| # Initialize ###################################################################################### | # Initialize ###################################################################################### | ||||
| Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||||
| Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||||
| Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_SYMBOLS ) | |||||
| Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||||
| Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||||
| Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_SYMBOLS ) | |||||
| Find_Package ( cppcore ) | |||||
| Find_Package ( cppmp ) | |||||
| Find_Package ( cppmp ) | |||||
| Find_Package ( cppcore ) | |||||
| # Object Library ################################################################################## | |||||
| # Interface Library ############################################################################### | |||||
| Set ( CPPRTTI_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include ) | |||||
| Add_Library ( cpprtti | |||||
| INTERFACE ) | |||||
| Target_Include_Directories ( cpprtti | |||||
| INTERFACE | |||||
| $<BUILD_INTERFACE:${CPPRTTI_INCLUDE_DIR}> | |||||
| $<INSTALL_INTERFACE:${CPPRTTI_INSTALL_DIR_INCLUDE}> ) | |||||
| Target_Link_Libraries ( cpprtti | |||||
| INTERFACE | |||||
| cppcore | |||||
| cppmp ) | |||||
| Set ( CPPRTTI_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include ) | |||||
| Add_Library ( cpprtti INTERFACE ) | |||||
| Target_Include_Directories ( cpprtti | |||||
| INTERFACE | |||||
| $<BUILD_INTERFACE:${CPPRTTI_INCLUDE_DIR}> | |||||
| $<INSTALL_INTERFACE:${CPPRTTI_INSTALL_DIR_INCLUDE}> ) | |||||
| Target_Link_Libraries ( cpprtti | |||||
| INTERFACE | |||||
| cppmp | |||||
| cppcore ) | |||||
| # Install ######################################################################################### | # Install ######################################################################################### | ||||
| Set ( CPPRTTI_HAS_EXPORT False PARENT_SCOPE ) | |||||
| Set ( CPPRTTI_HAS_EXPORT False PARENT_SCOPE ) | |||||
| # Header | # Header | ||||
| If ( CPPRTTI_INSTALL_HEADER ) | |||||
| Set ( CPPRTTI_HAS_EXPORT True PARENT_SCOPE ) | |||||
| Install ( FILES ${CPPRTTI_INCLUDE_DIR}/cpprtti.h | |||||
| DESTINATION ${CPPRTTI_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( DIRECTORY ${CPPRTTI_INCLUDE_DIR}/cpprtti | |||||
| DESTINATION ${CPPRTTI_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( TARGETS cpprtti | |||||
| EXPORT cpprtti | |||||
| DESTINATION ${CPPRTTI_INSTALL_DIR_INCLUDE} ) | |||||
| EndIf ( ) | |||||
| If ( CPPRTTI_INSTALL_HEADER ) | |||||
| Set ( CPPRTTI_HAS_EXPORT True PARENT_SCOPE ) | |||||
| Install ( FILES ${CPPRTTI_INCLUDE_DIR}/cpprtti.h | |||||
| DESTINATION ${CPPRTTI_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( DIRECTORY ${CPPRTTI_INCLUDE_DIR}/cpprtti | |||||
| DESTINATION ${CPPRTTI_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( TARGETS cpprtti | |||||
| EXPORT cpprtti | |||||
| DESTINATION ${CPPRTTI_INSTALL_DIR_INCLUDE} ) | |||||
| EndIf ( ) | |||||
| @@ -1,52 +1,59 @@ | |||||
| # Initialize ###################################################################################### | # Initialize ###################################################################################### | ||||
| Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||||
| Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||||
| Include ( cmake_tests OPTIONAL RESULT_VARIABLE HAS_CMAKE_TESTS ) | |||||
| Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||||
| Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||||
| Include ( cmake_tests OPTIONAL RESULT_VARIABLE HAS_CMAKE_TESTS ) | |||||
| Find_Package ( Sanitizers QUIET ) | |||||
| # Test ############################################################################################ | # Test ############################################################################################ | ||||
| Find_Package ( GTest ) | |||||
| If ( NOT "${GTest_FOUND}" ) | |||||
| Return ( ) | |||||
| EndIf ( ) | |||||
| Find_Package ( GTest ) | |||||
| If ( NOT "${GTest_FOUND}" ) | |||||
| Return ( ) | |||||
| EndIf ( ) | |||||
| File ( GLOB_RECURSE CPPRTTI_TEST_HEADER_FILES | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/*.h ) | |||||
| File ( GLOB_RECURSE CPPRTTI_TEST_INLINE_FILES | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/*.inl ) | |||||
| File ( GLOB_RECURSE CPPRTTI_TEST_SOURCE_FILES | |||||
| RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||||
| File ( GLOB_RECURSE CPPRTTI_TEST_HEADER_FILES | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/*.h ) | |||||
| File ( GLOB_RECURSE CPPRTTI_TEST_INLINE_FILES | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/*.inl ) | |||||
| File ( GLOB_RECURSE CPPRTTI_TEST_SOURCE_FILES | |||||
| RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||||
| ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||||
| ForEach ( FILE IN LISTS CPPRTTI_TEST_SOURCE_FILES ) | |||||
| ForEach ( FILE IN LISTS CPPRTTI_TEST_SOURCE_FILES ) | |||||
| # add test | # add test | ||||
| Get_Filename_Component ( TEST_DIR ${FILE} DIRECTORY ) | |||||
| Get_Filename_Component ( TEST_NAME ${FILE} NAME_WE ) | |||||
| Set ( TEST_NAME "${TEST_DIR}/${TEST_NAME}" ) | |||||
| String ( REPLACE "\\" "-" TEST_NAME "${TEST_NAME}" ) | |||||
| String ( REPLACE "/" "-" TEST_NAME "${TEST_NAME}" ) | |||||
| String ( REPLACE "_" "-" TEST_NAME "${TEST_NAME}" ) | |||||
| Set ( TEST_NAME "test-${TEST_NAME}" ) | |||||
| Add_Executable ( ${TEST_NAME} | |||||
| EXCLUDE_FROM_ALL | |||||
| ${CPPRTTI_TEST_HEADER_FILES} | |||||
| ${CPPRTTI_TEST_INLINE_FILES} | |||||
| ${FILE} ) | |||||
| Target_Link_Libraries ( ${TEST_NAME} | |||||
| PUBLIC | |||||
| cpprtti | |||||
| GTest::Main ) | |||||
| Get_Filename_Component ( TEST_DIR ${FILE} DIRECTORY ) | |||||
| Get_Filename_Component ( TEST_NAME ${FILE} NAME_WE ) | |||||
| Set ( TEST_NAME "${TEST_DIR}/${TEST_NAME}" ) | |||||
| String ( REPLACE "\\" "-" TEST_NAME "${TEST_NAME}" ) | |||||
| String ( REPLACE "/" "-" TEST_NAME "${TEST_NAME}" ) | |||||
| String ( REPLACE "_" "-" TEST_NAME "${TEST_NAME}" ) | |||||
| Set ( TEST_NAME "test-${TEST_NAME}" ) | |||||
| Add_Executable ( ${TEST_NAME} | |||||
| EXCLUDE_FROM_ALL | |||||
| ${CPPRTTI_TEST_HEADER_FILES} | |||||
| ${CPPRTTI_TEST_INLINE_FILES} | |||||
| ${FILE} ) | |||||
| Target_Link_Libraries ( ${TEST_NAME} | |||||
| PUBLIC | |||||
| cpprtti | |||||
| GTest::Main ) | |||||
| # Sanitizers | |||||
| If ( Sanitizers_FOUND ) | |||||
| Add_Sanitizers ( ${TEST_NAME} ) | |||||
| EndIf ( ) | |||||
| # pedantic | # pedantic | ||||
| If ( HAS_PEDANTIC ) | |||||
| Pedantic_Apply_Flags_Target ( ${TEST_NAME} ALL ) | |||||
| EndIf ( ) | |||||
| If ( HAS_PEDANTIC ) | |||||
| Pedantic_Apply_Flags_Target ( ${TEST_NAME} ALL ) | |||||
| EndIf ( ) | |||||
| # test | # test | ||||
| If ( HAS_CMAKE_TESTS ) | |||||
| Add_CMake_Test ( NAME ${TEST_NAME} TARGET ${TEST_NAME} GROUP cpprtti ) | |||||
| Else ( ) | |||||
| Add_Test ( NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) | |||||
| EndIf ( ) | |||||
| EndForEach ( ) | |||||
| If ( HAS_CMAKE_TESTS ) | |||||
| Add_CMake_Test ( NAME ${TEST_NAME} TARGET ${TEST_NAME} GROUP cpprtti ) | |||||
| Else ( ) | |||||
| Add_Test ( NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) | |||||
| EndIf ( ) | |||||
| EndForEach ( ) | |||||
| @@ -1,5 +1,6 @@ | |||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
| #include <cpprtti/misc/variant.h> | |||||
| #include <cpprtti.h> | |||||
| using namespace cpprtti; | using namespace cpprtti; | ||||
| @@ -1,4 +1,5 @@ | |||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
| #include <cpprtti.h> | #include <cpprtti.h> | ||||
| using namespace cpprtti; | using namespace cpprtti; | ||||