必要以上に複雑なソリューションを目指しているのではないかと感じているので、最初から構築を開始し、詳細は後で説明します。まず、提案された構文とその意味の分析を開始します。
friend vector3 operator*(const vector3 &v, const matrix4t &m);
template <typename scalarT>
friend scalarT operator*(const scalarT &inputSclT, const matrix4t &inputM4t);
これらは友達宣言です。Friend 宣言は、クラスの外部にエンティティを宣言し(存在することをコンパイラに伝えます)、そのようなエンティティには、このクラスの内部 (この場合はテンプレート) へのフル アクセスを許可する必要があります。2 番目のフレンド宣言は、const 参照によって型とオブジェクトの両方operator*
を取り、値を生成するフリー関数テンプレートです。このフレンド宣言は奇妙に思えます。スカラー値による行列の乗算は、通常、単なるスカラー値ではなく、同じ次元の別の行列を生成します。scalarT
matrix4T<T>
scalarT
クラス テンプレート内では、テンプレートの名前はテンプレートmatrix4t
を参照するのではなく、特定の特殊化を参照することに注意してください (つまりmatrix4t<T>
、テンプレートの名前ではなく、 を表します)。この区別は今は重要ではないように思えるかもしれませんが、遅かれ早かれその重要性に気付くでしょう。
2 番目の宣言は、 const 参照によってaと a の両方operator*
を受け取り、別の を生成するテンプレート化されていないフリー関数です。の定義内にあるため、テンプレートの名前は特殊化を参照しますが、テンプレートのみを参照し、特定のインスタンス化は参照しません。特定の typeを受け入れるテンプレートにするか、単一の型 (テンプレートの引数にすることができます)を受け入れるテンプレート化されていない関数にする必要があります。他の宣言と同じように、戻り値がオフになる場合とオフになる場合があります...ベクトルの次元が何であるかに依存します(行または列ですか?)vector3
matrix4t
vector3
matrix4t
matrix4t<T>
vector3
vector3<U>
U
T
vector3<T>
実際の友達関係については、別の同様の質問に対するこの回答を読むことをお勧めします。
実際の演算子として、スカラー型の場合、次のアプローチをお勧めします。
operator*=
格納されているのと同じ型のスカラーを引数として取る実装
- の両方のバージョンを実装
operator*
するoperator*=
.
template <typename T> class matrix4t {
public:
matrix4t& operator*=( T scalar ); // and implement
friend matrix4t operator*( matrix4t lhs, T scalar ) {
return lhs*=scalar;
}
friend matrix4t operator*( T scalar, matrix4t rhs ) {
return rhs*=scalar;
}
};
注:operator*=
行列を左辺として一度実装します (行列を右辺としてオーバーロードを提供することもできますが、少し奇妙に見えます:5 *= matrix
行列を生成します...)。に転送することにより、無料の関数として実装operator*
します(友情は、インスタンス化する型ごとに無料の関数を提供するためにのみ使用されます。リンクされた回答を読んでください)operator*=
。
ベクトルで乗算する場合 (対称ではないため)、単一の実装にディスパッチするトリックは機能しませんが、上記のようにテンプレート化されていないフレンドとして 2 つの実装を提供できます。
混合タイプの操作を提供したい場合は、上記のすべてをテンプレートにする必要があります。追加された複雑さはテンプレートではなく、タイプをプロモートしたい場合に結果タイプがどうあるべきかを決定することです。C++11 では、最も簡単な方法は、decltype
戻り値の型を使用して末尾に置くことです。
template <typename U>
friend auto operator*( matrixt4 lhs, U scalar ) -> matrix4t< decltype(scalar * element(0,0) ) > {
// implement here
}
についても同様ですoperator*(scalar,matrix)
。型をプロモートしている場合、operator*=
(型が lhs と同じであるため) はまったく意味をなさない可能性があることに注意してください。それを行うことを検討する場合、 は参照によって引数operator+
を取得しmatrix4t<A>
(適切な型ではない可能性があるため)、matrix4t<B>
戻り値の型にコピーする必要があります (ここでA
、 とB
はそれぞれ、乗算される行列と結果の型です)。
ここから先は、必要なものや実装したいものを決定する必要があり、より具体的な質問が寄せられたときに尋ねたいと思うかもしれません。