diff --git a/question_exp.h b/question_exp.h index 87298d295479b1ccc8c72ac86d9b9404145b9866..357391937f514fdb604c6a99f94b98c703bc47ff 100644 --- a/question_exp.h +++ b/question_exp.h @@ -89,7 +89,8 @@ public: virtual bool is_composite() const {return false;} virtual int get_depth() const {return 1;} virtual void show_immediate_value() const {} - virtual void clear() {} + virtual void safe_delete() const {} //used in qme::safe_delete function, do not call it directly + virtual void clear() {} //used in qme::safe_delete function, do not call it directly }; ///////////////////////////////////////////////////////////////////////////////////////// @@ -119,6 +120,8 @@ public: virtual std::shared_ptr> to_negative() const = 0; virtual T operator()(const std::function&) const = 0; + //used in qme::safe_execute function, do not call it directly + virtual T safe_execute(const std::function& cb) const {return operator()(cb);} }; ///////////////////////////////////////////////////////////////////////////////////////// @@ -395,6 +398,7 @@ public: } } + virtual T safe_execute(const std::function&) const {throw("unsupported safe execute operation!");} virtual void clear() {dexp_l.reset(); dexp_r.reset();} private: @@ -842,7 +846,10 @@ template inline int travel_exp(const T& exp, const std::function& backtrack_handler) { if (!exp->is_composite()) + { + left_handler(exp); return 1; + } auto depth = 1, max_depth = 0; std::list> exps; //true - left branch, false - right branch @@ -941,20 +948,13 @@ private: T value; }; -template class question_exp; template inline T safe_execute(const std::shared_ptr>& dexp, const std::function& cb) { - auto qexp = std::dynamic_pointer_cast>(dexp); - if (qexp) //for question_exp, recursion still happens here - return qexp->safe_execute(cb); - else if (!dexp->is_composite()) - return (*dexp)(cb); - std::list> res; travel_exp>>(dexp, - [&](const std::shared_ptr>& data) {res.emplace_back(safe_execute(data, cb));}, + [&](const std::shared_ptr>& data) {res.emplace_back(data->safe_execute(cb));}, [](const std::shared_ptr>&) {return false;}, - [&](const std::shared_ptr>& data) {res.emplace_back(safe_execute(data, cb));}, + [&](const std::shared_ptr>& data) {res.emplace_back(data->safe_execute(cb));}, [&](const std::shared_ptr>& data) { T re = res.back(); res.pop_back(); @@ -967,16 +967,10 @@ template inline T safe_execute(const std::shared_ptr>& template inline void safe_delete(const std::shared_ptr>& dexp) { - auto qexp = std::dynamic_pointer_cast>(dexp); - if (qexp) //for question_exp, recursion still happens here - return qexp->safe_delete(); - else if (!dexp->is_composite()) - return; - travel_exp>>(dexp, - [](const std::shared_ptr>& data) {safe_delete(data);}, + [](const std::shared_ptr>& data) {data->safe_delete();}, [](const std::shared_ptr>&) {return false;}, - [](const std::shared_ptr>& data) {safe_delete(data);}, + [](const std::shared_ptr>& data) {data->safe_delete();}, [](const std::shared_ptr>& data) {data->clear();} ); } @@ -995,15 +989,12 @@ public: virtual bool operator()(const std::function&) const = 0; //is recursion fully eliminated or not depends on the data_exp(s) this judge_exp holds + //used in qme::safe_execute function, do not call it directly virtual bool safe_execute(const std::function&) const = 0; - virtual void safe_delete() const = 0; }; template inline bool safe_execute(const std::shared_ptr>& jexp, const std::function& cb) { - if (!jexp->is_composite()) - return jexp->safe_execute(cb); - auto re = false; travel_exp>>(jexp, [&](const std::shared_ptr>& judge) {re = judge->safe_execute(cb);}, @@ -1028,9 +1019,6 @@ template inline bool safe_execute(const std::shared_ptr inline void safe_delete(const std::shared_ptr>& jexp) { - if (!jexp->is_composite()) - return jexp->safe_delete(); - travel_exp>>(jexp, [](const std::shared_ptr>& judge) {judge->safe_delete();}, [](const std::shared_ptr>&) {return false;}, @@ -1233,7 +1221,6 @@ public: } virtual bool safe_execute(const std::function&) const {throw("unsupported safe execute operation!");} - virtual void safe_delete() const {throw("unsupported safe delete operation!");} virtual void clear() {jexp_l.reset(); jexp_r.reset();} protected: @@ -1302,10 +1289,12 @@ public: virtual T operator()(const std::function& cb) const {return (*jexp)(cb) ? (*dexp_l)(cb) : (*dexp_r)(cb);} + //for question_exp, recursion still happens here if this question_exp is a sub expression virtual T safe_execute(const std::function& cb) const {return qme::safe_execute(jexp, cb) ? qme::safe_execute(dexp_l, cb) : qme::safe_execute(dexp_r, cb);} - void safe_delete() {qme::safe_delete(jexp); qme::safe_delete(dexp_l); qme::safe_delete(dexp_r);} + //for question_exp, recursion still happens here if this question_exp is a sub expression + virtual void safe_delete() const {qme::safe_delete(jexp); qme::safe_delete(dexp_l); qme::safe_delete(dexp_r);} protected: std::shared_ptr> clone() const {return std::make_shared>(jexp, dexp_l, dexp_r);}