0
は考えてみましょう:スカラーDSLと型付き演算子:慣用的な実装ですか?
val a:ExpressionT[Int] = Const(1)
val b:ExpressionT[Float] = Const(2.0f)
// + must raise types:
// (i+i) -> i
// (i+f) -> f
// (f+i) -> f
// (f+f) -> f
val c:ExpressionT[Float] = a+b
:
// A typed Expression
trait ExpressionT[T] extends Expression{
def evaluate(): T
}
class Const[T<:Any](value:T) extends ExpressionT[T] {
def evaluate(): T = value
}
object Const {
def apply(value:Int) = new Const[Int](value)
def apply(value:Float) = new Const[Float](value)
}
すべての数値型のために動作します+演算子を実装するための最もエレガントな方法は何ですか?タイプのすべての組み合わせを列挙しないようにする方法はありますか? Cでは
++この我々は単に(メモリから)することができます:
template <typename T>
class ExpressionT {
typedef typename T EvalT;
virtual T evaluate() const = 0;
}
// HighestType<X,Y>::EvalT,
// (int,float) --> float
// (float,int) --> float
// (int,int) --> int
template <typename X, typename Y>
class Add : public ExpressionT< HighestType<X::EvalT, Y::EvalT>::EvalT > {
Add(Expression<X> const& l, Expression<X> const& r) {...}
inline ResultT evaluate() { return l+r; }
}
template <typename X, typename Y>
auto operator + (Expression<T> const& lhs,
Expression<T> const& rhs){
return Add(lhs, rhs);
}
...何ごと型ケースを必要としないこれ、また楽しく、+(LHS、RHS)が定義されていない場合、コンパイルに失敗します。追加の作業をすることなく、新しい目に見えない型+(int、Matrix)、+(Matrix、float)への拡張を直接的に許可します。