Advanced Multi-Physics (AMP)
On-Line Documentation
typeid.h
Go to the documentation of this file.
1#ifndef included_AMP_typeid
2#define included_AMP_typeid
3
4#include <complex>
5#include <cstdint>
6#include <string_view>
7#include <type_traits>
8
9#include "AMP/AMP_TPLs.h"
10
11#ifndef AMP_CXX_STANDARD
12 #define AMP_CXX_STANDARD 17
13#endif
14#if AMP_CXX_STANDARD >= 20
15 #include <source_location>
16#endif
17
18
19namespace TypeID_Helpers {
20
21// Helper function to copy a string
22constexpr void copy( char *dst, const char *src, size_t N )
23{
24 for ( size_t i = 0; i < N; i++ )
25 dst[i] = 0;
26 for ( size_t i = 0; i < ( N - 1 ) && src[i] != 0; i++ )
27 dst[i] = src[i];
28}
29
30// Helper function to replace substrings
31constexpr void replace( char *str, size_t N, std::string_view match, std::string_view replace )
32{
33 std::string_view str2( str, N );
34 str2 = str2.substr( 0, str2.find( (char) 0 ) );
35 auto i = str2.find( match );
36 while ( i != std::string::npos ) {
37 if ( match.size() == replace.size() ) {
38 for ( size_t j = 0; j < match.size(); j++ )
39 str[i + j] = replace[j];
40 } else if ( match.size() > replace.size() ) {
41 for ( size_t j = 0; j < replace.size(); j++ )
42 str[i + j] = replace[j];
43 size_t D = match.size() - replace.size();
44 for ( size_t j = i + replace.size(); j < N - D; j++ )
45 str[j] = str[j + D];
46 for ( size_t j = N - D; j < N; j++ )
47 str[j] = 0;
48 } else {
49 throw std::logic_error( "Not finished" );
50 }
51 i = str2.find( match );
52 }
53}
54constexpr void deblank( char *str, size_t N )
55{
56 const char *whitespaces = " \t\f\v\n\r\0";
57 std::string_view str2( str, N );
58 str2 = str2.substr( 0, str2.find( (char) 0 ) );
59 auto i = str2.find_first_not_of( whitespaces );
60 auto j = str2.find_last_not_of( whitespaces );
61 if ( i == std::string::npos )
62 return;
63 str2 = str2.substr( i, j - i + 1 );
64 for ( size_t k = 0; k < str2.size(); k++ )
65 str[k] = str2[k];
66 for ( size_t k = str2.size(); k < N; k++ )
67 str[k] = 0;
68}
69
70// Perform murmur hash (constexpr version that assumes key.size() is a multiple of 8)
71template<std::size_t N>
72constexpr uint64_t MurmurHash64A( const char *key )
73{
74 static_assert( N % 8 == 0 );
75 const uint64_t seed = 0x65ce2a5d390efa53LLU;
76 const uint64_t m = 0xc6a4a7935bd1e995LLU;
77 const int r = 47;
78 uint64_t h = seed ^ ( N * m );
79 for ( size_t i = 0; i < N; i += 8 ) {
80 uint64_t k = ( uint64_t( key[i] ) << 56 ) ^ ( uint64_t( key[i + 1] ) << 48 ) ^
81 ( uint64_t( key[i + 2] ) << 40 ) ^ ( uint64_t( key[i + 3] ) << 32 ) ^
82 ( uint64_t( key[i + 4] ) << 24 ) ^ ( uint64_t( key[i + 5] ) << 16 ) ^
83 ( uint64_t( key[i + 6] ) << 8 ) ^ ( uint64_t( key[i + 7] ) );
84 k *= m;
85 k ^= k >> r;
86 k *= m;
87 h ^= k;
88 h *= m;
89 }
90 h ^= h >> r;
91 h *= m;
92 h ^= h >> r;
93 return h;
94}
95
96} // namespace TypeID_Helpers
97
98
111template<typename T>
112constexpr void getTypeName( uint64_t N, char *name )
113{
114 using namespace TypeID_Helpers;
115 if constexpr ( std::is_same_v<T, bool> ) {
116 copy( name, "bool", N );
117 } else if constexpr ( std::is_same_v<T, char> ) {
118 copy( name, "char", N );
119 } else if constexpr ( std::is_same_v<T, int8_t> ) {
120 copy( name, "int8_t", N );
121 } else if constexpr ( std::is_same_v<T, uint8_t> || std::is_same_v<T, unsigned char> ) {
122 copy( name, "uint8_t", N );
123 } else if constexpr ( std::is_same_v<T, int16_t> ) {
124 copy( name, "int16_t", N );
125 } else if constexpr ( std::is_same_v<T, uint16_t> ) {
126 copy( name, "uint16_t", N );
127 } else if constexpr ( std::is_same_v<T, int> || std::is_same_v<T, int32_t> ) {
128 copy( name, "int32_t", N );
129 } else if constexpr ( std::is_same_v<T, unsigned> || std::is_same_v<T, uint32_t> ) {
130 copy( name, "uint32_t", N );
131 } else if constexpr ( std::is_same_v<T, int64_t> ) {
132 copy( name, "int64_t", N );
133 } else if constexpr ( std::is_same_v<T, uint64_t> ) {
134 copy( name, "uint64_t", N );
135 } else if constexpr ( std::is_same_v<T, float> ) {
136 copy( name, "float", N );
137 } else if constexpr ( std::is_same_v<T, double> ) {
138 copy( name, "double", N );
139 } else if constexpr ( std::is_same_v<T, std::complex<float>> ) {
140 copy( name, "std::complex<float>", N );
141 } else if constexpr ( std::is_same_v<T, std::complex<double>> ) {
142 copy( name, "std::complex<double>", N );
143 } else if constexpr ( std::is_same_v<T, std::string> ) {
144 copy( name, "std::string", N );
145 } else if constexpr ( std::is_same_v<T, std::string_view> ) {
146 copy( name, "std::string_view", N );
147 } else {
148 // Get the type name from the function
149#if defined( __clang__ ) || defined( __GNUC__ )
150 constexpr std::string_view name0 = __PRETTY_FUNCTION__;
151 std::string_view name2 = name0;
152#elif defined( _MSC_VER )
153 constexpr std::string_view name0 = __FUNCSIG__;
154 std::string_view name2 = name0;
155#elif AMP_CXX_STANDARD >= 20
156 // Note this fails for nvhpc (does not contain template type)
157 auto source = std::source_location::current();
158 std::string_view name2( source.function_name() );
159#else
160 #error "Not finished";
161#endif
162 // Try to get just the type of interest
163 if ( name2.find( "T = " ) != std::string::npos ) {
164 name2 = name2.substr( name2.find( "T = " ) + 4 );
165 if ( name2.find( ';' ) != std::string::npos )
166 name2 = name2.substr( 0, name2.find( ';' ) );
167 else
168 name2 = name2.substr( 0, name2.rfind( ']' ) );
169 }
170 if ( name2.find( "getTypeName<" ) != std::string::npos ) {
171 auto i1 = name2.find( "getTypeName<" );
172 auto i2 = name2.rfind( ">" );
173 name2 = name2.substr( i1 + 12, i2 - i1 - 12 );
174 }
175 if ( name2[0] == ' ' )
176 name2.remove_prefix( 1 );
177 // Copy the function name
178 name2 = name2.substr( 0, N - 1 );
179 for ( size_t i = 0; i < N; i++ )
180 name[i] = 0;
181 for ( size_t i = 0; i < std::min( name2.size(), N - 1 ); i++ )
182 name[i] = name2[i];
183 // Cleanup some common format issues to make the typeid more consistent
184 // clang-format off
185 name[N - 1] = 0;
186 replace( name, N, "class ", "" );
187 replace( name, N, "struct ", "" );
188 replace( name, N, "std::__cxx11::basic_string<char>", "std::string" );
189 replace( name, N, "std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>", "std::string" );
190 replace( name, N, "std::basic_string<char,struct std::char_traits<char>,class std::allocator<char>>", "std::string" );
191 replace( name, N, "std::__cxx11::basic_string_view<char>", "std::string_view" );
192 replace( name, N, "std::__cxx11::basic_string_view<char, std::char_traits<char>>", "std::string_view" );
193 replace( name, N, "std::basic_string_view<char,struct std::char_traits<char>>", "std::string_view" );
194 replace( name, N, "std::basic_string_view<char>", "std::string_view" );
195 replace( name, N, "std::basic_string_view<char, std::char_traits<char>>", "std::string_view" );
196 replace( name, N, "std::__debug::", "std::" );
197 replace( name, N, " *", "* " );
198 replace( name, N, " >", ">" );
199 replace( name, N, "* [", "*[" );
200 deblank( name, N );
201 // clang-format on
202 }
203}
204
205
206namespace AMP {
207
208
210struct alignas( 8 ) typeID {
211 uint32_t bytes = 0;
212 uint32_t hash = 0;
213 char name[120] = { 0 };
214 constexpr bool operator==( uint32_t rhs ) const { return hash == rhs; }
215 constexpr bool operator!=( uint32_t rhs ) const { return hash != rhs; }
216 constexpr bool operator==( const typeID &rhs ) const { return hash == rhs.hash; }
217 constexpr bool operator!=( const typeID &rhs ) const { return hash != rhs.hash; }
218};
219static_assert( sizeof( typeID ) == 128 );
220
221
223template<typename T0>
225{
226 using namespace TypeID_Helpers;
227 typeID id = {};
228 // Remove const/references
229 using T1 = typename std::remove_reference_t<T0>;
230 using T2 = typename std::remove_cv_t<T1>;
231 using T = typename std::remove_cv_t<T2>;
232 // Get the name of the class
233 char name[4096] = { 0 };
234 getTypeName<T>( sizeof( name ), name );
235 copy( id.name, name, sizeof( id.name ) );
236 // Create the hash
237 if ( name[0] != 0 )
238 id.hash = MurmurHash64A<sizeof( name )>( name );
239 // Set the size
240 id.bytes = sizeof( T );
241 return id;
242}
244template<typename TYPE>
245constexpr typeID getTypeID()
246{
247 constexpr auto id = getTypeIDEval<TYPE>();
248 static_assert( id != 0 );
249 return id;
250}
251
252
253} // namespace AMP
254
255#endif
constexpr typeID getTypeID()
Get the type info (does not resolve dynamic types)
Definition typeid.h:245
constexpr typeID getTypeIDEval()
Get the type info (does not resolve dynamic types)
Definition typeid.h:224
constexpr void replace(char *str, size_t N, std::string_view match, std::string_view replace)
Definition typeid.h:31
constexpr void copy(char *dst, const char *src, size_t N)
Definition typeid.h:22
constexpr void deblank(char *str, size_t N)
Definition typeid.h:54
constexpr uint64_t MurmurHash64A(const char *key)
Definition typeid.h:72
Class to store type info.
Definition typeid.h:210
constexpr bool operator==(const typeID &rhs) const
Definition typeid.h:216
char name[120]
Name of function (may be truncated, null-terminated)
Definition typeid.h:213
constexpr bool operator!=(uint32_t rhs) const
Definition typeid.h:215
uint32_t hash
Hash of function.
Definition typeid.h:212
uint32_t bytes
Size of object (bytes)
Definition typeid.h:211
constexpr bool operator!=(const typeID &rhs) const
Definition typeid.h:217
constexpr bool operator==(uint32_t rhs) const
Definition typeid.h:214
constexpr void getTypeName(uint64_t N, char *name)
Get the type name.
Definition typeid.h:112



Advanced Multi-Physics (AMP)
Oak Ridge National Laboratory
Idaho National Laboratory
Los Alamos National Laboratory
This page automatically produced from the
source code by doxygen
Last updated: Tue Mar 10 2026 13:06:41.
Comments on this page