From 0eb5ac542531d897646caa04a0ceec564772df3c Mon Sep 17 00:00:00 2001 From: Samuel Benzaquen Date: Fri, 13 May 2022 14:50:25 -0700 Subject: Improve compiler errors for mismatched ParsedFormat inputs. PiperOrigin-RevId: 448582508 Change-Id: I67fbff5f42a083e093ea2c20749e073ca03feb0b --- absl/strings/BUILD.bazel | 1 + absl/strings/CMakeLists.txt | 1 + absl/strings/internal/str_format/bind.h | 42 ++++++++++++++++++++++++++++----- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 1cf58ca1..e9092165 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -1116,6 +1116,7 @@ cc_library( "//absl/numeric:representation", "//absl/types:optional", "//absl/types:span", + "//absl/utility", ], ) diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index c4358a12..a1b8d6ed 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -414,6 +414,7 @@ absl_cc_library( absl::core_headers absl::numeric_representation absl::type_traits + absl::utility absl::int128 absl::span ) diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h index b26cff66..dcaa5dd0 100644 --- a/absl/strings/internal/str_format/bind.h +++ b/absl/strings/internal/str_format/bind.h @@ -25,6 +25,7 @@ #include "absl/strings/internal/str_format/checker.h" #include "absl/strings/internal/str_format/parser.h" #include "absl/types/span.h" +#include "absl/utility/utility.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -87,6 +88,36 @@ class FormatSpecTemplate : public MakeDependent::type { using Base = typename MakeDependent::type; + template + struct ErrorMaker { + constexpr bool operator()(int) const { return res; } + }; + + template + static constexpr bool CheckArity(ErrorMaker SpecifierCount = {}, + ErrorMaker ParametersPassed = {}) { + static_assert(SpecifierCount(i) == ParametersPassed(j), + "Number of arguments passed must match the number of " + "conversion specifiers."); + return true; + } + + template + static constexpr bool CheckMatch( + ErrorMaker MismatchedArgumentNumber = {}) { + static_assert(MismatchedArgumentNumber(arg), + "Passed argument must match specified format."); + return true; + } + + template + static bool CheckMatches(absl::index_sequence) { + bool res[] = {true, CheckMatch()...}; + (void)res; + return true; + } + public: #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER @@ -133,13 +164,12 @@ class FormatSpecTemplate #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - template < - FormatConversionCharSet... C, - typename = typename std::enable_if::type, - typename = typename std::enable_if::type> + template FormatSpecTemplate(const ExtendedParsedFormat& pc) // NOLINT - : Base(&pc) {} + : Base(&pc) { + CheckArity(); + CheckMatches(absl::make_index_sequence{}); + } }; class Streamable { -- cgit v1.2.3