[libcxx-commits] [PATCH] D94452: [libc++] Support immovable return types in std::function.

Arthur O'Dwyer via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 11 14:28:14 PST 2021


Quuxplusone created this revision.
Quuxplusone added reviewers: ldionne, logan-5.
Quuxplusone added a project: libc++.
Quuxplusone requested review of this revision.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

Bug(?) reported by @logan-5.

This is either "oh yeah, sure, trivial, ship it" or "geez this is a really deep open question about the meaning of the standardese" — I'm not sure which. I've posted in #standardese but not otherwise tried to start a discussion/issue yet.

https://eel.is/c++draft/func.wrap.func#general-2
https://eel.is/c++draft/func.require#2
The crux seems to be what [func.require] means by "<expression> implicitly converted to R" — if the type of <expression> is already R, then "implicit conversion to R" is a no-op? Anyway, `is_convertible` seems to be the wrong tool for that job.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94452

Files:
  libcxx/include/functional
  libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp


Index: libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <functional>
+
+#include <functional>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct NonCopyable {
+    NonCopyable() = default;
+    NonCopyable(NonCopyable&&) = delete;
+    friend bool operator==(NonCopyable, NonCopyable) { return true; }
+};
+
+struct LargeLambda {
+    int a[100];
+    NonCopyable operator()() const { return NonCopyable(); }
+    NonCopyable operator()(int) const { return NonCopyable(); }
+};
+
+void test()
+{
+    std::function<NonCopyable()> f1a = []() { return NonCopyable(); };
+    std::function<NonCopyable()> f2a = +[]() { return NonCopyable(); };
+    std::function<NonCopyable()> f3a = LargeLambda();
+    std::function<NonCopyable()> f4a = std::ref(f1a);
+    std::function<NonCopyable(int)> f1b = [](int) { return NonCopyable(); };
+    std::function<NonCopyable(int)> f2b = +[](int) { return NonCopyable(); };
+    std::function<NonCopyable(int)> f3b = LargeLambda();
+    std::function<NonCopyable(int)> f4b = std::ref(f1b);
+
+    assert(f1a() == f2a());
+    assert(f3a() == f4a());
+    assert(f1b(1) == f2b(1));
+    assert(f3b(1) == f4b(1));
+}
+
+void ctad_test()
+{
+    std::function f1a = []() { return NonCopyable(); };
+    std::function f2a = +[]() { return NonCopyable(); };
+    std::function f1b = [](int) { return NonCopyable(); };
+    std::function f2b = +[](int) { return NonCopyable(); };
+    static_assert(std::is_same_v<decltype(f1a), std::function<NonCopyable()>>);
+    static_assert(std::is_same_v<decltype(f2a), std::function<NonCopyable()>>);
+    static_assert(std::is_same_v<decltype(f1b), std::function<NonCopyable(int)>>);
+    static_assert(std::is_same_v<decltype(f2b), std::function<NonCopyable(int)>>);
+}
+
+int main(int, char**)
+{
+    test();
+    ctad_test();
+    return 0;
+}
Index: libcxx/include/functional
===================================================================
--- libcxx/include/functional
+++ libcxx/include/functional
@@ -2349,6 +2349,8 @@
         struct __callable<_Fp, true>
         {
             static const bool value = is_same<void, _Rp>::value ||
+                is_same<typename __invoke_of<_Fp, _ArgTypes...>::type,
+                               _Rp>::value ||
                 is_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type,
                                _Rp>::value;
         };


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D94452.315926.patch
Type: text/x-patch
Size: 3057 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20210111/5b9d1fae/attachment.bin>


More information about the libcxx-commits mailing list