-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Open
Description
Describe the issue
If both AbslStringify and AbslFormatConvert are defined for a custom type (https://abseil.io/docs/cpp/guides/format#user-defined-formats), compilation fails when calling StrFormat.
For example, given
struct Point {
template <typename Sink>
friend void AbslStringify(Sink& sink, const Point& p) {
absl::Format(&sink, "(%d, %d)", p.x, p.y);
}
friend absl::FormatConvertResult<absl::FormatConversionCharSet::v>
AbslFormatConvert(const Point& p,
const absl::FormatConversionSpec& spec,
absl::FormatSink* s) {
absl::Format(s, "(%d, %d)", p.x, p.y);
return {true};
}
int x;
int y;
};
TEST(CustomStringify, Works) {
EXPECT_EQ(absl::StrFormat("%v", Point{1, 2}), "(1, 2)");
}compilation fails with
external/abseil-cpp+/absl/strings/internal/str_format/arg.h:426:31: error: call to 'FormatConvertImpl' is ambiguous
426 | using ConvResult = decltype(str_format_internal::FormatConvertImpl(
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
external/abseil-cpp+/absl/strings/str_format.h:281:26: note: in instantiation of function template specialization 'absl::str_format_internal::ArgumentToConv<Point>' requested here
281 | str_format_internal::ArgumentToConv<Args>()...>;
| ^
external/abseil-cpp+/absl/strings/str_format.h:362:43: note: in instantiation of template type alias 'FormatSpec' requested here
362 | [[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,
| ^
test.cc:35:13: note: while substituting deduced template arguments into function template 'StrFormat' [with Args = <Point>]
35 | EXPECT_EQ(absl::StrFormat("%v", Point{1, 2}), "(1, 2)");
| ^
external/abseil-cpp+/absl/strings/internal/str_format/arg.h:130:6: note: candidate function [with T = Point]
130 | auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
| ^
external/abseil-cpp+/absl/strings/internal/str_format/arg.h:164:6: note: candidate function [with T = Point]
164 | auto FormatConvertImpl(const T& v, FormatConversionSpecImpl,
| ^
test.cc:35:13: error: no matching function for call to 'StrFormat'
35 | EXPECT_EQ(absl::StrFormat("%v", Point{1, 2}), "(1, 2)");
| ^~~~~~~~~~~~~~~
I would expect that this compiles and prefers AbslFormatConvert over AbslStringify (while StrCat and GoogleTest would ignore AbslFormatConvert).
Steps to reproduce the problem
MODULE.bazel:
bazel_dep(name = "rules_cc", version = "0.2.9")
bazel_dep(name = "googletest", version = "1.17.0.bcr.1")
bazel_dep(name = "abseil-cpp", version = "20250814.1")
BUILD.bazel:
load("@rules_cc//cc:cc_test.bzl", "cc_test")
cc_test(
name = "test",
srcs = ["test.cc"],
deps = [
"@abseil-cpp//absl/strings:str_format",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
test.cc:
#include <string>
#include "absl/strings/str_format.h"
#include "gtest/gtest.h"
struct Point {
template <typename Sink>
friend void AbslStringify(Sink& sink, const Point& p) {
absl::Format(&sink, "(%d, %d)", p.x, p.y);
}
friend absl::FormatConvertResult<absl::FormatConversionCharSet::v>
AbslFormatConvert(const Point& p,
const absl::FormatConversionSpec& spec,
absl::FormatSink* s) {
absl::Format(s, "(%d, %d)", p.x, p.y);
return {true};
}
int x;
int y;
};
TEST(CustomStringify, Works) {
EXPECT_EQ(absl::StrFormat("%v", Point{1, 2}), "(1, 2)");
}.bazelrc:
build --define=absl=1
What version of Abseil are you using?
20250814.1
What operating system and version are you using?
macOS Tahoe
What compiler and version are you using?
Apple clang version 17.0.0 (clang-1700.3.19.1)
What build system are you using?
bazel 8.4.2
Additional context
No response
Metadata
Metadata
Assignees
Labels
No labels