Последнее время все чаще стал реализовывать разные классы, где тем или иным образом контекст вызова функционального объекта переносится в другое место. Чем нам может помочь С++17 ? Казалось бы, есть std::function и std::bind и все должно быть хорошо, но проблемы все таки есть. У меня в коде активно используются move-only объекты, а через std::function и std::bind они нормально не проходят:
struct Copyable
{
Copyable() noexcept = default;
void operator()() const {}
};
struct MoveOnly
{
MoveOnly() noexcept = default;
MoveOnly(const MoveOnly& that) = delete;
MoveOnly(MoveOnly&& that) noexcept = default;
MoveOnly& operator=(const MoveOnly& that) = delete;
MoveOnly& operator=(MoveOnly&& that) noexcept = default;
void operator()() const {}
};
std::function<void()> f1 = std::bind([](Copyable) {}, Copyable()); // Ok
std::function<void(Copyable)> f2 = std::bind([](Copyable) {}, std::placeholders::_1); // Ok
std::function<void()> f3 = std::bind([](MoveOnly) {}, MoveOnly()); // Fail
std::function<void(MoveOnly)> f4 = std::bind([](MoveOnly) {}, std::placeholders::_1); // Ok
std::function<void()> f5 = std::bind(Copyable()); // Ok
std::function<void()> f6 = std::bind(MoveOnly()); // Fail
Кратко, что не работает: не поддерживаются move-only callable объекты (функторы, лямбды и т.д.). Работают move-only передаваемые аргументы.
Что хочется: получить такой же функционал как и у std::invoke
1. Копируемые callable копируются
2. Перемещаемые callable перемещаются
3. Ссылки передаются через std::reference
Есть свои соображения на этот счет, но закрадываются сомнения, не переусложняю ли я ?!
Кто как как решат такое на чистом С++17 ? Что можете предложить ?