initial commit
This commit is contained in:
commit
37ff6c2b01
6 changed files with 308 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# emacs project control file
|
||||||
|
.projectile
|
||||||
|
# clangd working space (see emacs+lsp)
|
||||||
|
.cache
|
||||||
|
# typical cmake build directory (source-tree-nephew)
|
||||||
|
.build*
|
||||||
|
# symlink to builddir/compile_commands.json; should be set manually in dev sandbox
|
||||||
|
compile_commands.json
|
||||||
46
CMakeLists.txt
Normal file
46
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# xo-reflectutil/CMakeLists.txt
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(xo_reflectutil VERSION 1.0)
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(cmake/xo-bootstrap-macros.cmake)
|
||||||
|
|
||||||
|
xo_cxx_toplevel_options3()
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
# c++ settings
|
||||||
|
|
||||||
|
# one-time project-specific c++ flags. usually empty
|
||||||
|
set(PROJECT_CXX_FLAGS "")
|
||||||
|
#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2")
|
||||||
|
add_definitions(${PROJECT_CXX_FLAGS})
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
|
#add_subdirectory(example)
|
||||||
|
#add_subdirectory(utest)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
# provide find_package() support for projects using this library
|
||||||
|
|
||||||
|
set(SELF_LIB xo_reflectutil)
|
||||||
|
xo_add_headeronly_library(${SELF_LIB})
|
||||||
|
xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets)
|
||||||
|
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
# docs targets depend on all the other library/utest targets
|
||||||
|
#
|
||||||
|
#add_subdirectory(docs)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
# dependencies
|
||||||
|
|
||||||
|
xo_headeronly_dependency(${SELF_LIB} xo_flatstring)
|
||||||
|
#xo_headeronly_dependency(${SELF_LIB} randomgen)
|
||||||
|
# etc..
|
||||||
|
|
||||||
|
# end CMakeLists.txt
|
||||||
29
LICENSE
Normal file
29
LICENSE
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
Copyright (c) 2024 Roland Conybeare <git3ub@nym.hush.com>, All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
|
||||||
|
external contributions to this project including patches, pull requests, etc.
|
||||||
33
cmake/xo-bootstrap-macros.cmake
Normal file
33
cmake/xo-bootstrap-macros.cmake
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
# for example:
|
||||||
|
# $ PREFIX=/usr/local # for example
|
||||||
|
# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build
|
||||||
|
#
|
||||||
|
# will get
|
||||||
|
# CMAKE_MODULE_PATH
|
||||||
|
# from xo-cmake-config --cmake-module-path
|
||||||
|
#
|
||||||
|
# and expect .cmake macros in
|
||||||
|
# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake
|
||||||
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
|
find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED)
|
||||||
|
|
||||||
|
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "prefix"))
|
||||||
|
message(FATAL "could not find xo-cmake-config executable")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT XO_SUBMODULE_BUILD)
|
||||||
|
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix))
|
||||||
|
# default to typical install location for xo-project-macros
|
||||||
|
execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH)
|
||||||
|
message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# needs to have been installed somewhere on CMAKE_MODULE_PATH,
|
||||||
|
# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX)
|
||||||
|
#
|
||||||
|
include(xo_macros/xo_cxx)
|
||||||
|
|
||||||
|
xo_cxx_bootstrap_message()
|
||||||
17
cmake/xo_reflectutilConfig.cmake.in
Normal file
17
cmake/xo_reflectutilConfig.cmake.in
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
include(CMakeFindDependencyMacro)
|
||||||
|
|
||||||
|
# note: changes to find_dependency() calls here
|
||||||
|
# must coordinate with xo_dependency() calls
|
||||||
|
# in xo-reactor/src/reactor/CMakeLists.txt
|
||||||
|
#
|
||||||
|
find_dependency(xo_flatstring)
|
||||||
|
#find_dependency(subsys)
|
||||||
|
#find_dependency(Eigen3)
|
||||||
|
#find_dependency(webutil)
|
||||||
|
#find_dependency(printjson)
|
||||||
|
#find_dependency(callback)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
check_required_components("@PROJECT_NAME@")
|
||||||
175
include/xo/reflectutil/reflect_struct_info.hpp
Normal file
175
include/xo/reflectutil/reflect_struct_info.hpp
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
/** @file reflect_struct_info.hpp
|
||||||
|
*
|
||||||
|
* Author: Roland Conybeare
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace reflect {
|
||||||
|
/** Instructions for reflecting a struct:
|
||||||
|
*
|
||||||
|
* #include "xo/reflectutil/reflect_struct_info.hpp" // this file
|
||||||
|
*
|
||||||
|
* namespace xo {
|
||||||
|
* namespace reflect {
|
||||||
|
* // replacing X with the number of member variables in foo:
|
||||||
|
* REFLECT_BASE_STRUCT_INFO(some::ns::foo, X);
|
||||||
|
*
|
||||||
|
* // for each member {member_0, member_1, ...} of foo,
|
||||||
|
* // in the same order as they appear in class/struct decl:
|
||||||
|
* REFLECT_STRUCT_MEMBER_INFO(some::ns::foo, 0, member(0));
|
||||||
|
* REFLECT_STRUCT_MEMBER_INFO(some::ns::foo, 1, member(1);
|
||||||
|
* ..
|
||||||
|
* // (last member will have index number X-1)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* These decls can appear anywhere after decl for some::ns::foo;
|
||||||
|
* they must be made in the global namespace
|
||||||
|
* (so that specializations appear in the xo::reflect namespace)
|
||||||
|
*
|
||||||
|
* Finally to permanently capture struct ingredients,
|
||||||
|
* this statement must run at least once:
|
||||||
|
*
|
||||||
|
* xo::reflect::reflect_struct<some::ns::foo>();
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define REFLECT_BASE_STRUCT_INFO_TBODY(qualified_struct_name, member_count) \
|
||||||
|
struct reflect_struct_traits<qualified_struct_name> { \
|
||||||
|
static constexpr std::size_t n_members = member_count; \
|
||||||
|
static constexpr std::size_t n_parents = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define REFLECT_BASE_STRUCT_INFO(qualified_struct_name, member_count) \
|
||||||
|
template<> \
|
||||||
|
REFLECT_BASE_STRUCT_INFO_TBODY(qualified_struct_name, member_count)
|
||||||
|
|
||||||
|
#define REFLECT_STRUCT_MEMBER_INFO_TBODY(qualified_struct_name, member_ix, member_name) \
|
||||||
|
struct reflect_struct_member<qualified_struct_name, member_ix> { \
|
||||||
|
constexpr auto get() const { \
|
||||||
|
return reflect_struct_member_aux(xo::flatstring(#member_name), \
|
||||||
|
&qualified_struct_name::member_name##_); \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REFLECT_STRUCT_MEMBER_INFO(qualified_struct_name, member_ix, member_name) \
|
||||||
|
template <> \
|
||||||
|
REFLECT_STRUCT_MEMBER_INFO_TBODY(qualified_struct_name, member_ix, member_name)
|
||||||
|
|
||||||
|
/** @class reflect_struct_traits
|
||||||
|
*
|
||||||
|
* @brief header-only ingredients for reflecting a struct
|
||||||
|
*
|
||||||
|
* A class/struct T to be reflected should provide specializations
|
||||||
|
* of
|
||||||
|
* - xo::reflect::reflect_struct_traits<>
|
||||||
|
* - xo::reflect::reflect_struct_member<>
|
||||||
|
* - xo::reflect::reflect_struct_parent<> [aspirational, not yet]
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
*
|
||||||
|
* namespace foo {
|
||||||
|
* struct mycomplex { double real_, double imag_; };
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* namespace xo {
|
||||||
|
* namespace reflect {
|
||||||
|
* template <>
|
||||||
|
* struct reflect_struct_traits<foo::mycomplex> {
|
||||||
|
*
|
||||||
|
* // number of member variables
|
||||||
|
* static constexpr std::size_t n_members = 2;
|
||||||
|
*
|
||||||
|
* // number of parent structs
|
||||||
|
* // (i.e. directly inherited structs)
|
||||||
|
* static constexpr std::size_t n_parents = 0;
|
||||||
|
* };
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // or use convenience macro (must be in global namespace)
|
||||||
|
* REFLECT_BASE_STRUCT_INFO(foo::mycomplex, 2);
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
**/
|
||||||
|
template <typename T>
|
||||||
|
struct reflect_struct_traits;
|
||||||
|
|
||||||
|
/** @class reflect_struct_member
|
||||||
|
* @brief reflection ingredients for a particular struct member
|
||||||
|
*
|
||||||
|
* A class/struct T to be reflected should provide specializations
|
||||||
|
* of
|
||||||
|
* - xo::reflect::reflect_struct_traits<>
|
||||||
|
* - xo::reflect::reflect_struct_member<>
|
||||||
|
* - xo::reflect::reflect_struct_parent<> [aspirational, not yet]
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
*
|
||||||
|
* namespace foo {
|
||||||
|
* struct mycomplex { double real_, double imag_; };
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* namespace xo {
|
||||||
|
* namespace reflect {
|
||||||
|
* // reflect foo::mycomplex::real_
|
||||||
|
* template <>
|
||||||
|
* struct reflect_struct_member<foo::mycomplex, 0> {
|
||||||
|
* constexpr auto operator()() const { return reflect_struct_member_aux(xo::flatstring("real"), &foo::mycomplex::real_); }
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* // reflect foo::mycomplex::imag_
|
||||||
|
* template <>
|
||||||
|
* struct reflect_struct_member<foo::mycomplex, 1> {
|
||||||
|
* constexpr auto operator()() const { return reflect_struct_member_aux(xo::flatstring("imag"), &foo::mycomplex::imag_); }
|
||||||
|
* };
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // or use convenience macro (must be invoked from global namespace)
|
||||||
|
* REFLECT_STRUCT_MEMBER_INFO(foo::mycomplex, 0, real);
|
||||||
|
* REFLECT_STRUCT_MEMBER_INFO(foo::mycomplex, 1, imag);
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
**/
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
struct reflect_struct_member;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
|
template <typename OwnerT, typename MemberT, typename MemberNameT>
|
||||||
|
struct reflect_struct_member_info {
|
||||||
|
//using struct_type = StructT;
|
||||||
|
using owner_type = OwnerT;
|
||||||
|
using member_type = MemberT;
|
||||||
|
using member_name_type = MemberNameT;
|
||||||
|
|
||||||
|
constexpr reflect_struct_member_info(const MemberNameT & member_name,
|
||||||
|
MemberT OwnerT::* member_addr)
|
||||||
|
: member_name_{member_name}, member_addr_{member_addr} {}
|
||||||
|
|
||||||
|
MemberNameT member_name_;
|
||||||
|
MemberT OwnerT::* member_addr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
|
template <typename OwnerT, typename MemberT, typename MemberNameT>
|
||||||
|
constexpr auto reflect_struct_member_aux(const MemberNameT & member_name,
|
||||||
|
MemberT OwnerT:: * member_addr) {
|
||||||
|
return reflect_struct_member_info<OwnerT, MemberT, MemberNameT>
|
||||||
|
(member_name, member_addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /*namespace reflect*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/** end reflect_struct_info.hpp **/
|
||||||
Loading…
Add table
Add a link
Reference in a new issue