【发布时间】:2019-03-13 03:55:05
【问题描述】:
我正在开发一个使用动作队列顺序执行动作的小程序。
我希望能够在我的操作中存储参数直到它们被执行(然后应该可以从操作的exec() 方法访问参数)。
下面有一个小例子:
#include <tuple>
#include <iostream>
#include <memory>
#include <utility>
#include <queue>
/**
* Action interface
*/
struct Action {
Action() {}
virtual void exec() = 0;
};
/**
* This action creates an object which type is given as template
* and passes the parameters given to its ctor. On completion, it
* prints its ID.
*/
template<class T, class... Ps>
struct CustomAction : public Action {
// trying to store the variable arguments
std::tuple<Ps...> _args;
int _actionId;
CustomAction(int id, Ps&&... args) : _actionId(id),
_args(std::make_tuple(std::forward<Ps>(args)...)) {
}
virtual void exec() override {
T* item = new T(std::forward<Ps>(_args)...);
std::cout << "done " << _actionId << std::endl;
}
};
struct ActionQueue {
std::queue<Action*> _queue;
ActionQueue() {
}
void exec() {
while(_queue.size()) {
auto action = _queue.front();
action->exec();
_queue.pop();
}
}
template<class T, class... Ps>
void push(Ps&&... args) {
auto action = new T(std::forward<Ps>(args)...);
_queue.push(action);
}
};
/**
* Example item that is to be created. Nothing important here
*/
struct Item {
int _b;
Item(int b) : _b(b) {
}
};
int main() {
ActionQueue aq;
int actionId = 5;
int param = 2;
aq.push<CustomAction<Item>>(actionId, param);
// do stuff
aq.exec();
}
在这个例子中,我创建了一个ActionQueue。我在队列中推送了一个新的CustomAction。这个动作只是创建了一个Item 并给它的ctor 提供了我在将动作推送到动作队列时给出的参数。
我的问题是我不知道为什么push() 方法的参数不能在CustomAction 类中使用。
编译上面的例子给我以下错误:
<source>:56:27: error: no matching constructor for initialization of 'CustomAction<Item>'
auto action = new T(std::forward<Ps>(args)...);
^ ~~~~~~~~~~~~~~~~~~~~~~
<source>:82:8: note: in instantiation of function template specialization 'ActionQueue::push<CustomAction<Item>, int &, int &>' requested here
aq.push<CustomAction<Item>>(actionId, param);
^
<source>:27:5: note: candidate constructor not viable: requires single argument 'id', but 2 arguments were provided
CustomAction(int id, Ps&&... args) : _actionId(id),
^
<source>:22:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
struct CustomAction : public Action {
^
<source>:22:8: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
1 error generated.
Compiler returned: 1
错误表明CustomAction 需要一个参数,而给出了两个参数,但CustomAction 应该接受args 中的第二个参数。
我在这里做错了什么?
谢谢
【问题讨论】:
-
也许这会有所帮助? stackoverflow.com/a/10766422/1594913
-
或者这个:stackoverflow.com/questions/7858817/…。
T(std::forward<Ps>(_args)...)不会解包元组 -
C++11、C++14 还是 C++17?
-
为什么不使用基于存储 lambda 的设计?那是
std::queue<std::function<void())>>。 -
在上面的代码中,
Actionstruct 必须有一个虚析构函数。当您从队列中删除项目时,您需要删除它们。首选的解决方案是使用智能指针(例如std::unique_ptr<Action>.
标签: c++ templates c++17 variadic-templates variadic-functions