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 all commits
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
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 @@ -128,6 +128,7 @@
// P0858R0 Constexpr Iterator Requirements
// P1065R2 constexpr INVOKE
// (the std::invoke function only; other components like bind and reference_wrapper are C++20 only)
// P1169R4 static operator()
// P1518R2 Stop Overconstraining Allocators In Container Deduction Guides
// P2162R2 Inheriting From variant
// P2251R1 Require span And basic_string_view To Be Trivially Copyable
Expand Down
8 changes: 4 additions & 4 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,6 @@ std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp SKIPPED
std/depr/depr.c.headers/uchar_h.compile.pass.cpp FAIL
std/strings/c.strings/cuchar.compile.pass.cpp FAIL

# P1169R4 static operator()
std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp FAIL

# P2255R2 "Type Traits To Detect References Binding To Temporaries"
std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp FAIL

Expand All @@ -349,6 +346,10 @@ std/utilities/format/format.tuple/set_separator.pass.cpp FAIL
# MSVC doesn't properly support [[no_unique_address]]
std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp SKIPPED

# P1169R4 static operator()
std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp:0 FAIL
std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp:0 FAIL


# *** MISSING LWG ISSUE RESOLUTIONS ***
# LWG-2192 "Validity and return type of std::abs(0u) is unclear" (resolution is missing in UCRT, DevCom-10331466)
Expand Down Expand Up @@ -1065,7 +1066,6 @@ std/ranges/range.factories/range.single.view/cpo.pass.cpp FAIL
std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp FAIL
std/utilities/format/format.functions/escaped_output.ascii.pass.cpp FAIL
std/utilities/format/format.functions/locale-specific_form.pass.cpp FAIL
std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp FAIL
std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.inv/invoke.pass.cpp:0 FAIL
std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp:0 FAIL
std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.array.unbounded.pass.cpp FAIL
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,57 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifdef __cpp_static_call_operator

#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)>>);

#if !(defined(__clang__) && defined(_M_IX86)) // TRANSITION, LLVM-62594, fixed in Clang 18
auto lambda = [](int* p, int** q) static { return *p + **q; };
static_assert(is_same_v<decltype(Temp{lambda}), Temp<int(int*, int**)>>);
#endif // ^^^ no workaround ^^^
}

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

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