0

I have a piece of code that compiles and runs without issues in gcc-6.4.0. However, in gcc-7.2.0, the same code would have the following compile errors:

gcc-7.2.0/bin/g++ -std=c++14 myerr.cc
myerr.cc: In lambda function:
myerr.cc:53:52: error: binary expression in operand of fold-expression
             tq_.push_back([&](){ return (dep->run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
myerr.cc:53:52: error: expected primary-expression before ‘,’ token
             tq_.push_back([&](){ return (dep->run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
                                                    ^
myerr.cc:53:58: error: expected primary-expression before ‘&&’ token
             tq_.push_back([&](){ return (dep->run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
                                                          ^~
myerr.cc:53:52: error: binary expression in operand of fold-expression
             tq_.push_back([&](){ return (dep->run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
                                          ~~~~~~~~~~^~~~~~
myerr.cc:53:63: error: mismatched operator in fold-expression before ‘>’ token
             tq_.push_back([&](){ return (dep->run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
                                                           ^
myerr.cc:53:63: error: expected ‘)’ before ‘>’ token

Can anyone please help on the error messages? The code is below.

#include <iostream>
#include <deque>
#include <unordered_map>
#include <vector>
#include <utility>
#include <memory>
#include <functional>

template <typename T>
struct Task_Trait {
    typedef T obj_t;
    typedef T* obj_ptr;

    using pfid_t = const char * (T::*)() const;
    static pfid_t GetId;
};


template <typename T>
struct Task {
    typedef Task<T> task_t;
    typedef task_t * task_ptr;
    typedef std::unordered_map<std::string, std::unique_ptr<task_t>> taskmap_t;

private:    
    T *  obj_;
    std::vector<task_ptr> dependents_;

    Task(T& obj) : obj_(&obj), dependents_() {
    }

    static taskmap_t gtaskmap_;
    static std::deque<std::function<void()>> tq_;

public:
    static Task & CreateTask(T& obj) {
        static const char * (T::*getId)() const = Task_Trait<T>::GetId;
        const char * id = (obj.*getId)();
        auto it = gtaskmap_.find(id);
        if (it == gtaskmap_.end()) {
            it = gtaskmap_.emplace(id, std::move(std::unique_ptr<task_t>(new Task(obj)))).first;
        }
        return *(it->second);
    }

    template <typename F, class ... Args>
    void run(F&& f, Args&& ... args) {
        std::cout << "INFO: running function for task" << this->getId() << std::endl;
        (this->obj_->*f)(std::forward<Args>(args)...);
        for (auto dep : this->dependents_) {
            //auto mfunc = &(Task<T>::run<P>);
            tq_.push_back([&](){ return (dep->run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
        }
        while (!tq_.empty()) {
            std::function<void()> task = std::move(this->tq_.front());
            this->tq_.pop_front();
            task();
        }
    }

    const char * getId() const {
        static typename Task_Trait<T>::pfid_t getId = Task_Trait<T>::GetId;
        return (this->obj_->*getId)();
    }

    void depend(const char * id) {
        static typename Task_Trait<T>::pfid_t getId = Task_Trait<T>::GetId;
        auto dit = gtaskmap_.find(id);
        if (dit != gtaskmap_.end()) {
            dependents_.push_back(dit->second.get());
            std::cout << "INFO: " << id << " depends on " << this->getId() << std::endl;
        } else {
            std::cout << "ERROR: cannot find dependent " << id << " for task " << this->getId() << std::endl;
        }
    }
};


class DataTask {
public:
    DataTask(const char * id) : id_(id) {
    }

    void print(int x) {
        std::cout << "id=" << id_ << " value=" << x << std::endl;
    }

    const char * id() const {
        return id_.c_str();
    }

private:
    std::string id_;
};

template <typename T>
typename Task<T>::taskmap_t Task<T>::gtaskmap_;

template <typename T>
typename std::deque<std::function<void()>> Task<T>::tq_;

template <>
Task_Trait<DataTask>::pfid_t Task_Trait<DataTask>::GetId = &DataTask::id;

int main() {
    DataTask a("a");
    DataTask b("b");
    DataTask c("c");
    DataTask d("d");
    DataTask e("e");

    auto & ta = Task<DataTask>::CreateTask(a);
    auto & tb = Task<DataTask>::CreateTask(b);
    auto & tc = Task<DataTask>::CreateTask(c);
    auto & td = Task<DataTask>::CreateTask(d);
    auto & te = Task<DataTask>::CreateTask(e);

    ta.depend("b");
    ta.depend("c");
    tb.depend("d");
    tb.depend("e");

    return 0;
}
max66
  • 65,235
  • 10
  • 71
  • 111
wizwx0
  • 25
  • 5

1 Answers1

1

Try adding a template in run() (before run()).

I mean

// ...............................vvvvvvvvv
tq_.push_back([&](){ return (dep->template run<F, Args&&...>)(std::forward<F>(f), std::forward<Args>(args)...); });
max66
  • 65,235
  • 10
  • 71
  • 111
  • Yes, adding template before run works. What is this syntax? – wizwx0 Dec 12 '17 at 19:14
  • Does it have any ambiguities if I miss the keyword template? – wizwx0 Dec 12 '17 at 19:22
  • @wizwx0 - I'm not very good in explaining this sort of things; but Barry marked your question as a duplicate of another one with an extensive (and great, IMHO) answer to your question; I suggest you to read it. – max66 Dec 12 '17 at 20:33