[英]Using std::future/std::async
当我尝试运行下一个代码时,出现一些错误:
// tree.cpp
// compile with: g++ -std=c++11 tree.cpp -o tree
#include <iostream>
#include <future>
using namespace std;
int valtab[127]; // used for integer values of variables
class Tree; // forward declare
class Node {
protected:
Node() { use = 1; }
virtual void print(ostream &os) = 0;
virtual ~Node() { }
virtual int eval() = 0;
private:
friend class Tree;
friend ostream& operator<<(ostream&, const Tree&);
int use; // reference count
};
class Tree {
public:
Tree(int n); // constant
Tree(char id); // variable
Tree(char op, Tree t); // unary operator
Tree(char op, Tree left, Tree right); // binary operator
Tree(const Tree &t) { p = t.p; ++p->use; }
~Tree() { if (--p->use == 0) delete p; }
void operator=(const Tree &t);
int eval() { return p->eval(); }
private:
friend class Node;
friend ostream& operator<<(ostream &os, const Tree &t);
Node *p; // polymorphic hierarchy
};
void Tree::operator=(const Tree &t)
{
++t.p->use;
if (--p->use == 0)
delete p;
p = t.p;
}
ostream& operator<<(ostream &os, const Tree &t)
{
t.p->print(os);
return os;
}
class LeafNode: public Node {
private:
friend class Tree;
void print(ostream &os) = 0;
virtual int eval() = 0;
};
class IntNode: public LeafNode {
public:
int eval() { return n; }
private:
friend class Tree;
int n;
void print(ostream &os) { os << n ;}
IntNode(int k): n(k) { }
};
class IdNode: public LeafNode {
public:
int eval() { return valtab[name]; }
private:
friend class Tree;
char name;
void print(ostream& o) { o << name; }
IdNode(char id): name(id) { }
};
class UnaryNode: public Node {
public:
int eval();
private:
friend class Tree;
const char op;
Tree opnd;
UnaryNode(char a, Tree b): op(a), opnd(b) { }
void print(ostream& o) { o << "(" << op << opnd << ")"; }
};
int UnaryNode::eval()
{
switch (op) {
case '-': return (-opnd.eval());
case '+': return (+opnd.eval());
default: cerr << "no operand" << endl;
return 0;
}
}
class BinaryNode: public Node {
public:
int eval();
private:
friend class Tree;
const char op;
Tree left;
Tree right;
BinaryNode(char a, Tree b, Tree c): op(a), left(b), right(c) { }
void print(ostream &os) { os << "(" << left << op << right << ")"; }
};
int BinaryNode::eval()
{
switch (op) {
case '-': {
future<int> left = async(launch::async, left.eval());
future<int> right = async(launch::async, right.eval());
//return (left.get() - right.get());
}
case '+': return (left.eval() + right.eval());
case '*': return (left.eval() * right.eval());
default: cerr << "no operand" << endl;
return 0;
}
}
Tree::Tree(int n) { p = new IntNode(n); }
Tree::Tree(char id) { p = new IdNode(id); }
Tree::Tree(char op, Tree t) { p = new UnaryNode(op, t); }
Tree::Tree(char op, Tree left, Tree right) { p = new BinaryNode(op, left, right); }
int main()
{
valtab['A'] = 3; valtab['B'] = 4;
cout << "A = 3, B = 4" << endl;
Tree t1 = Tree('*', Tree('-', 5), Tree('+', 'A', 4));
Tree t2 = Tree('+', Tree('-', 'A', 1), Tree('+', t1, 'B'));
cout << "t1 = " << t1 << ", t2 = " << t2 << endl;
cout << "t1 = " << t1.eval() << ", t2 = " << t2.eval() << endl;
return 0;
}
我收到此错误:
error: 'class std::future<int>' has no member named 'eval'
我想更改程序,以便以并行方式对表达式求值。 但是我对未来的实现感到困惑,我不太了解它是如何工作的。 好吧,我知道它是如何工作的,但是我不明白为什么会收到这些错误。
我希望有人能给我一些提示或为我指明正确的方向。
您试图将虚拟成员函数作为异步调用,但未正确提供对象以使其固定。 此外,您同样-ID本地变量的使用,而不是直接引入一个错误,让这个令人难以置信的难以阅读。
我相信这是您要拍摄的内容:
auto eLeft = std::async(std::launch::async, std::bind(&Tree::eval, &this->left));
auto eRight = std::async(std::launch::async, std::bind(&Tree::eval, &this->right));
return (eLeft.get() - eRight.get());
不过,老实说,这似乎有些过分。 我看不出有什么意义纺纱两个异步操作只需再等上两个 。 为什么不启动一个 ,然后使用当前线程执行任务的另一半:
auto eRight = std::async(std::launch::async, std::bind(&Tree::eval, &this->right));
return (left.eval() - eRight.get());
std::async
的参数是一个函数(或更准确地说,是Callable )。
特别是,您不必自己调用该函数(这会产生返回值)。 调用由std::async
。
所以这些行:
future<int> left = async(launch::async, left.eval());
future<int> right = async(launch::async, right.eval());
相反,应阅读如下内容:
future<int> left_result = std::async(launch::async, [this]() { return left.eval(); });
future<int> right_result = std::async(launch::async, [this]() { return right.eval(); });
请注意,函数调用现在包装在lambda中。 还要注意的是,你还重用了名left
和right
在你的原代码,这是比较麻烦的。 我在这里将其重命名以使其正常运行。
像往常一样,由于您的程序现在具有并发性,因此您需要关心数据竞争。 当前,这似乎很好,因为树中的所有节点都是不同的,因此异步调用不会彼此共享任何数据。 但是请牢记任何将来的变化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.