mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Allows absl::StrFormat to accept types which implement AbslStringify()
PiperOrigin-RevId: 477507777 Change-Id: I5ecde3163ca560ac8774034e55654774e36ad230
This commit is contained in:
committed by
Copybara-Service
parent
6d9ea2b46f
commit
f7404cd33f
@@ -45,6 +45,11 @@ class FormatConversionSpec;
|
||||
|
||||
namespace str_format_internal {
|
||||
|
||||
template <FormatConversionCharSet C>
|
||||
struct ArgConvertResult {
|
||||
bool value;
|
||||
};
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct HasUserDefinedConvert : std::false_type {};
|
||||
|
||||
@@ -71,6 +76,20 @@ auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
|
||||
return AbslFormatConvert(v, fcs, &fs);
|
||||
}
|
||||
|
||||
void AbslStringify(); // Stops the lexical name lookup
|
||||
template <typename T>
|
||||
auto FormatConvertImpl(const T& v, FormatConversionSpecImpl,
|
||||
FormatSinkImpl* sink)
|
||||
-> std::enable_if_t<std::is_void<decltype(AbslStringify(
|
||||
std::declval<FormatSink&>(), v))>::value,
|
||||
ArgConvertResult<FormatConversionCharSetInternal::v>> {
|
||||
using FormatSinkT =
|
||||
absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
|
||||
auto fs = sink->Wrap<FormatSinkT>();
|
||||
AbslStringify(fs, v);
|
||||
return {true};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class StreamedWrapper;
|
||||
|
||||
@@ -95,11 +114,6 @@ struct VoidPtr {
|
||||
uintptr_t value;
|
||||
};
|
||||
|
||||
template <FormatConversionCharSet C>
|
||||
struct ArgConvertResult {
|
||||
bool value;
|
||||
};
|
||||
|
||||
template <FormatConversionCharSet C>
|
||||
constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
|
||||
return C;
|
||||
@@ -316,11 +330,11 @@ struct FormatArgImplFriend {
|
||||
|
||||
template <typename Arg>
|
||||
constexpr FormatConversionCharSet ArgumentToConv() {
|
||||
return absl::str_format_internal::ExtractCharSet(
|
||||
decltype(str_format_internal::FormatConvertImpl(
|
||||
std::declval<const Arg&>(),
|
||||
std::declval<const FormatConversionSpecImpl&>(),
|
||||
std::declval<FormatSinkImpl*>())){});
|
||||
using ConvResult = decltype(str_format_internal::FormatConvertImpl(
|
||||
std::declval<const Arg&>(),
|
||||
std::declval<const FormatConversionSpecImpl&>(),
|
||||
std::declval<FormatSinkImpl*>()));
|
||||
return absl::str_format_internal::ExtractCharSet(ConvResult{});
|
||||
}
|
||||
|
||||
// A type-erased handle to a format argument.
|
||||
|
||||
@@ -1074,7 +1074,8 @@ using FormatExtensionTest = ::testing::Test;
|
||||
|
||||
struct Point {
|
||||
friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
|
||||
absl::FormatConversionCharSet::kIntegral>
|
||||
absl::FormatConversionCharSet::kIntegral |
|
||||
absl::FormatConversionCharSet::v>
|
||||
AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
|
||||
absl::FormatSink* s) {
|
||||
if (spec.conversion_char() == absl::FormatConversionChar::s) {
|
||||
@@ -1093,6 +1094,7 @@ TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
|
||||
Point p;
|
||||
EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
|
||||
EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
|
||||
EXPECT_EQ(absl::StrFormat("a %v z", p), "a 10,20 z");
|
||||
|
||||
// Typed formatting will fail to compile an invalid format.
|
||||
// StrFormat("%f", p); // Does not compile.
|
||||
@@ -1101,6 +1103,21 @@ TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
|
||||
// FormatUntyped will return false for bad character.
|
||||
EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
|
||||
}
|
||||
|
||||
struct PointStringify {
|
||||
template <typename FormatSink>
|
||||
friend void AbslStringify(FormatSink& sink, const PointStringify& p) {
|
||||
sink.Append(absl::StrCat("(", p.x, ", ", p.y, ")"));
|
||||
}
|
||||
|
||||
double x = 10.0;
|
||||
double y = 20.0;
|
||||
};
|
||||
|
||||
TEST_F(FormatExtensionTest, AbslStringifyExample) {
|
||||
PointStringify p;
|
||||
EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Some codegen thunks that we can use to easily dump the generated assembly for
|
||||
|
||||
Reference in New Issue
Block a user