mardi 23 janvier 2018

Using class through std::function

I have a question about using a specific class through C++ 2011 std::function in a producer/consumer environment. The producer uses a class Invokable that keeps specific information; the consumer invokes the class instance passing the proper information. My implementation is:

#include <iostream>
#include <vector>
#include <string>
#include <functional>

class Args {
    std::vector<std::string> opts_;

public:
    Args() {}

    Args& operator<<(const std::string& arg) {
        opts_.push_back(arg);
        return *this;
    }

    bool empty() const {
        return opts_.empty();
    }

    std::size_t size() const {
        return opts_.size();
    }

    const std::string& arg(std::size_t index) const {
        return opts_.at(index);
    }
};

class Invokable {
    std::string arg_;

public:
    Invokable() : arg_("none") {}

    bool operator()(Args& args) {
        if (args.empty() == false) {
            arg_ = args.arg(0);
            std::cout << "Invoked with arg '" << arg_ << "'\n";
            return true;
        }

        return false;
    }

    const std::string& arg() const {
        return arg_;
    }
};

class Consumer {
    Args args_;

    std::vector<std::function<bool(Args&)>> signatures_;

public:
    Consumer() {
        args_ << "15" << "18";
    }

    void addInvokable(std::function<bool(Args&)>& sig) {
        signatures_.push_back(sig);
    }

    void run() {
        for (auto& sig : signatures_) {
            sig(args_);
        }
    }
};

class Producer {
    Consumer& user_;
    Invokable invokable_;

public:
    Producer(Consumer& u) : user_(u) {}

    void request() {
        std::function<bool(Args&)> sig {invokable_};
        user_.addInvokable(sig);

        user_.run();
    }

    void verify() {
        std::cout << "Invokable has arg '" << invokable_.arg() << "'\n";
    }
};

int main(int argc, const char** argv) {
    Consumer consumer;
    Producer producer(consumer);

    producer.request();
    producer.verify();

    return 0;
}

I don't understand why the output produced is: Invoked with arg '15' Invokable has arg 'none' That is, why the Invokable instance has not been updated by the consumer?

Aucun commentaire:

Enregistrer un commentaire