Easys
A minimalist, header-only C++ ECS library for efficient and fuss-free entity and component management.
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdio>
4#include <string>
5#include <string_view>
6#include <type_traits>
7#include <typeinfo>
8
9namespace {
10#if defined(__GNUG__) || defined(__clang__)
11#include <cxxabi.h>
12
13#include <cstdlib>
14#endif
15
16// get a compiler-provided type name (no UB)
17template <typename T>
18std::string_view raw_type_name()
19{
20#if defined(__clang__)
21 // std::string_view raw_type_name() [T = Foo]
22 std::string_view p = __PRETTY_FUNCTION__;
23 auto start = p.find("T = ") + 4;
24 auto end = p.rfind(']');
25 return p.substr(start, end - start);
26
27#elif defined(__GNUC__)
28 // std::string_view raw_type_name() [with T = Foo; ...]
29 std::string_view p = __PRETTY_FUNCTION__;
30 auto start = p.find("T = ") + 4;
31 auto end = p.find(';', start);
32 return p.substr(start, end - start);
33
34#elif defined(_MSC_VER)
35 // class std::basic_string_view<...> __cdecl raw_type_name<Foo>(void)
36 std::string_view p = __FUNCSIG__;
37 auto start = p.find("raw_type_name<") + 14;
38 auto end = p.find(">(void)", start);
39 return p.substr(start, end - start);
40
41#else
42 return typeid(T).name();
43#endif
44}
45
46// demangle if needed (mainly MSVC / fallback)
47inline std::string demangle(std::string_view sv)
48{
49#if defined(__GNUG__) || defined(__clang__)
50 int status = 0;
51 char* p = abi::__cxa_demangle(sv.data(), nullptr, nullptr, &status);
52 std::string result = (status == 0 && p) ? p : std::string(sv);
53 std::free(p);
54 return result;
55#else
56 return std::string(sv);
57#endif
58}
59
60// Helper to print a prettier type name
61template <typename T>
62const char* type_name()
63{
64 // static std::string name = normalize_type_name(raw_type_name<T>());
65 static std::string name = std::string(demangle(raw_type_name<T>()));
66 return name.c_str();
67}
68}; // namespace
69
70namespace Easys {
87template <typename... Ts>
88void checkComponentTraits(bool verbose = false)
89{
90 (
91 [&]()
92 {
93 using T = Ts;
94 printf("\n=== Checking component: %s ===\n", type_name<T>());
95
96 // Memory layout and copying
97 printf(" Size: %zu bytes, Alignment: %zu\n", sizeof(T), alignof(T));
98
99 if (verbose)
100 {
101 printf(" is_trivial: %s\n", std::is_trivial_v<T> ? "yes" : "no");
102 printf(" is_trivially_copyable: %s\n", std::is_trivially_copyable_v<T> ? "yes" : "no");
103 printf(" is_trivially_destructible: %s\n", std::is_trivially_destructible_v<T> ? "yes" : "no");
104
105 // Construction/destruction
106 printf(" is_default_constructible: %s\n", std::is_default_constructible_v<T> ? "yes" : "no");
107 printf(" is_nothrow_default_constructible: %s\n",
108 std::is_nothrow_default_constructible_v<T> ? "yes" : "no");
109 printf(" is_nothrow_copy_constructible: %s\n", std::is_nothrow_copy_constructible_v<T> ? "yes" : "no");
110 printf(" is_nothrow_move_constructible: %s\n", std::is_nothrow_move_constructible_v<T> ? "yes" : "no");
111 printf(" is_nothrow_destructible: %s\n", std::is_nothrow_destructible_v<T> ? "yes" : "no");
112
113 // Assignment
114 printf(" is_copy_assignable: %s\n", std::is_copy_assignable_v<T> ? "yes" : "no");
115 printf(" is_move_assignable: %s\n", std::is_move_assignable_v<T> ? "yes" : "no");
116 printf(" is_nothrow_copy_assignable: %s\n", std::is_nothrow_copy_assignable_v<T> ? "yes" : "no");
117 printf(" is_nothrow_move_assignable: %s\n", std::is_nothrow_move_assignable_v<T> ? "yes" : "no");
118
119 // Other important traits
120 printf(" is_empty: %s (can use empty base optimization)\n", std::is_empty_v<T> ? "yes" : "no");
121 printf(" is_standard_layout: %s (memcpy safe)\n", std::is_standard_layout_v<T> ? "yes" : "no");
122 printf(" is_pod (deprecated): %s\n", std::is_pod_v<T> ? "yes" : "no");
123 printf(" has_unique_object_representations: %s (hashing)\n",
124 std::has_unique_object_representations_v<T> ? "yes" : "no");
125
126 // For tagged components
127 printf(" is_final: %s\n", std::is_final_v<T> ? "yes" : "no");
128
129 // Check if type is suitable for memcpy
130 constexpr bool can_memcpy = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
131 printf(" Can use memcpy for bulk operations: %s\n", can_memcpy ? "yes" : "no");
132 }
133
134 // Summary for quick reading
135 constexpr bool optimal_for_ecs = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>
136 && std::is_nothrow_move_constructible_v<T>
137 && std::is_nothrow_move_assignable_v<T>
138 && std::is_default_constructible_v<T>;
139 printf(" Optimal for ECS: %s\n", optimal_for_ecs ? "YES" : "NO");
140
141 if (!optimal_for_ecs)
142 {
143 printf(" WARNING: This component may have performance overhead!\n");
144 }
145 }(),
146 ...);
147}
148}; // namespace Easys
Definition ecs.hpp:14
void checkComponentTraits(bool verbose=false)
Validates component types for ECS (Entity Component System) compatibility and performance.
Definition utils.hpp:88