eclipse-iceoryx / eclipse-iceoryx/iceoryx
iox::function claims to support moving functions, but doesn't
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 492
- Avg merge
- 18h 57m
- Merged PRs (30d)
- 1
Description
## Required information
[In the docstring](https://github.com/eclipse-iceoryx/iceoryx/blob/2e38d15f188a28cc3aaeb2716c3a9f0efb4f0626/iceoryx_hoofs/functional/include/iox/function.hpp#L29-L32) for the `iox::function` interface, it is claimed that
```
/// In contrast to iox::function_ref iox::function objects own everything needed
/// to invoke the underlying callable and can be safely stored.
/// They also support copy and move semantics in natural way
/// by copying or moving the underlying callable.
```
However in [the actual implementation docstring](https://github.com/eclipse-iceoryx/iceoryx/blob/2e38d15f188a28cc3aaeb2716c3a9f0efb4f0626/iceoryx_hoofs/functional/include/iox/detail/storable_function.hpp#L62) this is contradicted:
```
Furthermore, the storable_functor stores a copy
// which avoids implicit misbehaviors or ownership problems caused by implicit conversion.
```
And indeed if you attempt to wrap a lambda with a move capture, such as
```
auto unique_int = std::make_unique(42);
auto do_stuff = [unique_int = std::move(unique_int)]{++(*unique_int);};
iox::function do_stuff_wrapper(std::move(do_stuff));
do_stuff_wrapper();
```
You'll get a compile error:
```
external/iceoryx/iceoryx_hoofs/functional/include/iox/detail/storable_function.inl:207:22: error: call to implicitly-deleted copy constructor of 'StoredType' (aka '(lambda at main.cc:29:19)')
new (m_callable) StoredType(functor);
^ ~~~~~~~
external/iceoryx/iceoryx_hoofs/functional/include/iox/detail/storable_function.inl:32:5: note: in instantiation of function template specialization 'iox::storable_function<128, void ()>::storeFunctor<(lambda at /main.cc:29:19), void>' requested here
storeFunctor(functor);
^
/main.cc:30:29: note: in instantiation of function template specialization 'iox::storable_function<128, void ()>::storable_function<(lambda at /main.cc:29:19), void>' requested here
iox::function do_stuff_wrapper(std::move(do_stuff));
^
/main.cc:29:20: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor
auto do_stuff = [unique_int = std::move(unique_int)]{++(*unique_int);};
^
/usr/include/c++/11.2.0/bits/unique_ptr.h:468:7: note: 'unique_ptr' has been explicitly marked deleted here
unique_ptr(const unique_ptr&) = delete;
^
In file included from /main.cc:8:
In file included from :
In file included from :
In file included from external/iceoryx/iceoryx_posh/include/iceoryx_posh/internal/mepoo/segment_manager.hpp:21:
In file included from external/iceoryx/iceoryx_posh/include/iceoryx_posh/iceoryx_posh_config.hpp:19:
In file included from external/iceoryx/iceoryx_posh/include/iceoryx_posh/mepoo/segment_config.hpp:21:
In file included from external/iceoryx/iceoryx_posh/include/iceoryx_posh/mepoo/mepoo_config.hpp:19:
In file included from external/iceoryx/iceoryx_posh/include/iceoryx_posh/iceoryx_posh_types.hpp:24:
In file included from external/iceoryx/iceoryx_hoofs/functional/include/iox/function.hpp:20:
In file included from external/iceoryx/iceoryx_hoofs/functional/include/iox/detail/storable_function.hpp:208:
external/iceoryx/iceoryx_hoofs/functional/include/iox/detail/storable_function.inl:229:27: error: call to implicitly-deleted copy constructor of '(lambda at /main.cc:29:19)'
new (dest.m_callable) CallableType(*obj);
^ ~~~~
external/iceoryx/iceoryx_hoofs/functional/include/iox/detail/storable_function.inl:210:34: note: in instantiation of function template specialization 'iox::storable_function<128, void ()>::copy<(lambda at /main.cc:29:19)>' requested here
m_operations.copyFunction = ©;
^
external/iceoryx/iceoryx_hoofs/functional/include/iox/detail/storable_function.inl:32:5: note: in instantiation of function template specialization 'iox::storable_function<128, void ()>::storeFunctor<(lambda at /main.cc:29:19), void>' requested here
storeFunctor(functor);
^
/main.cc:30:29: note: in instantiation of function template specialization 'iox::storable_function<128, void ()>::storable_function<(lambda at /main.cc:29:19), void>' requested here
iox::function do_stuff_wrapper(std::move(do_stuff));
^
/main.cc:29:20: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor
auto do_stuff = [unique_int = std::move(unique_int)]{++(*unique_int);};
^
/usr/include/c++/11.2.0/bits/unique_ptr.h:468:7: note: 'unique_ptr' has been explicitly marked deleted here
unique_ptr(const unique_ptr&) = delete;
```
**Operating system:**
E.g. Ubuntu 20.04 LTS
**Compiler version:**
E.g. GCC 9.4.0
**Eclipse iceoryx version:**
On an older checkout of main, but should apply to main as well.
**Observed result or behaviour:**
`iox::function` does not support move-only functors
**Expected result or behaviour:**
It should support move-only functors, as documented in the API.
**Conditions where it occurred / Performed steps:**
Try to wrap a lambda with a move-capture.
## Additional helpful information
Contributor guide
Research direction
Start with the iox::function documentation in iceoryx_hoofs/functional/include/iox/function.hpp and the storage and copy paths in iceoryx_hoofs/functional/include/iox/detail/storable_function.hpp and storable_function.inl. Reproduce the move-capture example, then trace storeFunctor and the copy operation; done means a move-only functor can be wrapped and invoked as documented without the shown copy-constructor errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100