C++ 中的可调用 class 对象:没有用于调用“std::tuple<T>::tuple(<brace-enclosed initializer list>)”的匹配函数

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

我的代码由 2 个文件组成:main.cpputils.hpp。这些文件的内容如下:

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

为了实现可以中断的任务,我们继承了 CallableStoppableTask,例如 CallableSampleTask

main.cpp的内容是:

#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;
}

以上抛出一个非常大的编译时错误。我已经评论了 main.cpp 文件中引发错误的行。

我正在使用以下命令编译:

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

知道我哪里出了问题吗?

PS:如果我遗漏了什么,请用很棒的 C++ 概念启发我。

我无法 post 错误,因为它超出了 Whosebug 的限制。这里是 github link: https://github.com/KishoreKaushal/CallableObjects

这条线没问题

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

但更短的版本

(*f)();

更好。


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

没有任何意义。 fill 将 source 作为 const 对象,你想如何在 const 源对象上应用移动操作 [你还想移动源对象 N 次,但第一次移动操作离开源对象处于空状态] ?

可以替换为:

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

如果您想将仿函数传递给 async 函数,请使用 ref:

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

Demo