链接器在编译D模板时出错
这是一种简单语言的解释器的一部分。该语言还包括字符串、列表、函数等以及计算器中相应的函数evalString、evalList等函数。仅显示Number子类和evalNumber函数链接器在编译D模板时出错,d,D,这是一种简单语言的解释器的一部分。该语言还包括字符串、列表、函数等以及计算器中相应的函数evalString、evalList等函数。仅显示Number子类和evalNumber函数 Evaluator.evaluate函数调用Expr.eval,每个Expr子类调用正确的Evaluator函数(evalNumber,evalString,evalList等)对表达式求值 import std.stdio; import std.string; abstract class Expr {
Evaluator.evaluate
函数调用Expr.eval
,每个Expr
子类调用正确的Evaluator
函数(evalNumber
,evalString
,evalList
等)对表达式求值
import std.stdio;
import std.string;
abstract class Expr {
Out eval(Out)(Evaluator!Out evaluator);
}
class Number: Expr {
double num;
this(double _num) { num = _num; }
override Out eval(Out)(Evaluator!Out evaluator) {
return evaluator.evalNumber(this);
}
}
class Evaluator(Out) {
Out evaluate(Expr expr) {
return expr.eval(this); // ### Error is here ###
}
abstract Out evalNumber(Number number);
}
class ExprPrinter: Evaluator!string {
override string evalNumber(Number num) {
return format("%s", num.num);
}
}
void main() {
Number n = new Number(5);
auto printer = new ExprPrinter();
writefln("Number: %s", printer.evaluate(n));
}
当我试图建造它时,我得到了
example.o: In function `_D7example__T9EvaluatorTAyaZQp8evaluateMFCQBo4ExprZQBb':
/home/neniu/projects/duover/source/example.d:19: undefined reference to `_D7example4Expr__T4evalTAyaZQkMFCQBf__T9EvaluatorTQBaZQpZQBh'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
example.o: In function `_D7example__T9EvaluatorTAyaZQp8evaluateMFCQBo4ExprZQBb':
/home/neniu/projects/duover/source/example.d:19: undefined reference to `_D7example4Expr__T4evalTAyaZQkMFCQBf__T9EvaluatorTQBaZQpZQBh'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
如果我读错了,编译器会说第19行的expr.eval
引用了一个未定义的函数(在本例中,Number.eval
函数应该是该函数)
我试着将第19行改为包括我们的专业
return expr.eval!Out(this);
但这根本没什么区别
我错过了什么?如何获得expr.eval(this)
调用以解析为Number.eval
这是与DMD2.081.1
多谢各位
*&当我试图建造它时,我得到了
example.o: In function `_D7example__T9EvaluatorTAyaZQp8evaluateMFCQBo4ExprZQBb':
/home/neniu/projects/duover/source/example.d:19: undefined reference to `_D7example4Expr__T4evalTAyaZQkMFCQBf__T9EvaluatorTQBaZQpZQBh'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
example.o: In function `_D7example__T9EvaluatorTAyaZQp8evaluateMFCQBo4ExprZQBb':
/home/neniu/projects/duover/source/example.d:19: undefined reference to `_D7example4Expr__T4evalTAyaZQkMFCQBf__T9EvaluatorTQBaZQpZQBh'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
如果我读错了,编译器会说第19行的expr.eval(代码中有标记)引用了一个未定义的函数,但(在本例中)Number.eval函数应该是该函数
我试着将第19行改为包括我们的专业
return expr.eval!Out(this);
返回expr.eval!(这个)
但这根本没什么区别
我错过了什么?如何让expr.expr(此)调用解析为Number.eval
这是与DMD2.081.1
多谢各位
*编辑*
我尝试将Expr.eval
abstract(带或不带abstract
限定符)设置为类本身,因为这是每个子类必须重写的函数:
abstract class Expr {
abstract Out eval(Out)(Evaluator!Out evaluator);
}
但现在编译器抱怨
example.d(5): Error: function `example.Expr.eval!string.eval` final functions cannot be abstract
example.d(28): Error: template instance `example.Expr.eval!string` error instantiating
example.d(35): instantiated from here: Evaluator!string
我不希望Expr.eval
成为最终版本。我没有做任何事情使Expr.eval
成为最终版本。我不明白为什么这会使Expr.eval
成为最终版本。我如何使Expr.eval
不是最终版本,这样我就可以抽象它,这样我就可以——不,必须——重写它
将某物声明为抽象
(“您必须重写此函数”)与将其声明为最终
(“您不能重写此函数”)是否完全相反
将某物声明为抽象(“您必须重写此函数”)不是与将其声明为最终(“您不能重写此函数”)完全相反吗
是的。但是模板函数总是最终的。在我看来,override Out eval(Out)(Evaluator!Out Evaluator){
,应该有一条错误消息,但显然编译器选择保持沉默。您需要使eval
不是模板,或者移动它,使其不是成员函数
您所做的基本上是多重分派,它在中作为一个库实现。只知道您显示的代码,很难判断这是否正是您所需要的。
Expr.eval
需要了解Out
参数类型的唯一原因是因为我无法找到获取Evaluator.ev的方法aluate
以识别其输入的运行时类型。如果我可以执行以下操作
// In class Evaualor. Maybe (Out) is a parameter the class, not the method.
Out evaluate(Out)(Expr e) {
if (isType!Num(e)) {
return evalNum(cast(Num) e);
}
else if (isType!Str(e)) {
return evalStr(cast(Str) e);
}
else if (isType!List(e)) {
return evalList(cast(List) e);
}
and so on
}
然后Expr
将不需要了解求值器
或其求值
方法发出的类型
有没有这样一种方法来确定这类变量的实际运行时类型?这将节省我一些时间。这将解释为什么
eval.expr
没有定义。它没有定义是因为它是抽象的
,不能重新定义是因为它是最终的
(因为它是一个模板)。我同意编译器发出的嘎嘎声会很好。Out返回类型是一个参数,因为某些计算器/阶段(例如宏扩展、常量折叠)为下一阶段发出Expr
s,而某些(漂亮的打印机和其他语言的翻译程序)发出字符串。迭代非常简单,我可以将其克隆到单独的转换器和转换器基类中,并从中派生出每个阶段。Ooo。OpenMethods看起来可能正是我所追求的。我确实考虑了Clojure协议和多个分派,但不确定如何表达它。我确实需要进一步探索这一点但它看起来只是一张票,再次感谢您。另一个选项是将Expr
astruct
(而不是类)并添加一个ExprType type
字段,其中ExprType
是数字
、字符串
、列表
等的枚举。可以在运行时(在我的代码中,而不是在编译时在编译器的代码中)检查表达式类型并调度正确的计算器函数,并且因为struct Expr
无论如何都不能被子类化,所以模板化方法的final
性质是没有意义的,不是问题。