1

opencv では、次のように Mat のオブジェクトを作成できます。

Mat mat = (Mat_<int>(2, 3) << 1, 2, 3, 4, 5, 6);

したがって、 のインスタンスを初期化すると便利Mat_<type>です。カスタムの単純化された行列クラスがある場合は、Mat2Dこのパターンを使用しますが、どうすればよいでしょうか?
更新:可変長のパラメーター リストを使用しようとしましたが、error C2829: 'operator <<' cannot have a variable parameter list.

4

2 に答える 2

3

警告: これを行わないでください。あなたは警告されました。

演算子のオーバーロードを使用してこれを実現できますが、後で説明するように、これは非常に悪い考えです。

Matクラスには、 を受け取るコンストラクターがあると仮定しますMat_<int>

クラス テンプレートには、単一の要素を行列に挿入する方法を知っているMat_<T>というメソッドがあると仮定します。Insert()あなたに解決してもらいますが、挿入する場所を知る方法が必要です。

このメソッドを使用すると、簡単にオーバーロードできoperator<<ます。

template<typename T>
Mat_<T>& operator<<(Mat_<T>& mat, const T& el)
{
  mat.Insert(el);
  return mat;
}

そして、これをオーバーロードしてオーバーロードoperator,することができますoperator<<:

template<typename T>
Mat_<T>& operator,(Mat_<T>& mat, const T& el)
{
  return mat << el;
}

すべてが正常に機能し、構文を使用できます。ここで、なぜこれが悪い考えなのかを説明します。

このようにオーバーロードoperator<<することは完全に理にかなっています。これは挿入演算子であり、オーバーロードは要素をマトリックスに挿入します。これは誰もが予想することです。ここまでは順調ですね。

しかし、オーバーロードoperator,はそうではありません。この演算子の意味は、「2 つの式を評価し、最後の式を返す」ことです。これは明らかに、オーバーロードされた演算子が行うことではありません。,不注意なユーザーは、標準的な方法 (たとえば、ループ内) で演算子を使用しようとしfor、コードが機能しない理由を理解できません。コードを使用する人に嫌われたくない場合を除き、非標準操作を行うために演算子をオーバーロードしないでください。おそらく後で自分自身。

実際、標準ではオーバーロードが許可operator,されていますが、標準操作を実行するコードを作成することは不可能であるため、これはおそらく絶対に行うべきではありません。これは、下位互換性のために保持されている標準の誤りと見なすことができます。

そして、オーバーロードoperator,を 2 つ取りint、何らかの方法でそれらをまとめることを検討している場合、欠点がさらに深刻であるだけでなく、すべてのオペランドが組み込み型である場合に演算子をオーバーロードすることは違法です。

つまり、要約すると、それを行うことはできますが、それは悪い考えであり、コードの予期しない場所でバグが発生する可能性があります。

于 2012-10-02T15:43:48.197 に答える
1

これは、単純なDSLとしてインサーターとコンマ演算子を使用した、ビルダーパターンと流暢なインターフェイスの組み合わせです。DSLはこれらの演算子が適用される非常に特殊なコンテキストを定義しているため、(適切に実行された場合)いかなる種類の危険も見られません。インスピレーションを探している場合は、boost::assignをご覧ください。とにかく、私は演算子の代わりに口頭のDSL要素を使用しますが、これは私の個人的な好みの問題です...

于 2012-10-02T15:57:08.887 に答える