Skip to content

Commit af9771c

Browse files
committed
stored_function now supports directly storing small functions, not just empty functions. Improve the trivial checks.
1 parent d53121c commit af9771c

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

source/containers/stored_function.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,30 @@ import std_module;
1010

1111
namespace containers {
1212

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+
1332
export template<typename Function>
1433
using stored_function = std::conditional_t<
15-
std::is_empty_v<Function> and std::is_trivially_copyable_v<Function>,
34+
can_store_copy<Function>,
1635
std::remove_const_t<Function>,
17-
decltype(std::reference_wrapper(bounded::declval<Function &>()))
36+
function_reference<Function>
1837
>;
1938

2039
} // namespace containers

0 commit comments

Comments
 (0)