fix ADL lookup error for to_string()-ing user-defined classes
fmt::to_string: use fmt::format() instead of format(), because otherwise unrelated free-standing format() function from the printed class namespace could be called. Example of the bug here: https://stackoverflow.com/q/62423981/19905 This commit includes a test as well. Applied against 6.2.1 because current fmt version seems to be broken at the moment for fmt::to_string()-ing user-defined classes.
This commit is contained in:
parent
19bd751020
commit
e8b47c3efb
@ -3336,14 +3336,14 @@ arg_join<internal::iterator_t<const Range>, wchar_t> join(const Range& range,
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename T> inline std::string to_string(const T& value) {
|
template <typename T> inline std::string to_string(const T& value) {
|
||||||
return format("{}", value);
|
return fmt::format("{}", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
||||||
*/
|
*/
|
||||||
template <typename T> inline std::wstring to_wstring(const T& value) {
|
template <typename T> inline std::wstring to_wstring(const T& value) {
|
||||||
return format(L"{}", value);
|
return fmt::format(L"{}", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, std::size_t SIZE>
|
template <typename Char, std::size_t SIZE>
|
||||||
|
|||||||
@ -2043,9 +2043,31 @@ TEST(FormatTest, DynamicFormatter) {
|
|||||||
"precision not allowed for this argument type");
|
"precision not allowed for this argument type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace unrelated {
|
||||||
|
|
||||||
|
struct qwe{};
|
||||||
|
|
||||||
|
std::string format(const char * /*fmt*/, const qwe &) {
|
||||||
|
// Return distinct string on purpose to check whether fmt used
|
||||||
|
// this format() via ADL by mistake
|
||||||
|
return "{unrelated free-standing format() function discovered by ADL by mistake}";
|
||||||
|
}
|
||||||
|
} // namespace unrelated
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<unrelated::qwe> {
|
||||||
|
template<typename ParseContext>
|
||||||
|
auto parse(ParseContext & ctx) -> decltype(ctx.begin()) { return ctx.begin(); }
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(const unrelated::qwe &, FormatContext & ctx) -> decltype(ctx.out()) {
|
||||||
|
return fmt::format_to(ctx.out(), "[qwe]");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TEST(FormatTest, ToString) {
|
TEST(FormatTest, ToString) {
|
||||||
EXPECT_EQ("42", fmt::to_string(42));
|
EXPECT_EQ("42", fmt::to_string(42));
|
||||||
EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234)));
|
EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234)));
|
||||||
|
EXPECT_EQ("[qwe]", fmt::to_string(unrelated::qwe{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user