RavEngine
Loading...
Searching...
No Matches
CTTI.hpp
1#pragma once
2#include <stddef.h>
3#include <cstdint>
4#include <string_view>
5#include <type_traits>
6
7#ifdef _WIN32
8 #define __PRETTY_FUNCTION__ __FUNCSIG__
9#endif
10
11namespace RavEngine{
12
13// Derive from this struct to get a free CTTI specialization
14struct AutoCTTI{
15 AutoCTTI() {}
16};
17
18typedef size_t ctti_t;
19
20//compile-time hashing adapted from https://mikejsavage.co.uk/blog/cpp-tricks-compile-time-string-hashing.html
21
22consteval uint32_t Hash32_CT( const char * str, size_t n, uint32_t basis = uint_least32_t( 2166136261 ) ) {
23 return n == 0 ? basis : Hash32_CT( str + 1, n - 1, ( basis ^ str[ 0 ] ) * uint_least32_t( 16777619 ) );
24}
25consteval uint64_t Hash64_CT( const char * str, size_t n, uint64_t basis = uint_least64_t( 14695981039346656037U ) ) {
26 return n == 0 ? basis : Hash64_CT( str + 1, n - 1, ( basis ^ str[ 0 ] ) * uint_least64_t( 1099511628211 ) );
27}
28template< size_t N >
29consteval uint32_t Hash32_CT( const char ( &s )[ N ] ) {
30 return Hash32_CT( s, N);
31}
32template< size_t N >
33consteval uint64_t Hash64_CT( const char ( &s )[ N ] ) {
34 return Hash64_CT( s, N);
35}
36
37consteval uint32_t Hash32_CT(const std::string_view& v) {
38 return Hash32_CT(v.data(), v.size());
39}
40
41consteval uint64_t Hash64_CT(const std::string_view& v) {
42 return Hash64_CT(v.data(), v.size());
43}
44
45// Type name extraction
46
47template <typename T>
48consteval std::string_view type_name_impl();
49
50template <>
51consteval std::string_view type_name_impl<void>() {
52 return "void";
53}
54
55namespace detail {
56
57 using type_name_prober = void;
58
59 template <typename T>
60 consteval std::string_view wrapped_type_name()
61 {
62 return __PRETTY_FUNCTION__;
63 }
64
65 consteval std::size_t wrapped_type_name_prefix_length() {
66 return wrapped_type_name<type_name_prober>().find(type_name_impl<type_name_prober>());
67 }
68
69 consteval std::size_t wrapped_type_name_suffix_length() {
70 return wrapped_type_name<type_name_prober>().length()
71 - wrapped_type_name_prefix_length()
72 - type_name_impl<type_name_prober>().length();
73 }
74}
75
79template <typename T>
80consteval std::string_view type_name_impl() {
81 constexpr auto wrapped_name = detail::wrapped_type_name<T>();
82 constexpr auto prefix_length = detail::wrapped_type_name_prefix_length();
83 constexpr auto suffix_length = detail::wrapped_type_name_suffix_length();
84 constexpr auto type_name_length = wrapped_name.length() - prefix_length - suffix_length;
86}
87
88//already defined for void, don't want to define it again
89//defines automatically only for primitive types
90
91template<typename T>
92static constexpr bool fundamental_specialized = std::is_fundamental<T>::value && !std::is_same<T,void>::value;
93
94template<typename T, std::enable_if_t<fundamental_specialized<T>, bool> = false>
95consteval std::string_view type_name() {
96 return type_name_impl<T>();
97}
98
99template<typename T>
100static constexpr bool is_eligible = (std::is_base_of<RavEngine::AutoCTTI, T>::value || std::is_trivially_copyable<T>::value) && (!std::is_same<T,void>::value && !fundamental_specialized<T>);
101
102template<typename T>
103static constexpr bool is_ineligible = !is_eligible<T> && !fundamental_specialized<T>;
104
105// for structs, provide an automatic CTTI implementation using the derivation
106template <typename T, std::enable_if_t<is_eligible<T>,bool> = false>
107consteval std::string_view type_name() {
108#ifdef _MSC_VER
109 constexpr auto str = type_name_impl<T>();
110 size_t offset = 0;
111 static_assert(str[0] == 'c' || str[0] == 's', "Type must be a class or struct");
112 if constexpr (str[0] == 'c'){
113 offset = sizeof("class"); //advance past 'class'
114 }
115 else if (str[0] == 's'){
116 offset = sizeof("struct"); //advance past 'struct'
117 }
118 return std::string_view(str.data() + offset, str.size() - offset);
119#else
120 return type_name_impl<T>();
121#endif
122}
123
124// this is the catch-all for types that do not satisfy the above requirements
125// this specialization always fails.
126template<typename T, std::enable_if_t<is_ineligible<T>, bool> = false>
127consteval std::string_view type_name(){
128 static_assert(is_ineligible<T>,"A platform-independent type-name string cannot be auto-generated for this type. Create a manual specialization. See mathtypes.hpp for an example.");
129 return "";
130}
131
132
137template<typename T>
138static consteval ctti_t CTTI(){
139 return Hash32_CT(type_name<T>());
140}
141
142}
Definition concurrentqueue.h:747
uint64 uint64_t
Definition fwd.hpp:145
uint32 uint32_t
Definition fwd.hpp:131
Definition Animation.hpp:6
consteval std::string_view type_name_impl()
Definition CTTI.hpp:80
Definition CTTI.hpp:14