模板化的c ++参数无法正确找到类型

时间:2015-04-13 16:05:04

标签: c++ function templates arguments matching

我在解释我的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_ */

1 个答案:

答案 0 :(得分:0)

您的LiteralExpression班级使用CRTP

template<class T>
class LiteralExpression : public Expression<T>

onetwo都有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) {