Radium Engine  1.5.20
Loading...
Searching...
No Matches
TypesUtils.hpp
1#pragma once
2
3#include <Core/CoreMacros.hpp>
4#include <Core/Utils/StringUtils.hpp>
5
6#ifndef _WIN32
7# include <cxxabi.h>
8# include <memory>
9#else
10# include <typeinfo>
11#endif
12
13#include <string>
14#include <typeindex>
15
16namespace Ra {
17namespace Core {
18namespace Utils {
19
21template <typename T>
22std::string demangleType() noexcept;
23
25template <typename T>
26std::string demangleType( const T& ) noexcept;
27
29std::string demangleType( const std::type_index& typeIndex ) noexcept;
30
32template <typename T>
33auto simplifiedDemangledType() noexcept -> std::string;
34
36template <typename T>
37auto simplifiedDemangledType( const T& ) noexcept -> std::string;
38
43// RA_CORE_API auto simplifiedDemangledType( const std::type_index& typeName ) noexcept ->
44// std::string;
45
46// -----------------------------------------------------------------
47// ---------------------- inline methods ---------------------------
48
49namespace TypeInternal {
50RA_CORE_API auto makeTypeReadable( const std::string& ) -> std::string;
51}
52
53template <typename T>
54auto simplifiedDemangledType() noexcept -> std::string {
55 static auto demangled_name = []() {
56 std::string demangledType =
57 TypeInternal::makeTypeReadable( Ra::Core::Utils::demangleType<T>() );
58 return demangledType;
59 }();
60 return demangled_name;
61}
62
63template <typename T>
64auto simplifiedDemangledType( const T& ) noexcept -> std::string {
65 return simplifiedDemangledType<T>();
66}
67
68inline auto simplifiedDemangledType( const std::type_index& typeName ) noexcept -> std::string {
69 return TypeInternal::makeTypeReadable( Ra::Core::Utils::demangleType( typeName ) );
70}
71
72// Check if a type is a container with access to its element type and number
73// adapted from https://stackoverflow.com/questions/13830158/check-if-a-variable-type-is-iterable
74namespace detail {
75
76using std::begin;
77using std::end;
78
79template <typename T>
80auto is_container_impl( int )
81 -> decltype( begin( std::declval<T&>() ) !=
82 end( std::declval<T&>() ), // begin/end and operator !=
83 void(), // Handle evil operator ,
84 std::declval<T&>().empty(),
85 std::declval<T&>().size(),
86 ++std::declval<decltype( begin( std::declval<T&>() ) )&>(), // operator ++
87 void( *begin( std::declval<T&>() ) ), // operator*
88 std::true_type {} );
89
90template <typename T>
91std::false_type is_container_impl( ... );
92
93} // namespace detail
94
95template <typename T>
96using is_container = decltype( detail::is_container_impl<T>( 0 ) );
97
98// TypeList taken and adapted from
99// https://github.com/AcademySoftwareFoundation/openvdb/blob/master/openvdb/openvdb/TypeList.h
100// Only took small part of TypeList utilities
101
102// forward declarations
103template <typename... Ts>
104struct TypeList;
105
106namespace TypeListInternal {
107
112template <typename ListT, typename... Ts>
114
119template <typename... Ts, typename... OtherTs>
120struct TSAppendImpl<TypeList<Ts...>, OtherTs...> {
121 using type = TypeList<Ts..., OtherTs...>;
122};
123
128template <typename... Ts, typename... OtherTs>
129struct TSAppendImpl<TypeList<Ts...>, TypeList<OtherTs...>> {
130 using type = TypeList<Ts..., OtherTs...>;
131};
132
133} // namespace TypeListInternal
134
135template <typename... Ts>
136struct TypeList {
138 using Self = TypeList;
140 static constexpr size_t Size = sizeof...( Ts );
141
157 template <typename... TypesToAppend>
158 using Append = typename TypeListInternal::TSAppendImpl<Self, TypesToAppend...>::type;
159};
160
161#ifdef _WIN32
162// On windows (since MSVC 2019), typeid( T ).name() (and then typeIndex.name() returns the demangled
163// name
164inline std::string demangleType( const std::type_index& typeIndex ) noexcept {
165 std::string retval = typeIndex.name();
166 removeAllInString( retval, "class " );
167 removeAllInString( retval, "struct " );
168 removeAllInString( retval, "__cdecl" );
169 replaceAllInString( retval, "& __ptr64", "&" );
170 replaceAllInString( retval, ",", ", " );
171 replaceAllInString( retval, " >", ">" );
172 replaceAllInString( retval, "__int64", "long" );
173 replaceAllInString( retval, "const &", "const&" );
174 return retval;
175}
176#else
177// On Linux/macos, use the C++ ABI demangler
178inline std::string demangleType( const std::type_index& typeIndex ) noexcept {
179 int error = 0;
180 std::string retval;
181 char* name = abi::__cxa_demangle( typeIndex.name(), 0, 0, &error );
182 if ( error == 0 ) { retval = name; }
183 else {
184 // error : -1 --> memory allocation failed
185 // error : -2 --> not a valid mangled name
186 // error : other --> __cxa_demangle
187 retval = std::string( "Type demangler error : " ) + std::to_string( error );
188 }
189 std::free( name );
190 removeAllInString( retval, "__1::" ); // or "::__1" ?
191 replaceAllInString( retval, " >", ">" );
192 return retval;
193}
194#endif
195template <typename T>
196std::string demangleType() noexcept {
197 // once per one type
198 static auto demangled_name = demangleType( std::type_index( typeid( T ) ) );
199 return demangled_name;
200}
201
202// calling with instances
203template <typename T>
204std::string demangleType( const T& ) noexcept {
205 return demangleType<T>();
206}
207
208} // namespace Utils
209} // namespace Core
210} // namespace Ra
T begin(T... args)
T declval(T... args)
T end(T... args)
T free(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
STL namespace.
Append any number of types to a TypeList.
T to_string(T... args)