Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utility: make type_name more reliable #31

Merged
merged 2 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion awlib/include/aw/config/msvc.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Not a bug: all of compiler_setup headers have the same include guard
#ifndef aw_compiler_setup_2
#define aw_compiler_setup_2
#define AW_COMPILER AW_COMPILER_MVSC
#define AW_COMPILER AW_COMPILER_MSVC
#define AW_CVER_X _MSC_VER

#if defined(_M_X64)
Expand Down
7 changes: 7 additions & 0 deletions platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,10 @@ target_link_libraries(awplatform
PRIVATE
awalgo
awutils)

if (WIN32)
target_link_libraries(awplatform
PRIVATE
DbgHelp
)
endif()
3 changes: 2 additions & 1 deletion platform/demangle.c++
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ std::string demangle(const char* name)
return name;
}
} // namespace aw
#elif (AW_COMPILER == AW_COMPILER_MSVC)
#elif (AW_COMPILER == AW_COMPILER_MSVC) || (AW_COMPILER == AW_COMPILER_CLANG_CL)
#include <vector>
#include <aw/platform/windows.h>
#include <dbghelp.h>
#undef UnDecorateSymbolName
namespace aw {
Expand Down
13 changes: 8 additions & 5 deletions utility/include/aw/utility/type_name.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@

#include <aw/config.h>

namespace aw {
template<typename T>
static constexpr string_view compiler_string()
static constexpr std::string_view aw_type_string()
{
return AW_FUNCTION_SIGNATURE;
}

namespace aw {
class type_name_helper {
static constexpr size_t full_size = compiler_string<void>().size();
static constexpr size_t full_size = aw_type_string<void>().size();
static constexpr size_t name_size = string_view("void").size();
static constexpr size_t prefix_size = compiler_string<void>().find("void");
static constexpr size_t prefix_size = aw_type_string<void>().find("void");
static constexpr size_t suffix_size = full_size - prefix_size - name_size;

public:
Expand All @@ -49,13 +49,16 @@ struct type_name
{
constexpr static std::string_view name()
{
return type_name_helper::extract_name(compiler_string<T>());
return type_name_helper::extract_name(aw_type_string<T>());
}

using type = T;
constexpr static std::string_view value = name();
};

template<typename T>
constexpr std::string_view type_name_v = type_name<T>::value;

} // namespace aw

#endif // aw_utility_type_name_h
56 changes: 48 additions & 8 deletions utility/tests/type_name.c++
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,64 @@ TestFile( "type_name" );
using namespace std::string_view_literals;

namespace aw {
// doesn't give details
//static_assert( type_name<void>::value == "void"sv );
static_assert( type_name<void>::value == "void"sv );
static_assert( type_name<int>::value == "int"sv );

Test(type_name_basic)
namespace test {
struct empty {};
} // namespace test

Test(type_name_inside_aw)
{
TestEqual( type_name<void>::value, "void"sv );
TestEqual( type_name<int>::value, "int"sv );
TestEqual( type_name<test::empty>::value, "aw::test::empty"sv );
}
} // namespace aw

#if 0 // doesn't work reliably
namespace test {
struct empty {};
} // namespace test

Test(type_name_classes)
Test(type_name_outside_aw)
{
TestEqual( type_name<test::empty>::value, "aw::test::empty"sv );
TestEqual( aw::type_name<void>::value, "void"sv );
TestEqual( aw::type_name<int>::value, "int"sv );
TestEqual( aw::type_name<aw::test::empty>::value, "aw::test::empty"sv );
TestEqual( aw::type_name<::test::empty>::value, "test::empty"sv );
}
#endif

} // namespace aw
class test_class {};

namespace test {
template<typename T>
std::string_view type_name2()
{
return aw::type_name<T>::value;
}

class registrar {
public:
template<typename T>
void do_register()
{
name = type_name2<T>();
}

std::string_view name;
};
} // namespace test

Test(type_name_called_from_template)
{
TestEqual( test::type_name2<test::empty>(), "test::empty"sv );
TestEqual( test::type_name2<test_class>(), "test_class"sv );

test::registrar r;
r.do_register<int>();
TestEqual( r.name, "int"sv );
r.do_register<test_class>();
TestEqual( r.name, "test_class"sv );
r.do_register<test::empty>();
TestEqual( r.name, "test::empty"sv );
}
Loading