Skip to content

Add target() to executor_ref and execution_context#154

Merged
sgerbino merged 1 commit intocppalliance:developfrom
sgerbino:pr/target
Feb 12, 2026
Merged

Add target() to executor_ref and execution_context#154
sgerbino merged 1 commit intocppalliance:developfrom
sgerbino:pr/target

Conversation

@sgerbino
Copy link
Collaborator

@sgerbino sgerbino commented Feb 12, 2026

Replace executor_ref::type_id() with a type-safe target() accessor modeled after std::any_cast. Add the same target() API to execution_context for downcasting to a derived context type. Add corresponding unit tests for both classes.

Summary by CodeRabbit

  • New Features
    • Introduced runtime type identification and type-safe downcasting capabilities for execution contexts and executor references, enabling safe discovery and access to underlying implementations without unsafe casts.
    • Enhanced service resolution with support for keyed type lookups, providing more granular and type-aware service discovery mechanisms.

Replace executor_ref::type_id() with a type-safe target<T>()
accessor modeled after std::any_cast. Add the same target<T>()
API to execution_context for downcasting to a derived context
type. Add corresponding unit tests for both classes.
@coderabbitai
Copy link

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

Added per-instance type identification and downcasting capabilities to execution contexts and executor references. Introduced ti_ type-info pointers and template target<T>() methods for safe type checking and retrieval of concrete types from type-erased wrappers.

Changes

Cohort / File(s) Summary
Execution Context Type Identification
include/boost/capy/ex/execution_context.hpp
Added per-instance type tracking via ti_ member pointer, protected constructor to capture derived type info, public target<ExecutionContext>() template methods for safe downcasting, and get_key template specialization for keyed service lookups.
Executor Reference Downcasting
include/boost/capy/ex/executor_ref.hpp
Replaced public type_id() method with parameterized target<Executor>() template accessors that check type compatibility and return typed pointers to the underlying executor, or nullptr on mismatch.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related PRs

  • various #130: Adds the vtable's type_id field and type_id() accessor that directly supports the per-instance type identification mechanism introduced in this PR.

Poem

🐰 Downcasting dreams with type-id gleams,
No more opaque, just match the scheme—
target() calls, the truth unfolds,
Concrete types, no secrets held!
Safe pointers dance, the pattern's blessed.

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding target() methods to both executor_ref and execution_context classes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@include/boost/capy/ex/executor_ref.hpp`:
- Around line 273-280: The non-const target() in executor_ref exposes a
const_cast that can yield UB when executor_ref was constructed from an Ex
const&, so remove the mutable overload to ensure executor_ref only provides a
const view: delete the template< typename Executor> Executor* target() that
returns const_cast of ex_, leaving (or adding) only a const overload returning
Executor const*; update any references/docs/comments for executor_ref, target(),
vt_->type_id and ex_ to reflect that callers must not obtain a mutable pointer
from executor_ref (or alternatively add a prominent `@warning` in the header if
you prefer the documented-but-unsafe behavior).
🧹 Nitpick comments (6)
include/boost/capy/ex/executor_ref.hpp (2)

264-270: Mark target() as noexcept.

All operations inside (*vt_->type_id, comparison, static_cast) are non-throwing, and the analogous std::any_cast on pointers is also noexcept. Both overloads should be marked noexcept for consistency with the model and to allow callers to rely on the no-throw guarantee.

Proposed fix
     template< typename Executor >
-    const Executor* target() const
+    const Executor* target() const noexcept
     {

And similarly for the non-const overload:

     template< typename Executor>
-    Executor* target()
+    Executor* target() noexcept
     {

251-263: Documentation is missing @par Example and @see sections.

Per the coding guidelines for function javadocs in headers, include @par Example with a @code block showing typical usage (e.g., checking and downcasting), and @see at the end cross-referencing related types like execution_context::target, any_executor, or std::any_cast.

As per coding guidelines, "Include @par Example in function javadocs with one or more @code blocks" and "Include @see in function javadocs (always last) for related functions, types, and concepts".

include/boost/capy/ex/execution_context.hpp (4)

437-452: Mark target() overloads as noexcept.

Same as executor_ref::target() — all operations (null check, type_info comparison, static_cast) are non-throwing. Marking these noexcept is consistent with std::any_cast on pointers.

Proposed fix
     template< typename ExecutionContext >
-    const ExecutionContext* target() const
+    const ExecutionContext* target() const noexcept
     {
     template< typename ExecutionContext >
-    ExecutionContext* target()
+    ExecutionContext* target() noexcept
     {

99-101: Protected constructor lacks documentation.

This constructor is part of the protected API that derived classes must use to enable target(). A brief docstring explaining its purpose, the Derived* parameter (used only for type deduction), and the postcondition (target<Derived>() will succeed) would help derived-class authors.

As per coding guidelines, "Docstrings are required for all classes and functions in public headers in non-detail namespaces."


424-436: Documentation is missing @par Example and @see sections.

Same as executor_ref::target() — the coding guidelines require examples and cross-references for function javadocs in headers. A short example showing a derived class using the Derived* constructor and then calling target() would be helpful.

As per coding guidelines, "Include @par Example in function javadocs with one or more @code blocks" and "Include @see in function javadocs (always last) for related functions, types, and concepts".


88-88: Consider placing ti_ near the other data members at the bottom of the class.

ti_ is declared at the very top of the class (line 88) while all other data members (mutex_, owned_, frame_alloc_, head_, shutdown_) are grouped together in the private: section at lines 539-546. Placing ti_ with them improves layout clarity and keeps the data member declarations cohesive.

Comment on lines +273 to 280
template< typename Executor>
Executor* target()
{
return *vt_->type_id;
if ( *vt_->type_id == detail::type_id< Executor >() )
return const_cast< Executor* >(
static_cast< Executor const* >( ex_ ));
return nullptr;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Non-const target() casts away constness of a const-captured executor.

executor_ref captures the executor via Ex const& (line 153), storing it as void const*. The non-const target() then uses const_cast to return a mutable Executor*. If a caller mutates through this pointer, that's UB whenever the original executor was declared const.

This is consistent with the existing vtable lambdas (e.g., context(), on_work_started()) which also const_cast internally, so this is a pre-existing design choice. However, target() exposes the cast directly to user code, which is more hazardous. Consider either:

  • Adding a @note or @warning in the documentation stating that modification through the returned pointer is undefined behavior if the original executor was const, or
  • Removing the non-const overload entirely, since executor_ref fundamentally holds a const view.
🤖 Prompt for AI Agents
In `@include/boost/capy/ex/executor_ref.hpp` around lines 273 - 280, The non-const
target() in executor_ref exposes a const_cast that can yield UB when
executor_ref was constructed from an Ex const&, so remove the mutable overload
to ensure executor_ref only provides a const view: delete the template< typename
Executor> Executor* target() that returns const_cast of ex_, leaving (or adding)
only a const overload returning Executor const*; update any
references/docs/comments for executor_ref, target(), vt_->type_id and ex_ to
reflect that callers must not obtain a mutable pointer from executor_ref (or
alternatively add a prominent `@warning` in the header if you prefer the
documented-but-unsafe behavior).

@cppalliance-bot
Copy link

An automated preview of the documentation is available at https://154.capy.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-02-12 03:31:42 UTC

@cppalliance-bot
Copy link

GCOVR code coverage report https://154.capy.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://154.capy.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://154.capy.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-02-12 03:39:09 UTC

@sgerbino sgerbino merged commit b1fc33c into cppalliance:develop Feb 12, 2026
13 checks passed
@sgerbino sgerbino deleted the pr/target branch February 12, 2026 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments