Repository navigation
Use invoke - #57
Use invoke#57
Conversation
- Added support for invoking member pointers directly using std::invoke. - Updated documentation to reflect new invocation capabilities. - Removed the make_function_object.hpp file and its associated tests. - Added unit tests for invoking member pointers and applying member functions.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a57fda82b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| /// @brief Shifts @p left left by @p right. | ||
| template<typename T, typename U> | ||
| constexpr decltype(auto) operator()(T&& left, U&& right) const |
There was a problem hiding this comment.
Decay shift results before operand temporaries expire
When a deferred operand evaluates to a prvalue and its custom operator<< returns a reference to that operand, decltype(auto) propagates a reference to the temporary created inside apply_evaluated; the temporary is destroyed before the caller uses the result, causing a dangling reference (reproduced as a stack-use-after-return under ASan). The previous lambda's auto return decayed this result to a value, as the new unary wrappers do. Return auto here and in the analogous shift_right wrapper.
Useful? React with 👍 / 👎.
`invoke_builder` and `apply_invoker` stored the callable as `F&& f`. When `F` is a function reference the member is a reference to a function, which MSVC cannot read in a constant expression, so `constexpr` uses of `apply()` and `apply_evaluated()` failed to compile. Hold functions as function pointers instead, via a new `detail::callable_storage_t`. `std::optional`'s converting constructor has no noexcept specification, so `if_(true, 42)` is only nothrow where the standard library chooses to make it so; libstdc++ does, libc++ does not. Assert the propagation rule the library actually guarantees rather than libstdc++'s behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CftmcRq9o1fztk1puisTNN
`shift_left` and `shift_right` returned `decltype(auto)`, unlike the five unary wrappers and unlike the lambdas they replaced, which both return `auto`. When the left operand evaluates to a prvalue it is materialized as a temporary inside `apply_invoker::operator()`; a user `operator<<` returning a reference to that operand then had the reference propagated out through `apply_evaluated()` and `expression_::operator()`, outliving the temporary. Reproduced as a stack-use-after-return under ASan. Reported by Codex review on #57. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CftmcRq9o1fztk1puisTNN
Adds a Clang + ASan job on Ubuntu. The dangling reference just fixed in the shift operators was a stack-use-after-return that only a sanitizer run would have caught, so detect_stack_use_after_return is enabled explicitly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CftmcRq9o1fztk1puisTNN
No description provided.