Conversation
- Added std::type_info formatter;
- Reused std::type_info formatter in std::exception formatters;
- Updated MSVC std::type_info outputting to exclude all class, struct and enum occurences.
|
Ok still WIP in order to support |
75cdef1 to
ce222b5
Compare
|
Update: removed union occurrences as well for MSVC |
cb58b68 to
7c74917
Compare
|
I think formatting Before your changes, |
Note that prior to my changes, the
I think we can output the characters one by one while jumping over the occurrences instead of using a I do wonder whether I could erronously strip part of the actual identifier, instead of language keywords. All of the patterns do contain a space character that should prevent this. MSVC does not seem to use spaces before and after |
|
Suggested changes Create function: namespace detail {
template <typename Char, typename OutputIt>
auto write_demangled_name(OutputIt out,
std::type_info& ti) -> OutputIt {
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
int status = 0;
std::size_t size = 0;
std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
string_view demangled_name_view;
if (demangled_name_ptr) {
demangled_name_view = demangled_name_ptr.get();
// Normalization of stdlib inline namespace names.
// libc++ inline namespaces.
// std::__1::* -> std::*
// std::__1::__fs::* -> std::*
// libstdc++ inline namespaces.
// std::__cxx11::* -> std::*
// std::filesystem::__cxx11::* -> std::filesystem::*
if (demangled_name_view.starts_with("std::")) {
char* begin = demangled_name_ptr.get();
char* to = begin + 5; // std::
for (char *from = to, *end = begin + demangled_name_view.size();
from < end;) {
// This is safe, because demangled_name is NUL-terminated.
if (from[0] == '_' && from[1] == '_') {
char* next = from + 1;
while (next < end && *next != ':') next++;
if (next[0] == ':' && next[1] == ':') {
from = next + 2;
continue;
}
}
*to++ = *from++;
}
demangled_name_view = {begin, detail::to_unsigned(to - begin)};
}
} else {
demangled_name_view = string_view(ti.name());
}
return detail::write_bytes<Char>(out, demangled_name_view);
# elif FMT_MSC_VERSION
std::string demangled_name(ti.name());
details::remove_all_substrings(demangled_name, "class ");
details::remove_all_substrings(demangled_name, "enum ");
details::remove_all_substrings(demangled_name, "struct ");
details::remove_all_substrings(demangled_name, "union ");
return detail::write_bytes<Char>(out, demangled_name);
# else
return detail::write_bytes<Char>(out, string_view(ti.name()));
# endif
}
}and reuse it in formatters. We don't need to use |
Out of scope improvements:
|
|
LGTM |
55387ae to
3bf8a0b
Compare
include/fmt/std.h
Outdated
| #else | ||
| out = detail::write_bytes<Char>(out, string_view("std::exception")); | ||
| #endif |
There was a problem hiding this comment.
I am sorry :(
It was my mistake.
#else code will never execute if FMT_USE_RTTI is disabled, because with_typename_ = FMT_USE_RTTI != 0; in parse() function.
More correct variant is remove this #else block and move #endif after return detail::write_bytes<Char>(out, string_view(ex.what()));
This was before PR.
I'm sorry.
There was a problem hiding this comment.
Wouldn't it be more clear to do something like the below instead:
#if FMT_USE_RTTI
if (with_typename_) {
out = detail::write_demangled_name<Char>(out, typeid(ex));
*out++ = ':';
*out++ = ' ';
}
#endif
return detail::write_bytes<Char>(out, string_view(ex.what()));?
There was a problem hiding this comment.
Overall looks good but please a test case for the new formatter.
|
It is actually implicitly tested already via the exception formatter. |
| TEST(std_test, type_info) { | ||
| EXPECT_EQ(fmt::format("{}", typeid(std::runtime_error)), | ||
| "std::runtime_error"); | ||
| } |
There was a problem hiding this comment.
I think this should be wrapped in FMT_USE_RTTI check.
There was a problem hiding this comment.
Note
EXPECT_EQ("std::runtime_error: Test Exception", fmt::format("{:t}", ex));
EXPECT_THAT(fmt::format("{:t}", ex), StartsWith("std::system_error: "));
EXPECT_THAT(fmt::format("{:t}", ex),
StartsWith("std::filesystem::filesystem_error: "));
None of these tests would succeed without FMT_USE_RTTI, which is not used as guard in std-test.cc.
* Added std::type_info formatter; * Reused std::type_info formatter in std::exception formatters; * Updated MSVC std::type_info outputting to exclude all class, struct and enum occurences.