Add `ContextProjection()`.

It adapts a field handler to depend on a part of the context. Makes a field
handler depending on some outer context parameters from a field handler
depending on inner context parameters.

`projection...` parameters are applied sequentially to transform the outer
context to the inner context. Each `projection` is an invocable which
returns either a reference or a tuple of references. Common projections
include `ContextAt<indices...>` to select a subset of context parameters,
or `&Context::member` to select a member of the context parameter.

PiperOrigin-RevId: 877765506
diff --git a/riegeli/messages/BUILD b/riegeli/messages/BUILD
index ac9b900..15c9dc2 100644
--- a/riegeli/messages/BUILD
+++ b/riegeli/messages/BUILD
@@ -171,6 +171,20 @@
 )
 
 cc_library(
+    name = "context_projection",
+    hdrs = ["context_projection.h"],
+    deps = [
+        ":serialized_message_reader_internal",
+        "//riegeli/base:cord_iterator_span",
+        "//riegeli/bytes:limiting_reader",
+        "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/base:nullability",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/strings:string_view",
+    ],
+)
+
+cc_library(
     name = "dynamic_field_handler",
     hdrs = ["dynamic_field_handler.h"],
     deps = [
diff --git a/riegeli/messages/context_projection.h b/riegeli/messages/context_projection.h
new file mode 100644
index 0000000..b68813f
--- /dev/null
+++ b/riegeli/messages/context_projection.h
@@ -0,0 +1,479 @@
+// Copyright 2026 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef RIEGELI_MESSAGES_CONTEXT_PROJECTION_H_
+#define RIEGELI_MESSAGES_CONTEXT_PROJECTION_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/nullability.h"
+#include "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "riegeli/base/cord_iterator_span.h"
+#include "riegeli/bytes/limiting_reader.h"
+#include "riegeli/messages/serialized_message_reader_internal.h"
+
+ABSL_POINTERS_DEFAULT_NONNULL
+
+namespace riegeli {
+
+// The type of `ContextAt<indices...>`.
+template <size_t... indices>
+struct ContextAtImpl;
+
+// A projection for `ContextProjection()` which selects a subset of context
+// parameters. The other context parameters are ignored.
+template <size_t... indices>
+constexpr ContextAtImpl<indices...> ContextAt = {};
+
+// The type returned by `ContextProjection()` with a single projection.
+template <auto projection, typename FieldHandler>
+class ContextProjectionImpl;
+
+// Adapts a field handler to depend on a part of the context. Makes a field
+// handler taking some outer context parameters from a field handler taking
+// inner context parameters.
+//
+// `projection...` parameters are applied sequentially to transform the outer
+// context to the inner context. Each `projection` is an invocable which
+// returns either a reference or a tuple of references. Common projections
+// include `ContextAt<indices...>` to select a subset of context parameters,
+// and `&Context::member` to select a member of the only context parameter.
+
+template <typename FieldHandler>
+constexpr FieldHandler&& ContextProjection(FieldHandler&& field_handler) {
+  return std::forward<FieldHandler>(field_handler);
+}
+
+template <auto projection, typename FieldHandler>
+constexpr ContextProjectionImpl<projection, std::decay_t<FieldHandler>>
+ContextProjection(FieldHandler&& field_handler) {
+  return ContextProjectionImpl<projection, std::decay_t<FieldHandler>>(
+      std::forward<FieldHandler>(field_handler));
+}
+
+template <auto first_projection, auto second_projection,
+          auto... rest_projections, typename FieldHandler>
+constexpr auto ContextProjection(FieldHandler&& field_handler) {
+  return ContextProjection<first_projection>(
+      ContextProjection<second_projection, rest_projections...>(
+          std::forward<FieldHandler>(field_handler)));
+}
+
+// Implementation details follow.
+
+namespace context_projection_internal {
+
+template <typename T>
+struct DecodeContextResult {};
+
+template <typename Context>
+struct DecodeContextResult<Context&>
+    : std::type_identity<std::tuple<Context&>> {};
+
+template <typename... Context>
+struct DecodeContextResult<std::tuple<Context&...>>
+    : std::type_identity<std::tuple<Context&...>> {};
+
+template <auto projection, typename... Context>
+struct InnerContextTuple
+    : DecodeContextResult<
+          std::invoke_result_t<decltype(projection), Context&...>> {};
+
+}  // namespace context_projection_internal
+
+template <size_t... indices>
+struct ContextAtImpl {
+  template <typename... Context>
+  std::tuple<std::tuple_element_t<indices, std::tuple<Context&...>>...>
+  operator()(Context&... context) const {
+    const std::tuple<Context&...> context_tuple = {context...};
+    return {std::get<indices>(context_tuple)...};
+  }
+};
+
+template <auto projection, typename FieldHandler>
+class ContextProjectionImpl {
+ private:
+  template <template <typename T, typename... InnerContext> class Predicate,
+            typename InnerContextTuple>
+  struct IsProjectedFieldHandlerImpl;
+
+  template <template <typename T, typename... InnerContext> class Predicate,
+            typename... InnerContext>
+  struct IsProjectedFieldHandlerImpl<Predicate, std::tuple<InnerContext&...>>
+      : Predicate<FieldHandler, InnerContext...> {};
+
+  template <template <typename T, typename... InnerContext> class Predicate,
+            typename... Context>
+  struct IsProjectedFieldHandler
+      : IsProjectedFieldHandlerImpl<
+            Predicate, typename context_projection_internal::InnerContextTuple<
+                           projection, Context...>::type> {};
+
+ public:
+  static constexpr int kFieldNumber = FieldHandler::kFieldNumber;
+
+  template <typename FieldHandlerInitializer,
+            std::enable_if_t<
+                std::is_convertible_v<FieldHandlerInitializer&&, FieldHandler>,
+                int> = 0>
+  explicit constexpr ContextProjectionImpl(
+      FieldHandlerInitializer&& field_handler)
+      : field_handler_(std::forward<FieldHandlerInitializer>(field_handler)) {}
+
+  ContextProjectionImpl(const ContextProjectionImpl& that) = default;
+  ContextProjectionImpl& operator=(const ContextProjectionImpl& that) = default;
+
+  ContextProjectionImpl(ContextProjectionImpl&& that) = default;
+  ContextProjectionImpl& operator=(ContextProjectionImpl&& that) = default;
+
+  template <
+      typename... Context,
+      std::enable_if_t<
+          IsProjectedFieldHandler<
+              serialized_message_reader_internal::IsStaticFieldHandlerForVarint,
+              Context...>::value,
+          int> = 0>
+  absl::Status HandleVarint(uint64_t repr, Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleVarint(repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename DependentFieldHandler = FieldHandler,
+            std::enable_if_t<serialized_message_reader_internal::
+                                 IsDynamicFieldHandlerForVarintSomeContext<
+                                     DependentFieldHandler>::value,
+                             int> = 0>
+  auto AcceptVarint(int field_number) const {
+    return field_handler_.AcceptVarint(field_number);
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsDynamicFieldHandlerForVarint,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleVarint(Accepted&& accepted, uint64_t repr,
+                                   Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleVarint(
+              std::forward<Accepted>(accepted), repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsStaticFieldHandlerForFixed32,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status HandleFixed32(uint32_t repr, Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleFixed32(repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename DependentFieldHandler = FieldHandler,
+            std::enable_if_t<serialized_message_reader_internal::
+                                 IsDynamicFieldHandlerForFixed32SomeContext<
+                                     DependentFieldHandler>::value,
+                             int> = 0>
+  auto AcceptFixed32(int field_number) const {
+    return field_handler_.AcceptFixed32(field_number);
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsDynamicFieldHandlerForFixed32,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleFixed32(Accepted&& accepted, uint32_t repr,
+                                    Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleFixed32(
+              std::forward<Accepted>(accepted), repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsStaticFieldHandlerForFixed64,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status HandleFixed64(uint64_t repr, Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleFixed64(repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename DependentFieldHandler = FieldHandler,
+            std::enable_if_t<serialized_message_reader_internal::
+                                 IsDynamicFieldHandlerForFixed64SomeContext<
+                                     DependentFieldHandler>::value,
+                             int> = 0>
+  auto AcceptFixed64(int field_number) const {
+    return field_handler_.AcceptFixed64(field_number);
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsDynamicFieldHandlerForFixed64,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleFixed64(Accepted&& accepted, uint64_t repr,
+                                    Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleFixed64(
+              std::forward<Accepted>(accepted), repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <
+      typename... Context,
+      std::enable_if_t<IsProjectedFieldHandler<
+                           serialized_message_reader_internal::
+                               IsStaticFieldHandlerForLengthDelimitedFromReader,
+                           Context...>::value,
+                       int> = 0>
+  absl::Status HandleLengthDelimitedFromReader(ReaderSpan<> repr,
+                                               Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleLengthDelimitedFromReader(
+              std::move(repr), inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <
+      typename... Context,
+      std::enable_if_t<IsProjectedFieldHandler<
+                           serialized_message_reader_internal::
+                               IsStaticFieldHandlerForLengthDelimitedFromCord,
+                           Context...>::value,
+                       int> = 0>
+  absl::Status HandleLengthDelimitedFromCord(CordIteratorSpan repr,
+                                             std::string& scratch,
+                                             Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleLengthDelimitedFromCord(
+              std::move(repr), scratch, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <
+      typename... Context,
+      std::enable_if_t<IsProjectedFieldHandler<
+                           serialized_message_reader_internal::
+                               IsStaticFieldHandlerForLengthDelimitedFromString,
+                           Context...>::value,
+                       int> = 0>
+  absl::Status HandleLengthDelimitedFromString(absl::string_view repr,
+                                               Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleLengthDelimitedFromString(
+              repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <
+      typename DependentFieldHandler = FieldHandler,
+      std::enable_if_t<serialized_message_reader_internal::
+                           IsDynamicFieldHandlerForLengthDelimitedSomeContext<
+                               DependentFieldHandler>::value,
+                       int> = 0>
+  auto AcceptLengthDelimited(int field_number) const {
+    return field_handler_.AcceptLengthDelimited(field_number);
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<
+                    serialized_message_reader_internal::
+                        IsDynamicFieldHandlerForLengthDelimitedFromReader,
+                    Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleLengthDelimitedFromReader(
+      Accepted&& accepted, ReaderSpan<> repr, Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleLengthDelimitedFromReader(
+              std::forward<Accepted>(accepted), std::move(repr),
+              inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <
+      typename Accepted, typename... Context,
+      std::enable_if_t<IsProjectedFieldHandler<
+                           serialized_message_reader_internal::
+                               IsDynamicFieldHandlerForLengthDelimitedFromCord,
+                           Context...>::value,
+                       int> = 0>
+  absl::Status DynamicHandleLengthDelimitedFromCord(Accepted&& accepted,
+                                                    CordIteratorSpan repr,
+                                                    std::string& scratch,
+                                                    Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleLengthDelimitedFromCord(
+              std::forward<Accepted>(accepted), std::move(repr), scratch,
+              inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<
+                    serialized_message_reader_internal::
+                        IsDynamicFieldHandlerForLengthDelimitedFromString,
+                    Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleLengthDelimitedFromString(
+      Accepted&& accepted, absl::string_view repr, Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleLengthDelimitedFromString(
+              std::forward<Accepted>(accepted), repr, inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsStaticFieldHandlerForStartGroup,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status HandleStartGroup(Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleStartGroup(inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename DependentFieldHandler = FieldHandler,
+            std::enable_if_t<serialized_message_reader_internal::
+                                 IsDynamicFieldHandlerForStartGroupSomeContext<
+                                     DependentFieldHandler>::value,
+                             int> = 0>
+  auto AcceptStartGroup(int field_number) const {
+    return field_handler_.AcceptStartGroup(field_number);
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsDynamicFieldHandlerForStartGroup,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleStartGroup(Accepted&& accepted,
+                                       Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleStartGroup(
+              std::forward<Accepted>(accepted), inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsStaticFieldHandlerForEndGroup,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status HandleEndGroup(Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.HandleEndGroup(inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+  template <typename DependentFieldHandler = FieldHandler,
+            std::enable_if_t<serialized_message_reader_internal::
+                                 IsDynamicFieldHandlerForEndGroupSomeContext<
+                                     DependentFieldHandler>::value,
+                             int> = 0>
+  auto AcceptEndGroup(int field_number) const {
+    return field_handler_.AcceptEndGroup(field_number);
+  }
+
+  template <typename Accepted, typename... Context,
+            std::enable_if_t<
+                IsProjectedFieldHandler<serialized_message_reader_internal::
+                                            IsDynamicFieldHandlerForEndGroup,
+                                        Context...>::value,
+                int> = 0>
+  absl::Status DynamicHandleEndGroup(Accepted&& accepted,
+                                     Context&... context) const {
+    return std::apply(
+        [&](auto&... inner_context) {
+          return field_handler_.DynamicHandleEndGroup(
+              std::forward<Accepted>(accepted), inner_context...);
+        },
+        InnerContext(context...));
+  }
+
+ private:
+  template <typename... Context>
+  static
+      typename context_projection_internal::InnerContextTuple<projection,
+                                                              Context...>::type
+      InnerContext(Context&... context) {
+    // If `projection` returns a reference, this returns a tuple with a single
+    // element. If `projection` returns a tuple of references, this returns the
+    // tuple while the braces are redundant.
+    return {std::invoke(projection, context...)};
+  }
+
+  ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS FieldHandler field_handler_;
+};
+
+}  // namespace riegeli
+
+#endif  // RIEGELI_MESSAGES_CONTEXT_PROJECTION_H_
diff --git a/riegeli/messages/serialized_message_reader_internal.h b/riegeli/messages/serialized_message_reader_internal.h
index 23e92a2..869c03a 100644
--- a/riegeli/messages/serialized_message_reader_internal.h
+++ b/riegeli/messages/serialized_message_reader_internal.h
@@ -149,6 +149,60 @@
         std::declval<Context&>()...))>,
     Context...> : std::true_type {};
 
+template <typename T, typename Enable = void>
+struct IsDynamicFieldHandlerForVarintSomeContext : std::false_type {};
+
+template <typename T>
+struct IsDynamicFieldHandlerForVarintSomeContext<
+    T, std::enable_if_t<std::is_constructible_v<
+           bool, decltype(std::declval<const T&>().AcceptVarint(
+                     std::declval<int>()))>>> : std::true_type {};
+
+template <typename T, typename Enable = void>
+struct IsDynamicFieldHandlerForFixed32SomeContext : std::false_type {};
+
+template <typename T>
+struct IsDynamicFieldHandlerForFixed32SomeContext<
+    T, std::enable_if_t<std::is_constructible_v<
+           bool, decltype(std::declval<const T&>().AcceptFixed32(
+                     std::declval<int>()))>>> : std::true_type {};
+
+template <typename T, typename Enable = void>
+struct IsDynamicFieldHandlerForFixed64SomeContext : std::false_type {};
+
+template <typename T>
+struct IsDynamicFieldHandlerForFixed64SomeContext<
+    T, std::enable_if_t<std::is_constructible_v<
+           bool, decltype(std::declval<const T&>().AcceptFixed64(
+                     std::declval<int>()))>>> : std::true_type {};
+
+template <typename T, typename Enable = void>
+struct IsDynamicFieldHandlerForLengthDelimitedSomeContext : std::false_type {};
+
+template <typename T>
+struct IsDynamicFieldHandlerForLengthDelimitedSomeContext<
+    T, std::enable_if_t<std::is_constructible_v<
+           bool, decltype(std::declval<const T&>().AcceptLengthDelimited(
+                     std::declval<int>()))>>> : std::true_type {};
+
+template <typename T, typename Enable = void>
+struct IsDynamicFieldHandlerForStartGroupSomeContext : std::false_type {};
+
+template <typename T>
+struct IsDynamicFieldHandlerForStartGroupSomeContext<
+    T, std::enable_if_t<std::is_constructible_v<
+           bool, decltype(std::declval<const T&>().AcceptStartGroup(
+                     std::declval<int>()))>>> : std::true_type {};
+
+template <typename T, typename Enable = void>
+struct IsDynamicFieldHandlerForEndGroupSomeContext : std::false_type {};
+
+template <typename T>
+struct IsDynamicFieldHandlerForEndGroupSomeContext<
+    T, std::enable_if_t<std::is_constructible_v<
+           bool, decltype(std::declval<const T&>().AcceptEndGroup(
+                     std::declval<int>()))>>> : std::true_type {};
+
 template <typename T, typename Enable, typename... Context>
 struct IsDynamicFieldHandlerForVarintImpl : std::false_type {};
 
@@ -156,9 +210,7 @@
 struct IsDynamicFieldHandlerForVarintImpl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<bool,
-                                decltype(std::declval<const T&>().AcceptVarint(
-                                    std::declval<int>()))>,
+        IsDynamicFieldHandlerForVarintSomeContext<T>::value,
         std::void_t<decltype(std::declval<const T&>().DynamicHandleVarint(
             *std::declval<const T&>().AcceptVarint(std::declval<int>()),
             std::declval<uint64_t>(), std::declval<Context&>()...))>>,
@@ -171,9 +223,7 @@
 struct IsDynamicFieldHandlerForFixed32Impl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<bool,
-                                decltype(std::declval<const T&>().AcceptFixed32(
-                                    std::declval<int>()))>,
+        IsDynamicFieldHandlerForFixed32SomeContext<T>::value,
         std::void_t<decltype(std::declval<const T&>().DynamicHandleFixed32(
             *std::declval<const T&>().AcceptFixed32(std::declval<int>()),
             std::declval<uint32_t>(), std::declval<Context&>()...))>>,
@@ -186,9 +236,7 @@
 struct IsDynamicFieldHandlerForFixed64Impl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<bool,
-                                decltype(std::declval<const T&>().AcceptFixed64(
-                                    std::declval<int>()))>,
+        IsDynamicFieldHandlerForFixed64SomeContext<T>::value,
         std::void_t<decltype(std::declval<const T&>().DynamicHandleFixed64(
             *std::declval<const T&>().AcceptFixed64(std::declval<int>()),
             std::declval<uint64_t>(), std::declval<Context&>()...))>>,
@@ -202,9 +250,7 @@
 struct IsDynamicFieldHandlerForLengthDelimitedFromReaderImpl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<
-            bool, decltype(std::declval<const T&>().AcceptLengthDelimited(
-                      std::declval<int>()))>,
+        IsDynamicFieldHandlerForLengthDelimitedSomeContext<T>::value,
         std::void_t<
             decltype(std::declval<const T&>()
                          .DynamicHandleLengthDelimitedFromReader(
@@ -221,9 +267,7 @@
 struct IsDynamicFieldHandlerForLengthDelimitedFromCordImpl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<
-            bool, decltype(std::declval<const T&>().AcceptLengthDelimited(
-                      std::declval<int>()))>,
+        IsDynamicFieldHandlerForLengthDelimitedSomeContext<T>::value,
         std::void_t<
             decltype(std::declval<const T&>()
                          .DynamicHandleLengthDelimitedFromCord(
@@ -242,9 +286,7 @@
 struct IsDynamicFieldHandlerForLengthDelimitedFromStringImpl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<
-            bool, decltype(std::declval<const T&>().AcceptLengthDelimited(
-                      std::declval<int>()))>,
+        IsDynamicFieldHandlerForLengthDelimitedSomeContext<T>::value,
         std::void_t<
             decltype(std::declval<const T&>()
                          .DynamicHandleLengthDelimitedFromString(
@@ -261,9 +303,7 @@
 struct IsDynamicFieldHandlerForStartGroupImpl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<
-            bool, decltype(std::declval<const T&>().AcceptStartGroup(
-                      std::declval<int>()))>,
+        IsDynamicFieldHandlerForStartGroupSomeContext<T>::value,
         std::void_t<decltype(std::declval<const T&>().DynamicHandleStartGroup(
             *std::declval<const T&>().AcceptStartGroup(std::declval<int>()),
             std::declval<Context&>()...))>>,
@@ -276,9 +316,7 @@
 struct IsDynamicFieldHandlerForEndGroupImpl<
     T,
     std::enable_if_t<
-        std::is_constructible_v<
-            bool, decltype(std::declval<const T&>().AcceptEndGroup(
-                      std::declval<int>()))>,
+        IsDynamicFieldHandlerForEndGroupSomeContext<T>::value,
         std::void_t<decltype(std::declval<const T&>().DynamicHandleEndGroup(
             *std::declval<const T&>().AcceptEndGroup(std::declval<int>()),
             std::declval<Context&>()...))>>,