@@ -10,11 +10,30 @@ import std_module;
10
10
11
11
namespace containers {
12
12
13
+ // Use CTAD to avoid making a reference_wrapper<reference_wrapper>
14
+ template <typename Function>
15
+ using function_reference = decltype (std::reference_wrapper(bounded::declval<Function &>()));
16
+
17
+ // This used to check if the function is empty instead of whether it is small
18
+ // enough. The sizeof optimization is valid in all cases except those in which
19
+ // the address of state in the function is relevant. In those cases, the
20
+ // function should probably not be copyable (and definitely not trivially
21
+ // copyable), so it seems safe to do.
22
+ template <typename Function>
23
+ constexpr auto can_store_copy =
24
+ std::invocable<Function const &> and
25
+ std::is_trivially_move_constructible_v<Function> and
26
+ std::is_trivially_copy_constructible_v<Function> and
27
+ std::is_trivially_move_assignable_v<Function> and
28
+ std::is_trivially_copy_assignable_v<Function> and
29
+ std::is_trivially_destructible_v<Function> and
30
+ sizeof (Function) <= sizeof (function_reference<Function>);
31
+
13
32
export template <typename Function>
14
33
using stored_function = std::conditional_t <
15
- std::is_empty_v<Function> and std::is_trivially_copyable_v <Function>,
34
+ can_store_copy <Function>,
16
35
std::remove_const_t <Function>,
17
- decltype (std::reference_wrapper(bounded::declval <Function &>()))
36
+ function_reference <Function>
18
37
>;
19
38
20
39
} // namespace containers
0 commit comments