c++c++17stdasync

Callable class objects in C++ : no matching function for call to ‘std::tuple<T>::tuple(<brace-enclosed initializer list>)’


My code consists of 2 files: main.cpp and utils.hpp. The contents of those files are given below:

utils.hpp

#ifndef UTILITY_HPP
#define UTILITY_HPP

#include <iostream>
#include <thread>
#include <future>
#include <functional>
#include <chrono>

using std::chrono::milliseconds;

class CallableStoppableTask {
    std::promise<void>  exit_signal;
    std::future<void>   future_obj;

    public:

    CallableStoppableTask() : future_obj(exit_signal.get_future()) {}

    CallableStoppableTask(const CallableStoppableTask&) = delete;
    CallableStoppableTask& operator=(const CallableStoppableTask&) = delete;

    virtual void run() = 0;

    void operator()() { run(); }

    bool is_stop_requested(int timeout_milliseconds = 0) const {
        return (future_obj.wait_for(milliseconds(timeout_milliseconds)) == std::future_status::ready);
    }

    void request_stop() { exit_signal.set_value(); }
};


struct Car {
    int     model;
    int     price;

    explicit Car(const int& arg_model = -1, const int& arg_price = -1)
    : model(arg_model), price(arg_price) {}
};

class CallableSampleTask : public CallableStoppableTask {
    
    CallableSampleTask(const CallableSampleTask&) = delete;

    CallableSampleTask& operator=(const CallableSampleTask&) = delete;

    void run() override {
        std::cout << "Running Some Car Sample Task.. " << std::endl;
    }

public:
    CallableSampleTask(const Car& arg_car = Car()) {}
};

#endif

To implement a task that can be interrupted we inherit the CallableStoppableTask for eg., CallableSampleTask.

The contents of main.cpp are:

#include "utils.hpp"
#include <iostream>
#include <array>
#include <future>
#include <memory>

#define NUM_TASK 5

static std::array<std::unique_ptr<CallableSampleTask>, NUM_TASK> ar_uptr_task;

int main() {
    std::unique_ptr<CallableSampleTask> f = std::move(std::make_unique<CallableSampleTask>());
    (*f.get())();   // COMPILE TIME ERROR: what is the error in this?

    ar_uptr_task.fill(std::move(std::make_unique<CallableSampleTask>()));

    for (int i = 0; i < NUM_TASK; i++) {
        // I want to do something like this. COMPILE TIME ERROR
        auto discard_ret = std::async(std::launch::async, (*ar_uptr_task[i].get()));
    }

    std::cout << "Hello, World!" << std::endl;
    return 0;
}

The above throws a very big COMPILE TIME ERROR. I have commented the lines in main.cpp file which throws the error.

I am using the following command to compile:

g++ -std=c++17 -pthread main.cpp

Any idea where and what I am going wrong?

PS: Please enlighten me with great C++ concepts if I am missing something.

I can't post the error because it is exceeding the stackoverflow limit. Here is the github link: https://github.com/KishoreKaushal/CallableObjects


Solution

  • This line is fine

    (*f.get())();   // COMPILE TIME ERROR: what is the error in this?
    

    but shorter version

    (*f)();
    

    is better.


    ar_uptr_task.fill(std::move(std::make_unique<CallableSampleTask>()));
    

    doesn't make any sense. fill takes source as const object, how do you want apply move operation on const source object [also you want to move source object N-times, but first move operation leaves source object in empty state] ?

    Can be replaced by:

    for (int i = 0; i < 5; ++i)    
        ar_uptr_task[i] = std::make_unique<CallableSampleTask>();
    

    If you want pass functor to async function, wrap it in reference_wrapper by using ref:

     for (int i = 0; i < NUM_TASK; i++) {
         auto discard_ret = std::async(std::launch::async, std::ref(*ar_uptr_task[i]));
     }
    

    Demo