Skip to content

Commit 6353f31

Browse files
committed
Try lifetimebound
1 parent 352ddc9 commit 6353f31

File tree

4 files changed

+48
-2
lines changed

4 files changed

+48
-2
lines changed

subspace/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ target_sources(subspace PUBLIC
7373
"macros/compiler.h"
7474
"macros/eval_macro.h"
7575
"macros/for_each.h"
76+
"macros/lifetimebound.h"
7677
"macros/no_unique_address.h"
7778
"macros/nonnull.h"
7879
"macros/remove_parens.h"

subspace/fn/fn_defn.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <stdint.h>
1818

1919
#include "subspace/fn/callable.h"
20+
#include "subspace/macros/lifetimebound.h"
2021
#include "subspace/mem/addressof.h"
2122
#include "subspace/mem/forward.h"
2223
#include "subspace/mem/never_value.h"
@@ -85,6 +86,14 @@ concept FunctionPointer =
8586
{ (*f)(args...) } -> std::convertible_to<R>;
8687
};
8788

89+
template <class T>
90+
concept IsFunctionPointer = std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>;
91+
92+
template <class F>
93+
concept ConvertsToFunctionPointer = requires(F f) {
94+
{ +f } -> IsFunctionPointer;
95+
};
96+
8897
template <class F, class R, class... Args>
8998
concept CallableMut =
9099
!FunctionPointer<F, R, Args...> && requires(F & f, Args... args) {
@@ -127,7 +136,7 @@ concept CallableConst =
127136
template <class R, class... CallArgs>
128137
class [[sus_trivial_abi]] Fn<R(CallArgs...)> {
129138
public:
130-
/// Construction from a function pointer or captureless lambda.
139+
/// Construction from a function pointer.
131140
///
132141
/// #[doc.overloads=ctor.fnpointer]
133142
template <__private::FunctionPointer<R, CallArgs...> F>
@@ -137,16 +146,28 @@ class [[sus_trivial_abi]] Fn<R(CallArgs...)> {
137146
invoke_ = &__private::Invoker<F>::template fnptr_call_const<R, CallArgs...>;
138147
}
139148

140-
/// Construction from a capturing lambda or other callable object.
149+
/// Construction from a non-capturing lambda.
141150
///
142151
/// #[doc.overloads=ctor.lambda]
143152
template <__private::CallableMut<R, CallArgs...> F>
153+
requires(__private::ConvertsToFunctionPointer<F>)
144154
constexpr Fn(F&& object) noexcept {
145155
storage_.object = ::sus::mem::addressof(object);
146156
invoke_ = &__private::Invoker<
147157
std::remove_reference_t<F>>::template object_call_const<R, CallArgs...>;
148158
}
149159

160+
/// Construction from a capturing lambda or other callable object.
161+
///
162+
/// #[doc.overloads=ctor.lambda]
163+
template <__private::CallableMut<R, CallArgs...> F>
164+
requires(!__private::ConvertsToFunctionPointer<F>)
165+
constexpr Fn(F&& object sus_lifetimebound) noexcept {
166+
storage_.object = ::sus::mem::addressof(object);
167+
invoke_ = &__private::Invoker<
168+
std::remove_reference_t<F>>::template object_call_const<R, CallArgs...>;
169+
}
170+
150171
~Fn() noexcept = default;
151172

152173
constexpr Fn(Fn&& o) noexcept

subspace/fn/fn_unittest.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,4 +494,9 @@ TEST(Fn, CallsCorrectOverload) {
494494
EXPECT_EQ(mut_calls, 2);
495495
}
496496

497+
TEST(Fn, Lvalue) {
498+
Fn<void()> f([]() {});
499+
Fn<void()> g([i = 1]() { (void)i; });
500+
}
501+
497502
} // namespace

subspace/macros/lifetimebound.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include "subspace/macros/compiler.h"
18+
19+
#define sus_lifetimebound sus_if_clang([[clang::lifetimebound]])

0 commit comments

Comments
 (0)