eclipse-iceoryx / eclipse-iceoryx/iceoryx

iox::function claims to support moving functions, but doesn't

Open
#2,319 7 comments 0 reactions 0 assignees View on GitHub
bug good first issue
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.