This commit series implements double indirection avoidance for the
function_ref and it is based on my patch for function_ref implementation.

This patch is send as RFC instead of PATCH ready for review, as I have
noticed that performing this implementation is user-observable and not
allowed in the standard even with changes suggested in LWG4264 [1].

To avoidance of double indirection requires that constructed function_ref,
refers directly to the target function of the source, instead of source,
and this is visible after the assigment:

```
void foo() noexcept;
void bar() noexcept;

std::function_ref<void() noexcept> sr(&foo);
std::function_ref<void()> dr(sr);
dr(); // calls `foo` regardless of implementation

sr = &bar;
sr(); // calls `bar`
dr(); // still calls `foo` if we avoid indirection,
      // calls `bar` if we do not
```

Similary for move_only_function/copyable_function source:

```
std::move_only_function<void()> sm;
std::function_ref<void()> dm(sm);

dm(); // UB because `sm` is empty

sm = &foo;

dm(); // remains UB if we avoid indirection,
      // calls `bar` if we do not.

```

While we may want to allow skipping indirection for function_ref,
as this produces same behavior as in case for copy constructor (matching
signatures):
```
void foo() noexcept;
void bar() noexcept;

std::function_ref<void() noexcept> sr(&foo);
std::function_ref<void() noexcept> dr(sr); // copy-cosntructor
dr(); // calls `foo` regardless of implementation

sr = &bar;
sr(); // calls `bar`
dr(); // still calls `foo` if we avoid indirection
```,
I do not think this is acceptable for `move_only_function. So most
likely we will and only first commit. 
 
Note that for the same reason, implementations are not free to avoid
dangling when constructing function_ref from reference_wrapper:
---
auto srw = std::ref(&foo);
std::function_ref<void()> drw(srw);
drw(); // calls `foo`

srw = std::ref(&bar);
drw(); // calls `foo` if we unwrap referenc wrapper,
       // calls `bar` otherwise.
--

Note that this is limited to function_ref due reference nature of this
wrapper.

[1] https://cplusplus.github.io/LWG/issue4264

Reply via email to