From e0e9e73e41a6c92c44609cc85969549e94df34ee Mon Sep 17 00:00:00 2001 From: Chris Sarbora Date: Sun, 3 Dec 2023 21:03:55 -0800 Subject: [PATCH] Avoid using RTTI for list tests when possible With Clang, GCC and MSVC, we can generate the typename using compiler macros and some string manipulation. Where this is possible, we will use this instead of RTTI. Where it is not, we will fall back to RTTI and/or index-based default typename string generation. Special thanks to Corentin Schreiber (cschreib@strw.leidenuniv.nl) for the inspiration here. --- .../internal/catch_template_test_registry.hpp | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/catch2/internal/catch_template_test_registry.hpp b/src/catch2/internal/catch_template_test_registry.hpp index 85074fff38..aaec19cda7 100644 --- a/src/catch2/internal/catch_template_test_registry.hpp +++ b/src/catch2/internal/catch_template_test_registry.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #if defined(CATCH_CONFIG_USE_RTTI) || (defined(CATCH_INTERNAL_RTTI_SUPPORTED) && !defined(CATCH_INTERNAL_USE_NO_RTTI)) @@ -353,6 +354,33 @@ namespace Catch { template struct IndexedTestTypeName { std::string operator()(size_t index) const { +#if defined(CATCH_CONFIG_CPP17_STRING_VIEW) || !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) + #if defined(__clang__) + constexpr auto prefix = std::string_view{"[T = "}; + constexpr auto suffix = "]"; + constexpr auto function = std::string_view{__PRETTY_FUNCTION__}; + #elif defined(__GNUC__) + constexpr auto prefix = std::string_view{"with T = "}; + constexpr auto suffix = "; "; + constexpr auto function = std::string_view{__PRETTY_FUNCTION__}; + #elif defined(_MSC_VER) + constexpr auto prefix = std::string_view{"get_type_name<"}; + constexpr auto suffix = ">(size_t)"; + constexpr auto function = std::string_view{__FUNCSIG__}; + #else + constexpr std::string_view prefix; + constexpr std::string_view suffix; + constexpr std::string_view function; + if (false) // make sure we don't execute this substr block immediately below + #endif + { + const auto start = function.find(prefix) + prefix.size(); + const auto end = function.find(suffix, start); + const auto size = end - start; + return std::string{function.substr(start, size)}; + } +#endif + #if defined(CATCH_INTERNAL_USE_RTTI) const char* name = typeid(T).name(); int status = 0; @@ -361,9 +389,9 @@ namespace Catch { return demangled.get(); } #endif - return std::to_string(index); + return Catch::to_string(index); } }; -} +} // namespace Catch #endif // CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED