我在解释我的Interpreter设计模式时遇到了问题。我想实施的BNF是:
<表达> :: =< expression> “AND”< expression> | <字面>
<字面> :: =“A”| “B”| 1 | 2
我在谈论以下设计模式:Interpreter
诀窍是,我想允许LiteralExpression返回int和string类型,但只返回Expression的字符串。这不起作用,因为这违反了Liskov substitution principle。接下来,我尝试使基类更通用。看起来不错,“唯一的字符串”版本正在编译,我已经将LiteralExpression的int实例添加到main。代码不编译说
没有用于调用Expression<std::string>::Expression(LiteralExpression<int>&, LiteralExpression<int>&)
我认为问题在于,
Expression(Expression const &leftExpression, Expression const rightExpression)
构造函数不允许具有与构造它的T
不同的左右表达式模板类型。我必须完全实现
Expression(Expression<int> const &leftExpression,
Expression<int> const &rightExpression)
Expression(Expression<int> const &leftExpression,
Expression<string> const &rightExpression)
Expression(Expression<string> const &leftExpression,
Expression<int> const &rightExpression)
Expression(Expression<string> const &leftExpression,
Expression<string> const &rightExpression)
版本。这就是我想要避免的。我怎么能这样做?
在构造函数中&lt;&lt;应该为我照顾不同的类型。
我已经检查了与我的问题有些相关的堆栈溢出注释。我试图理解并应用类型擦除,但无法实现。
我试图在Expression和LiteralExpression协变中使用GetResult()的类型(标准§10.3[class.virtual] / p7),所以它是指针。没有帮助(这完全不相关吗?)。
对不起,很长的帖子。请帮忙。
我的代码如下所示:
// main.cpp
#include <iostream>
#include "LiteralExpression.h"
using std::cout;
using std::endl;
int main() {
LiteralExpression<string> a("A");
LiteralExpression<string> b("B");
Expression<string> shortExpression(a, b);
cout << *shortExpression.GetResult() << endl;
LiteralExpression<int> one(1);
LiteralExpression<int> two(2);
Expression<string> shortExpression2(one, two);
cout << *shortExpression2.GetResult() << endl;
return 0;
}
// LiteralExpression.h
#ifndef LITERALEXPRESSION_H_
#define LITERALEXPRESSION_H_
#include "Expression.h"
template<class T>
class LiteralExpression: public Expression<T> {
public:
LiteralExpression(string literal) {
this->_result = (literal == "A" || literal == "B") ? new string(literal) : new string("");
}
LiteralExpression(int literal) {
this->_result = (literal == 1 || literal == 2) ? new int(literal) : new int(0);
}
virtual ~LiteralExpression() {
delete this->_result;
}
virtual T *GetResult() const {
return this->_result;
}
protected:
T *_result;
};
#endif /* LITERALEXPRESSION_H_ */
// Expression.h:
#ifndef EXPRESSION_H_
#define EXPRESSION_H_
#include <string>
#include <sstream>
using std::string;
using std::stringstream;
template<class T>
class Expression {
public:
virtual ~Expression() {
delete this->_result;
}
Expression(Expression const &leftExpression, Expression const &rightExpression) {
stringstream result;
result << *(leftExpression.GetResult()) << " AND " << *(rightExpression.GetResult());
this->_result = new string(result.str());
}
// making it more generic by changing from
// virtual string *GetResult() const {
// to
virtual T *GetResult() const {
return this->_result;
}
protected:
T *_result;
Expression() {
this->_result = 0;
}
};
#endif /* EXPRESSION_H_ */
答案 0 :(得分:0)
您的LiteralExpression
班级使用CRTP
template<class T>
class LiteralExpression : public Expression<T>
one
和two
都有Expression<int>
作为基类
LiteralExpression<int> one(1);
LiteralExpression<int> two(2);
将它们传递给Expression<string>
构造函数
Expression<string> shortExpression2(one, two);
// where
template<class T>
class Expression {
Expression(Expression const &leftExpression, Expression const &rightExpression) {
你问的是同样的事情:
template<class T>
class Expression {
Expression(Expression<T> const &leftExpression, Expression<T> const &rightExpression) {
自14.6.2.1/1开始说
名称是指当前实例化,如果它是
- 在类模板的定义中,类的嵌套类 模板,类模板的成员或嵌套类的成员 类模板,类的注入类名(第9节) 模板或嵌套类,[...]
显然是Expression<int> != Expression<string>
。
作为一种解决方案,除了采用更简单的继承设计之外,关于模板,你可以做一些像
这样的事情。template<class U, class V> // Base classes could be anything and this works
Expression(Expression<U> const &leftExpression, Expression<V> const &rightExpression) {