模板化的 C++ 参数无法正确找到类型
templated c++ arguments cannot find out type properly
我在推广我的解释器设计模式时遇到了问题。我想实现的 BNF 是:
<表达式> ::= <表达式> " AND " <表达式> | <文字>
<文字> ::= "A" | "B" | 1 | 2
我说的是以下设计模式:Interpreter
诀窍是,我想允许 return 整型和字符串类型的 LiteralExpression,但只允许表达式的字符串。那是行不通的,因为那违反了 Liskov substitution principle。接下来,我尝试使基础 class 更通用。看起来不错,"only string" 版本正在编译,我已将 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)
版本。这就是我想要避免的。我该怎么做?
在构造函数中,<< 应该为我处理不同的类型。
我已经检查了与我的问题有些相关的堆栈溢出评论。我试图理解和应用类型擦除,但无法做到。
我试图使 GetResult() 的表达式和 LiteralExpression 协变(标准 §10.3 [class.virtual]/p7)类型,所以它是指针。没有帮助(完全不相关吗?)。
抱歉这么久 post。请帮忙。
我的代码如下所示:
// 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_ */
您的 LiteralExpression
class 使用 CRTP
template<class T>
class LiteralExpression : public Expression<T>
并且 one
和 two
都以 Expression<int>
作为基础 class
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 说
A name refers to the current instantiation if it is
— in the definition of a class template, a nested class of a class
template, a member of a class template, or a member of a nested class
of a class template, the injected-class-name (Clause 9) of the class
template or nested class, [...]
显然 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) {
我在推广我的解释器设计模式时遇到了问题。我想实现的 BNF 是:
<表达式> ::= <表达式> " AND " <表达式> | <文字>
<文字> ::= "A" | "B" | 1 | 2
我说的是以下设计模式:Interpreter
诀窍是,我想允许 return 整型和字符串类型的 LiteralExpression,但只允许表达式的字符串。那是行不通的,因为那违反了 Liskov substitution principle。接下来,我尝试使基础 class 更通用。看起来不错,"only string" 版本正在编译,我已将 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)
版本。这就是我想要避免的。我该怎么做?
在构造函数中,<< 应该为我处理不同的类型。
我已经检查了与我的问题有些相关的堆栈溢出评论。我试图理解和应用类型擦除,但无法做到。
我试图使 GetResult() 的表达式和 LiteralExpression 协变(标准 §10.3 [class.virtual]/p7)类型,所以它是指针。没有帮助(完全不相关吗?)。
抱歉这么久 post。请帮忙。
我的代码如下所示:
// 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_ */
您的 LiteralExpression
class 使用 CRTP
template<class T>
class LiteralExpression : public Expression<T>
并且 one
和 two
都以 Expression<int>
作为基础 class
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 说
A name refers to the current instantiation if it is
— in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name (Clause 9) of the class template or nested class, [...]
显然 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) {