2

「タスク」クラスを実装したいと考えています。このクラスには、関数ポインターとそれに渡す引数を格納できます。std::bind() のように。引数の保存方法について質問があります。

class BaseTask {
public:
    virtual ~BaseTask() {}
    virtual void run() = 0;
};

template<typename ... MTArg>
class Task : public BaseTask {
public:
    typedef void (*RawFunction)(MTArg...);

    Task(RawFunction rawFunction, MTArg&& ... args) : // Q1: MTArg&& ... args
        rawFunction(rawFunction),
        args(std::make_tuple(std::forward<MTArg>(args)...)) {} // Q2: std::make_tuple(std::forward<MTArg>(args)...)

    virtual void run() {
        callFunction(GenIndexSequence<sizeof...(MTArg)>()); // struct GenIndexSequence<count> : IndexSequence<0, ..., count-1>
    }
private:
    template<unsigned int... argIndexs>
    inline void callFunction() {
        rawFunction(std::forward<MTArg>(std::get<argIndexs>(args))...);
    }

private:
    RawFunction rawFunction;
    std::tuple<MTArg...> args; // Q3: std::tuple<MTArg...>
};

Q1: MTArg の後に && は必要ですか?

Q2: この方法で引数を初期化するのは正しいですか?

Q3: 引数の型は正しいですか?

std::tuple<special_decay_t<MTArg>...>

これによると:http://en.cppreference.com/w/cpp/utility/tuple/make_tuple

//質問終わり

  1. Task は次のように使用できます。

    void fun(int i, const int& j) {}
    
    BaseTask* createTask1() {
        return new Task<int, const int&>(&fun, 1, 2); // "2" must not be disposed at the time of task.run(), so inside Task "2" should be store as "int", not "const int&"
    }
    
    BaseTask* createTask2(const int& i, const int& j) {
        return new Task<int, const int&>(&fun, i, j); // "j" must not be disposed at the time of task.run(), so inside Task "j" should be store as "int", not "const int&"
    }
    
    void test(){
        createTask1()->run();
        createTask2(1, 2)->run();
    }
    
  2. task は 1 回しか実行されません。つまり、0 回または 1 回です。

4

2 に答える 2