模板化的 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>

并且 onetwo 都以 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) {