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

P1169R4 static operator() #4053

Merged
merged 5 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
27 changes: 26 additions & 1 deletion stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -1139,12 +1139,37 @@ public:
_NON_MEMBER_CALL(_FUNCTION_POINTER_DEDUCTION_GUIDE, X1, X2, X3)
#undef _FUNCTION_POINTER_DEDUCTION_GUIDE

template <class _Fx, class _Call_op, class = void>
struct _Deduce_from_call_operator : _Is_memfunptr<_Call_op>::_Guide_type {}; // N4958 [func.wrap.func.con]/16.1

#ifdef __cpp_static_call_operator // TRANSITION, P1169R4
template <class>
struct _Inspect_static_call_operator {};

#define _STATIC_CALL_OPERATOR_GUIDES(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT) \
template <class _Ret, class... _Args> \
struct _Inspect_static_call_operator<_Ret(CALL_OPT*)(_Args...) NOEXCEPT_OPT> { \
using type = _Ret(_Args...); \
};

_NON_MEMBER_CALL(_STATIC_CALL_OPERATOR_GUIDES, , , )
#ifdef __cpp_noexcept_function_type
_NON_MEMBER_CALL(_STATIC_CALL_OPERATOR_GUIDES, , , noexcept)
#endif // ^^^ defined(__cpp_noexcept_function_type) ^^^

#undef _STATIC_CALL_OPERATOR_GUIDES

template <class _Fx, class _Call_op>
struct _Deduce_from_call_operator<_Fx, _Call_op, void_t<decltype(_STD declval<_Fx>().operator())>>
: _Inspect_static_call_operator<_Call_op> {}; // N4958 [func.wrap.func.con]/16.2
#endif // ^^^ defined(__cpp_static_call_operator) ^^^

template <class _Fx, class = void>
struct _Deduce_signature {}; // can't deduce signature when &_Fx::operator() is missing, inaccessible, or ambiguous

template <class _Fx>
struct _Deduce_signature<_Fx, void_t<decltype(&_Fx::operator())>>
: _Is_memfunptr<decltype(&_Fx::operator())>::_Guide_type {}; // N4950 [func.wrap.func.con]/16.1
: _Deduce_from_call_operator<_Fx, decltype(&_Fx::operator())> {};

template <class _Fx>
function(_Fx) -> function<typename _Deduce_signature<_Fx>::type>;
Expand Down
1 change: 1 addition & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@
// P1072R10 basic_string::resize_and_overwrite
// P1132R7 out_ptr(), inout_ptr()
// P1147R1 Printing volatile Pointers
// P1169R4 static operator()
// P1206R7 Conversions From Ranges To Containers
// P1223R5 ranges::find_last, ranges::find_last_if, ranges::find_last_if_not
// P1272R4 byteswap()
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ tests\P1135R6_latch
tests\P1135R6_semaphore
tests\P1147R1_printing_volatile_pointers
tests\P1165R1_consistently_propagating_stateful_allocators
tests\P1169R4_static_call_operator
tests\P1206R7_deque_append_range
tests\P1206R7_deque_assign_range
tests\P1206R7_deque_from_range
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P1169R4_static_call_operator/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
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifdef __cpp_static_call_operator // TRANSITION, P1169R4

#include <functional>
#include <future>
#include <type_traits>
using namespace std;

struct F0 {
static char operator()();
};

struct F1 {
static short operator()(float);
};

struct F2 {
static int operator()(double*, double&);
};

struct F3 {
static void operator()(const long&, long&&, const long&&);
};

struct Base {
static bool operator()(unsigned int);
};

struct Derived : Base {};

struct Nothrow {
static char16_t operator()(char32_t) noexcept;
};

template <template <class> class Temp>
void test_ctad() {
static_assert(is_same_v<decltype(Temp{F0{}}), Temp<char()>>);
static_assert(is_same_v<decltype(Temp{F1{}}), Temp<short(float)>>);
static_assert(is_same_v<decltype(Temp{F2{}}), Temp<int(double*, double&)>>);
static_assert(is_same_v<decltype(Temp{F3{}}), Temp<void(const long&, long&&, const long&&)>>);
static_assert(is_same_v<decltype(Temp{Derived{}}), Temp<bool(unsigned int)>>);
static_assert(is_same_v<decltype(Temp{Nothrow{}}), Temp<char16_t(char32_t)>>);

auto lambda = [](int* p, int** q) static { return *p + **q; };
static_assert(is_same_v<decltype(Temp{lambda}), Temp<int(int*, int**)>>);
}

void all_tests() {
test_ctad<function>();
test_ctad<packaged_task>();
}

#endif // ^^^ defined(__cpp_static_call_operator) ^^^