Почему не видит функцию?

  1. Можете объяснить почему в методе run std::bind не видет void write(std::string && msg)?
  2. как можно изменить код (не меняя интерфейс класса), чтобы решить эту проблему?
  3. есть ли пример концепта для метода run? я имею ввиду концепт, который будет проверять что Func и переменное кол-во аргументов - исполняемый объект?
#include <iostream>
#include <functional>
struct Foo {
    void add(std::string && msg) {
        run(&Foo::write, this, std::move(msg));
    }
    template<class Func, class ...Args>
    void run(Func && func, Args && ... args) {
        auto task = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);
        task();
    }
    void write(std::string && msg) {
        std::cout << "Foo::write " << msg << '\n';
    }
};
int main()
{
    Foo foo;
    foo.add("hello!");
    return 0;
}

upd сама ошибка

main.cpp:18:13: error: no match for call to ‘(const std::_Bind))(std::basic_string&&)>) ()’
         task();
         ~~~~^~
In file included from main.cpp:10:0:
/usr/include/c++/7/functional:547:2: note: candidate: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}; _Result = _Result; _Functor = void (Foo::*)(std::basic_string&&); _Bound_args = {Foo*, std::basic_string, std::allocator >}]
  operator()(_Args&&... __args)

Ответы (1 шт):

Автор решения: KoVadim

Просто исправьте функцию write на такую

void write(const std::string& msg) {
    std::cout << "Foo::write " << msg << '\n';
}

ну не знает bind о том, что нужно Ваш аргумент передавать таким способом. и не находит подходящей перегрузки

Можете объяснить почему в методе run std::bind не видет void write(std::string && msg)?

Потому что bind на самом деле создает функциональный объект (грубо говоря класс, где переданные параметры - переменные этого класса. А они по определению не будут rvalue).

как можно изменить код (не меняя интерфейс класса), чтобы решить эту проблему?

В вопросе немного не видно, где интерфейс класса, а где нет. Но если где то не работает bind, то нужно использовать лямбды. Маерс в своей книге утверждает, что есть только один случай, где bind ему кажется красивее.

В процессе экспериментов, родился вот такой франкинштейн (поэтому не ругайте:) ). Насколько он "не нарушает интерфейсов", я не знаю. Но он компилируется и работает.

#include <iostream>
#include <functional>

struct Foo {

    void add(std::string && msg) {
        run([&](std::string&&s) {this->write(std::move(s));}, std::move(msg));
    }
    template<class Func, class ...Args>
    void run(Func func, Args && ... args) {
        auto task = [&]() { func(std::forward<Args>(args)...); };
        task();
    }
    void write(std::string&& msg) {
        std::cout << "Foo::write " << msg << '\n';
    }
};
int main()
{
    Foo foo;
    foo.add("hello!");
    return 0;
}

есть ли пример концепта для метода run? я имею ввиду концепт, который будет проверять что Func и переменное кол-во аргументов - исполняемый объект?

я не думаю, что они Вам нужны.

→ Ссылка