xo-reader2 stack: + TypeRegistry
This commit is contained in:
parent
d895083b58
commit
fc9ca649dd
2 changed files with 153 additions and 30 deletions
94
include/xo/reflectutil/type_name.hpp
Normal file
94
include/xo/reflectutil/type_name.hpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* @file type_name.hpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include <string>
|
||||
#include <string_view>
|
||||
#include <array> // std::array
|
||||
#include <utility> // std::index_sequence
|
||||
|
||||
namespace xo {
|
||||
namespace reflect {
|
||||
|
||||
template <std::size_t...Idxs>
|
||||
constexpr auto
|
||||
substring_as_array(std::string_view str,
|
||||
std::index_sequence<Idxs...> indexes)
|
||||
{
|
||||
//return std::array<char, indexes.size()+1>{str[Idxs]..., '\n'};
|
||||
return std::array<char, indexes.size()>{str[Idxs]...};
|
||||
} /*substring_as_array*/
|
||||
|
||||
template <typename T> constexpr auto type_name_array() {
|
||||
#if defined(__clang__)
|
||||
constexpr auto prefix = std::string_view{"[T = "};
|
||||
constexpr auto suffix = std::string_view{"]"};
|
||||
constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
|
||||
#elif defined(__GNUC__)
|
||||
constexpr auto prefix = std::string_view{"with T = "};
|
||||
constexpr auto suffix = std::string_view{"]"};
|
||||
constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
|
||||
#elif defined(_MSC_VER)
|
||||
constexpr auto prefix = std::string_view{"type_name_array<"};
|
||||
constexpr auto suffix = std::string_view{">(void)"};
|
||||
constexpr auto function = std::string_view{__FUNCSIG__};
|
||||
#else
|
||||
# error type_name_array: Unsupported compiler
|
||||
#endif
|
||||
|
||||
constexpr auto start = function.find(prefix) + prefix.size();
|
||||
constexpr auto end = function.rfind(suffix);
|
||||
|
||||
//static_assert(start < end);
|
||||
|
||||
constexpr auto name = function.substr(start, (end - start));
|
||||
|
||||
constexpr auto ixseq = std::make_index_sequence<name.size()>{};
|
||||
|
||||
return substring_as_array(name, ixseq);
|
||||
} /*type_name_array*/
|
||||
|
||||
template <typename T>
|
||||
struct type_name_holder {
|
||||
static inline constexpr auto value = type_name_array<T>();
|
||||
};
|
||||
|
||||
/** report name of type T as a string_view;
|
||||
* using constexpr deps so runs at **/
|
||||
template <typename T>
|
||||
constexpr auto type_name() -> std::string_view
|
||||
{
|
||||
constexpr auto& value = type_name_holder<T>::value;
|
||||
return std::string_view{value.data(), value.size()};
|
||||
}
|
||||
|
||||
#ifdef NOT_IN_USE
|
||||
template <std::string_view const&... Strs>
|
||||
struct join
|
||||
{
|
||||
// Join all strings into a single std::array of chars
|
||||
static constexpr auto impl() noexcept
|
||||
{
|
||||
constexpr std::size_t len = (Strs.size() + ... + 0);
|
||||
std::array<char, len + 1> arr{};
|
||||
auto append = [i = 0, &arr](auto const& s) mutable {
|
||||
for (auto c : s) arr[i++] = c;
|
||||
};
|
||||
(append(Strs), ...);
|
||||
arr[len] = 0;
|
||||
return arr;
|
||||
}
|
||||
// Give the joined string static storage
|
||||
static constexpr auto arr = impl();
|
||||
// View as a std::string_view
|
||||
static constexpr std::string_view value {arr.data(), arr.size() - 1};
|
||||
};
|
||||
|
||||
// Helper to get the value out
|
||||
template <std::string_view const&... Strs>
|
||||
static constexpr auto join_v = join<Strs...>::value;
|
||||
#endif
|
||||
} /*namespace reflect*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end type_name.hpp */
|
||||
|
|
@ -5,22 +5,20 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "type_name.hpp"
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace reflect {
|
||||
/**
|
||||
* Tag here so we can preserve header-only implementation
|
||||
* and still have static variable
|
||||
*/
|
||||
template<typename Tag = class typeseq_tag>
|
||||
struct typeseq_impl {
|
||||
/** create sentinel value **/
|
||||
typeseq_impl() = default;
|
||||
// template <typename Tag = class typerecd_tag>
|
||||
struct typerecd {
|
||||
/** sentinel value **/
|
||||
typerecd() = default;
|
||||
|
||||
/** typeseq with specific unique id **/
|
||||
explicit typeseq_impl(int32_t s) : seqno_{s} {}
|
||||
/** type-record with specific, unique id **/
|
||||
explicit typerecd(int32_t s,
|
||||
std::string_view n) : seqno_{s}, name_{n} {}
|
||||
|
||||
/** Can't have this be constexpr.
|
||||
* We need ids in shared libraries to be generated
|
||||
|
|
@ -35,57 +33,88 @@ namespace xo {
|
|||
* when using clang.
|
||||
**/
|
||||
template <typename T>
|
||||
static typeseq_impl<Tag> id() {
|
||||
static bool armed = true;
|
||||
static typerecd recd() {
|
||||
// reminder: {armed, id} are distint for each T
|
||||
static bool s_armed = true;
|
||||
static int32_t id = 0;
|
||||
|
||||
if (armed) {
|
||||
armed = false;
|
||||
id = ++s_next_id;
|
||||
if (s_armed) {
|
||||
s_armed = false;
|
||||
id = require_next_id();
|
||||
}
|
||||
|
||||
return typeseq_impl(id);
|
||||
return typerecd(id, xo::reflect::type_name<T>());
|
||||
|
||||
}
|
||||
|
||||
static int32_t require_next_id() {
|
||||
static int32_t s_next_id = 0;
|
||||
return s_next_id++;
|
||||
}
|
||||
|
||||
int32_t seqno() const { return seqno_; }
|
||||
std::string_view name() const { return name_; }
|
||||
|
||||
/** sentinel typerecd instance **/
|
||||
static typerecd sentinel() {
|
||||
return typerecd(-1, "_%sentinel%_");
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t seqno_ = 0;
|
||||
std::string_view name_;
|
||||
};
|
||||
|
||||
//template <typename Tag>
|
||||
//int32_t typerecd_impl<Tag>::s_next_id = 0;
|
||||
|
||||
/**
|
||||
* Tag here so we can preserve header-only implementation
|
||||
* and still have static variable
|
||||
*/
|
||||
struct typeseq {
|
||||
/** create sentinel value **/
|
||||
typeseq() = default;
|
||||
|
||||
/** typeseq with specific unique id **/
|
||||
explicit typeseq(int32_t s) : seqno_{s} {}
|
||||
|
||||
/** 'anonymous' sentinel type.
|
||||
* Niche uses for this, e.g. untyped allocator
|
||||
**/
|
||||
static typeseq_impl<Tag> anon() {
|
||||
return typeseq_impl(-1);
|
||||
static typeseq sentinel() {
|
||||
return typeseq(typerecd::sentinel().seqno());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typeseq id() {
|
||||
return typeseq(xo::reflect::typerecd::recd<T>().seqno());
|
||||
}
|
||||
|
||||
int32_t seqno() const { return seqno_; }
|
||||
|
||||
private:
|
||||
static int32_t s_next_id;
|
||||
|
||||
int32_t seqno_ = 0;
|
||||
};
|
||||
|
||||
template <typename Tag>
|
||||
int32_t typeseq_impl<Tag>::s_next_id = 0;
|
||||
//template <typename Tag>
|
||||
//int32_t typeseq_impl<Tag>::s_next_id = 0;
|
||||
|
||||
template <typename Tag>
|
||||
inline bool
|
||||
operator==(const typeseq_impl<Tag> & lhs, const typeseq_impl<Tag> & rhs) {
|
||||
operator==(const typeseq & lhs, const typeseq & rhs) {
|
||||
return lhs.seqno() == rhs.seqno();
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
inline bool
|
||||
operator!=(const typeseq_impl<Tag> & lhs, const typeseq_impl<Tag> & rhs) {
|
||||
operator!=(const typeseq & lhs, const typeseq & rhs) {
|
||||
return lhs.seqno() != rhs.seqno();
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream & s, const typeseq_impl<Tag> & x) {
|
||||
operator<<(std::ostream & s, const typeseq & x) {
|
||||
s << x.seqno();
|
||||
return s;
|
||||
}
|
||||
|
||||
using typeseq = typeseq_impl<>;
|
||||
} /*namespace reflect*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue