私は、テンプレートの表現パターンをJavaで模倣できるかどうか、ループの融合などの最適化を試みています。一例として、Javaで汎用クラス型を渡す
、IポートJavaクラスにこの式テンプレートの例で見つかったC++クラス:https://en.wikipedia.org/wiki/Expression_templates#Motivation_and_example
はまず、ベクトル表現を表すテンプレートクラスVecExpression<E>
。テンプレートパラメータE
を使用し、クラスタイプE
をコンストラクタパラメータとして使用します。その後E
public abstract class VecExpression <E> {
private VecExpression thisAsE;
public VecExpression(Class<E> type) throws Exception {
if(type.isInstance(this)) {
thisAsE = (VecExpression)type.cast(this);
}
else {
throw new Exception("Class type must extend VecExpression");
}
}
public double get(int i) {
return thisAsE.get(i);
}
public int size() {
return thisAsE.size();
}
}
第二に、スーパーコンストラクタにVec.class
を渡し、VecExpression<E>
クラスで呼び出さget()
とsize()
メソッドを実装しVecExpression<Vec>
を拡張するクラスVec
のクラスタイプにthis
キャストにプライベート変数thisAsE
セットを作成します。
public class Vec extends VecExpression<Vec> {
private double[] elems;
public <E> Vec(VecExpression<E> expression) throws Exception {
super(Vec.class);
for(int i = 0; i < expression.size(); ++i) {
elems[i] = expression.get(i);
}
}
public Vec(double[] elems) throws Exception {
super(Vec.class);
this.elems = elems;
}
public double get(int i) {
return elems[i];
}
}
第三、VecExpression<VecSum<E1, E2>
を拡張し、2つのVecExpression<E>
Sの合計を返すために、そのget()
方法を使用してテンプレートクラスVecSum<E1, E2>
。型は明示的なパラメータClass<VecSum<E1, E2>> type
として渡されます。
public class VecSum <E1, E2> extends VecExpression<VecSum<E1, E2>> {
private VecExpression u;
private VecExpression v;
public VecSum(Class<VecSum<E1, E2>> type, VecExpression<E1> u, VecExpression<E2> v) throws Exception {
super(type);
if(u.size() != v.size()) {
throw new Exception("Vectors must be of the same size");
}
this.u = u;
this.v = v;
}
public double get(int i) {
return u.get(i) + v.get(i);
}
public int size() {
return v.size();
}
}
最後に、式テンプレートを使用して、メモリを1回通過する3つのベクトルを追加できるクラスを生成します。ルイ・ワッサーマンさんのコメント
あたりとして編集
public class Main {
public static void main(String[] args) throws Exception {
Vec a = new Vec(new double[] {1, 2, 3});
Vec b = new Vec(new double[] {1, 2, 3});
Vec c = new Vec(new double[] {1, 2, 3});
VecSum<Vec, Vec> ab = new VecSum<Vec, Vec>(VecSum<Vec, Vec>.class, a, b);
VecSum<VecSum<Vec, Vec>, Vec> abc = new VecSum<>(VecSum<VecSum<Vec, Vec>, Vec>.class, ab, c);
}
}
式はパラメータ化された型からクラスを取得しようとしているのでしかし、VecSum
コンストラクターに渡されるクラスの種類は動作しません。 Louisは、ジェネリッククラスの実装は、C++のように異なるクラスにコンパイルしないと指摘しました。どのように型を渡すか、あるいは式テンプレートパターンに別のアプローチがありますか?
"SomeClass、SomeClass など...別のクラスにコンパイルしないでください"いいえ、彼らはJavaではありません。 –
"異なるクラスにコンパイルしてはいけませんか?"いいえ。 [type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html)を参照してください – bradimus
「タイプ消去」を検索してください:https://docs.oracle.com/javase/tutorial/ java/generics/erasure.html – Spoke44