Skip to content
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>: Implement invoke_r #2019

Merged
merged 29 commits into from
Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0ab0cdc
Implement invoke_r
SuperWig Jun 20, 2021
4ef0e40
trailing spaces
SuperWig Jun 20, 2021
88caed6
if constexpr for void
SuperWig Jun 20, 2021
c0d78ba
Add zero argument and void return type functionality.
SuperWig Jun 20, 2021
f376138
[skip ci] formatting
SuperWig Jun 20, 2021
1c53570
Add _NODISCARD
SuperWig Jun 20, 2021
4a91928
[skip ci] correct comment placement and `()`
SuperWig Jun 21, 2021
9a30dfd
[skip ci] formatting
SuperWig Jun 22, 2021
6b1dde4
Restore 3 arg overload.
SuperWig Jun 22, 2021
059fdba
Use invoke_r on data member and use is_permissive trick.
SuperWig Jun 23, 2021
1963a65
Make a templated noexcept_test
SuperWig Jun 23, 2021
795d2a8
Merge branch 'main' into invoke_r
StephanTLavavej Jun 30, 2021
78abdc7
Small changes
SuperWig Jun 30, 2021
27ecd63
[skip ci] SHOUTY banner
SuperWig Jul 1, 2021
edc4e15
Use single overload
SuperWig Jul 1, 2021
554e25e
Use SFINAE instead of requires
SuperWig Jul 9, 2021
b5d2606
long int and foo
SuperWig Jul 9, 2021
64f3d30
use traits and add additional noexcept test
SuperWig Jul 9, 2021
46fa210
additional tests
SuperWig Jul 9, 2021
e169e27
Missed argument overloads
SuperWig Jul 9, 2021
b197c7d
Test noexcept functions are false if __cpp_noexcept_function_type isn…
SuperWig Jul 14, 2021
45a3d89
Assert messages are no longer correct.
SuperWig Jul 14, 2021
f491133
Merge remote-tracking branch 'upstream/main' into invoke_r
SuperWig Jul 21, 2021
d2018be
[skip ci] shhh
SuperWig Jul 23, 2021
92cd950
Merge branch 'main' into invoke_r
StephanTLavavej Aug 10, 2021
56bc89f
Test a stateful lambda.
StephanTLavavej Aug 10, 2021
f2ede72
Need to include `<string>`.
StephanTLavavej Aug 10, 2021
021209d
Consistently use `STATIC_ASSERT`.
StephanTLavavej Aug 10, 2021
1ab5964
Use `static_cast<T&&>` for throughput/consistency.
StephanTLavavej Aug 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ _STL_DISABLE_CLANG_WARNINGS
#undef new

_STD_BEGIN
#if _HAS_CXX23
template <class _Result_type, class _Callable, class... _Types,
enable_if_t<is_invocable_r_v<_Result_type, _Callable, _Types...>, int> = 0>
_NODISCARD constexpr _Result_type invoke_r(_Callable&& _Obj, _Types&&... _Args) noexcept(
is_nothrow_invocable_r_v<_Result_type, _Callable, _Types...>) {
if constexpr (is_void_v<_Result_type>) {
(void) _STD invoke(static_cast<_Callable&&>(_Obj), static_cast<_Types&&>(_Args)...);
} else {
return _STD invoke(static_cast<_Callable&&>(_Obj), static_cast<_Types&&>(_Args)...);
}
}
#endif // _HAS_CXX23

// plus, minus, and multiplies are defined in <xstddef>

template <class _Ty = void>
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
// P1682R3 to_underlying() For Enumerations
// P1951R1 Default Template Arguments For pair's Forwarding Constructor
// P1989R2 Range Constructor For string_view
// P2136R3 invoke_r()
Copy link
Member

Choose a reason for hiding this comment

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

HUGE nit: the paper title does not seem to have the parenthesis

Copy link
Member

Choose a reason for hiding this comment

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

Good catch - this is intentional, I added the parentheses to the "cleaned-up" title in #1978 to be consistent with the other cleaned-up titles.

// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
// P2186R2 Removing Garbage Collection Support

Expand Down Expand Up @@ -1354,6 +1355,7 @@
#define __cpp_lib_allocate_at_least 202106L
#endif // __cpp_lib_concepts

#define __cpp_lib_invoke_r 202106L
#define __cpp_lib_is_scoped_enum 202011L

#ifdef __cpp_lib_concepts
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ tests\P1614R2_spaceship
tests\P1645R1_constexpr_numeric
tests\P1682R3_to_underlying
tests\P1951R1_default_arguments_pair_forward_ctor
tests\P2136R3_invoke_r
tests\P2162R2_std_visit_for_derived_classes_from_variant
tests\VSO_0000000_allocator_propagation
tests\VSO_0000000_any_calling_conventions
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2136R3_invoke_r/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
115 changes: 115 additions & 0 deletions tests/std/tests/P2136R3_invoke_r/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cassert>
#include <functional>
#include <string>
#include <type_traits>

#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)

using namespace std;

// TRANSITION, DevCom-1457457
namespace detail {
static constexpr bool permissive() {
return false;
}

template <class>
struct DependentBase {
static constexpr bool permissive() {
return true;
}
};

template <class T>
struct Derived : DependentBase<T> {
static constexpr bool test() {
return permissive();
}
};
} // namespace detail
constexpr bool is_permissive = detail::Derived<int>::test();

constexpr int square(int n) {
return n * n;
}
constexpr int square_noexcept(int n) noexcept {
return n * n;
}
constexpr const char* cstring() noexcept;

struct Thing {
int n = 0;
constexpr int& moo() {
return n;
}
};

struct RefQualified {
constexpr int operator()(int&&) && {
return 1;
}
constexpr int operator()(const int&) && {
return 2;
}
constexpr int operator()(int&&) & {
return 3;
}
constexpr int operator()(const int&) & {
return 4;
}
};

constexpr bool test_invoke_r() {
auto v1 = invoke_r<long>(square, 3);
assert(v1 == 9L);
STATIC_ASSERT(is_same_v<decltype(v1), long>);

auto v2 = invoke_r<double>([]() -> int { return 5; });
assert(v2 == 5);
STATIC_ASSERT(is_same_v<decltype(v2), double>);
STATIC_ASSERT(is_void_v<decltype(invoke_r<void>(square, 1))>);

// TRANSITION, DevCom-1457457
STATIC_ASSERT(noexcept(invoke_r<int>(square, 3)) == is_permissive);
STATIC_ASSERT(noexcept(invoke(square, 3)) == is_permissive);

constexpr bool has_noexcept_in_type =
#ifdef __cpp_noexcept_function_type
true;
#else
false;
#endif
SuperWig marked this conversation as resolved.
Show resolved Hide resolved
STATIC_ASSERT(noexcept(invoke(square_noexcept, 3)) == has_noexcept_in_type);
STATIC_ASSERT(noexcept(invoke_r<int>(square_noexcept, 3)) == has_noexcept_in_type);
STATIC_ASSERT(noexcept(invoke(cstring)) == has_noexcept_in_type);
STATIC_ASSERT(!noexcept(invoke_r<string>(cstring)));

Thing thing;
invoke_r<void>(&Thing::n, thing); // no nodiscard warning
STATIC_ASSERT(is_same_v<decltype(invoke(&Thing::moo, thing)), int&>);
STATIC_ASSERT(is_same_v<decltype(invoke_r<int>(&Thing::moo, thing)), int>);

auto lambda = [counter = 0]() mutable { return ++counter; };
assert(lambda() == 1);
assert(lambda() == 2);
assert(invoke_r<int>(lambda) == 3);
assert(invoke_r<int>(lambda) == 4);
assert(lambda() == 5);

int lvalue = 0;
assert(invoke_r<int>(RefQualified{}, 0) == 1);
assert(invoke_r<int>(RefQualified{}, lvalue) == 2);
RefQualified r;
assert(invoke_r<int>(r, 0) == 3);
assert(invoke_r<int>(r, lvalue) == 4);

return true;
}
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

int main() {
test_invoke_r();
STATIC_ASSERT(test_invoke_r());
}
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,16 @@ STATIC_ASSERT(__cpp_lib_interpolate == 201902L);
STATIC_ASSERT(__cpp_lib_invoke == 201411L);
#endif

#if _HAS_CXX23
#ifndef __cpp_lib_invoke_r
#error __cpp_lib_invoke_r is not defined
#elif __cpp_lib_invoke_r != 202106L
#error __cpp_lib_invoke_r is not 202106L
#else
STATIC_ASSERT(__cpp_lib_invoke_r == 202106L);
#endif
#endif

#if _HAS_CXX17
#ifndef __cpp_lib_is_aggregate
#error __cpp_lib_is_aggregate is not defined
Expand Down