-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<functional> Avoid layers of forwards in invoke #585
Conversation
…s, working around DevCom-936694 and DevCom-936696.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some little tweaky things - and thanks for the investigation with my tiny invoke
implementation.
stl/inc/type_traits
Outdated
return _Invoker1<_Callable, _Ty1>::_Call( | ||
static_cast<_Callable&&>(_Obj), static_cast<_Ty1&&>(_Arg1), static_cast<_Types2&&>(_Args2)...); | ||
#endif // _HAS_IF_CONSTEXPR | ||
} | ||
|
||
#if _HAS_CXX17 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we consider #define _C_invoke invoke
in C++20 mode to potentially reduce total instantiations when a program calls both invoke(args...)
and _C_invoke(args...)
? Or:
#if _HAS_CXX20
#define _C_INVOKE invoke
#else
#define _C_INVOKE _C_invoke
// define _C_invoke here
#endif
and replace _C_invoke
with _C_INVOKE
at the callsites?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to think that we should implement #51 unconditionally and just have invoke
be constexpr
. WG21-P0859 "Core Issue 1581: When are constexpr member functions defined?" was voted in as a Defect Report in Albuquerque, which means that it applies retroactively to C++14 (so we can report any issues as compiler bugs). As for the library side, our general policy is to guard features for Standard modes, unless the feature is non-disruptive and guarding it would increase complexity significantly. So far, our experience with constexpr
has been that while it can trigger compiler bugs, it almost always does so when the user is attempting to use it in a constant expression, not ordinary calls (that's why we were able to constexprize so much of the STL without the world exploding). Additionally, making a function constexpr
is non-disruptive to people who aren't expecting it - it introduces no new identifiers, doesn't change lookup or throughput, etc. (The Library's prohibition on constexpr
strengthening does not make sense anymore.) At most, people might take a dependency on the feature and then notice that other implementations do guard it - but that seems like a minor risk (entirely at compile time).
The throughput cost of having two invoke
implementations is nonzero, and the complexity cost (horrible macro) is significant, so I think it should just be unconditionally constexpr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto "I shouldn't be trying to trick you into implementing #51, nevermind for now."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reactivating: I'm going to do just the std::invoke itself only part of #51 unconditionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementing that makes this change depend on #565 since you want to land that out-of-band in 16.6, so I'll hold off merging this until you've done that out of cycle stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/unconditionally/in C++17/g because our rationale is "apply" and friends added in 17
* de-std:: * _C_invoke => _STD invoke * Note that the LWG issue part of P1065R2 is implemented under '17. * Remove decay of _Pmf/_Pmd * PMD noexcept * Remove forwarding of reference_wrapper. * Strengthen noexcept and punch through reference_wrapper.
…tests for the constexpr invoke function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, two comment changes requested.
stl/inc/type_traits
Outdated
public: | ||
template <class... _Types> | ||
auto operator()(_Types&&... _Args) const | ||
noexcept(noexcept(_STD invoke(*_Ptr, static_cast<_Types&&>(_Args)...))) // Strengthened |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We conventionally say strengthened
in lowercase.
@@ -1032,21 +1060,76 @@ void test_reference_wrapper_invocation() { | |||
|
|||
|
|||
// Test C++17 invoke(). | |||
#if _HAS_CXX17 | |||
constexpr bool test_invoke_constexpr() { | |||
// MSVC++ implements LWG-2894 as a DR back to C++17 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually refer to ourselves as MSVC
without ++
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't work for "MSVD"?
Co-Authored-By: Casey Carter <[email protected]>
This resolved Microsoft-internal VSO-231629 " |
Description
This change removes the last "nonessential" stack frame that would be encountered for threads, and makes the debugging experience for several standard components, like
std::function
, nicer by not needing so many step into / step out of sequences.Hopefully this makes debug codegen better too, particularly now that ranges hammers invoke even harder than we used to.
I didn't change any of the metaprogramming for deciding which strategy to use -- I like that we don't use SFINAE to make that decision, and don't really consider myself competent enough a metaprogrammer to confidently make changes there. I just make
_Invoker_xyz
also supply a strategy value that is fed intoif constexpr
. @CaseyCarter suggested some larger changes which might have sped up metaprogramming I tried, but ran into issues because one can't deduce the calling convention of pointers-to-member-function.I've also made a one time exception to our usual policy of using
std::forward
rather thanstatic_cast
, with the rationale thatinvoke
is hammered everywhere, and also by traits, and we want the debugging experience of that to be as nice as possible.(Also drive-by removed unnecessary compilation of iostreams from the
Dev10_729003_bind_reference_wrapper
I noticed debugging a test case failure)Checklist
Be sure you've read README.md and understand the scope of this repo.
If you're unsure about a box, leave it unchecked. A maintainer will help you.
_Ugly
as perhttps://eel.is/c++draft/lex.name#3.1 or there are no product code changes.
verified by an STL maintainer before automated testing is enabled on GitHub,
leave this unchecked for initial submission).
members, adding virtual functions, changing whether a type is an aggregate
or trivially copyable, etc.).
the C++ Working Draft (including any cited standards), other WG21 papers
(excluding reference implementations outside of proposed standard wording),
and LWG issues as reference material. If they were derived from a project
that's already listed in NOTICE.txt, that's fine, but please mention it.
If they were derived from any other project (including Boost and libc++,
which are not yet listed in NOTICE.txt), you must mention it here,
so we can determine whether the license is compatible and what else needs
to be done.