3

私はこのようなことをする必要があります:

template <typename Matrix_xx>
bool ProcessMatrix<Matrix_xx>::function1(Matrix_xx a) {
    int x, y;

    // ... some code here ... //

    if (Matrix_xx == Matrix_1D) {
        a->readFromFile(x);
    } else if (Matrix_xx == Matrix_2D) {
        a->readFromFile(x, y);
    } // ...

}

つまり、異なる関数を呼び出すかどうかは、テンプレート引数に依存します。Matrix_1D::readFromFile(int x) と Matrix_2D::readFromFile(int x, int y) しかないため、上記のコードはコンパイルされません。関数 1 を 2 つの異なる関数に分割したくありません。これは、二重化されたコードが多くなるからです。別の方法はありますか?

4

3 に答える 3

10

オーバーロードされた関数または明示的に特化されたテンプレートのいずれかで、型固有のコードをラップします。

void doReadFromFile(Matrix_1D &a, int x, int y)
{
    a->readFromFile(x);
}

void doReadFromFile(Matrix_2D &a, int x, int y)
{
    a->readFromFile(x, y);
}

template <typename Matrix_xx>
bool ProcessMatrix<Matrix_xx>::function1(Matrix_xx a) {
    int x, y;

    // ... some code here ... //

    doReadFromFile(a, x, y);
}

Matrix_xxisの場合Matrix_1D、オーバーロードは最初のオーバーロードを選択し、Matrix_2D の場合、オーバーロードは 2 番目のオーバーロードを選択し、それ以外の場合はコンパイルしません。しかし、誰かが新しいタイプの行列を提供した場合、そのための を定義することでコンパイルできますdoReadFromFile

これは、一般的に便利なトリックであり、標準ライブラリが「特性」を使用する理由です。特性は、誰かが提供するクラスに対して定義でき、クラス以外の型に対して定義できます。「特性」は、明示的に特殊化されたテンプレートまたはフリー関数の形式のいずれかであり、通常は引数依存のルックアップで検索されます (テンプレートではなく、引数の名前空間に配置されます)。

完全を期すために、明示的な特殊化は次のようになります。

template <typename Matrix_xx>
struct doReadFromFile {};

template <>
struct<Matrix_1D> struct doReadFromFile {
    void operator()(Matrix_1D &a, int x, int y) {
        a->readFromFile(x);
    }
}

template <>
struct<Matrix_1D> struct doReadFromFile {
    void operator()(Matrix_1D &a, int x, int y) {
        a->readFromFile(x, y);
    }
}
于 2012-10-11T07:17:51.627 に答える
1

readFromFileへの参照への引数を作成しvector、Matrix_xxインスタンスに入力するインデックスの数を決定させることができませんでしたか?これにより、条件付きチェックが不要になります。

于 2012-10-11T07:15:09.250 に答える
0

typeid 演算子を使用してこれを回避できます。

それを使用すると、コードは次のようになります。

template <typename Matrix_xx>
bool ProcessMatrix<Matrix_xx>::function1(Matrix_xx a) {
    int x, y;

    // ... some code here ... //

    if (typeid(Matrix_xx) == typeid(Matrix_1D)) {
        a->readFromFile(x);
    } else if (typeid(Matrix_xx) == typeid(Matrix_2D)) {
        a->readFromFile(x, y);
    } // ...
}

または、スイッチでそれを行うことができます:

switch(typeid(Matrix_xx))
{
    case typeid(Matrix_1D):
         a->readFromFile(x);
         break;

    case typeid(Matrix_2D):
        a->readFromFile(x,y);
        break;

    // etc, etc
}

[編集:]コンパイルできないと言う人のために、私が上に残したコードと、作業中のプロジェクトから取得した以下のコードの機能的な違いを知りたいと思っています:

pdfArray.h

#ifndef PDFARRAY_H
#define PDFARRAY_H

#include "pdfObj.h"
#include "pdfTypes.h"

class pdfArray : public pdfObj
{
public:
    pdfArray();
    pdfArray(const pdfArray &src);
    size_t size()
    {
        return(mArray->size());
    }
    void clear();

    ~pdfArray();

    template <typename T> void addItem(const T *newItem)
    {
        //cout << typeid(T).name() << endl;
        pdfObj *item = new T(*newItem);
        mArray->push_back(item);
    }
    pdfObj *getItem(unsigned int itemIndex);
    const bstring& toString();
    pdfArray &operator=(const pdfArray &src);
private:
    vecObjPtr *mArray;
};

#endif // PDFARRAY_H

pdfArray.cpp からの抜粋

pdfArray::pdfArray(const pdfArray &src)
{
    vecObjPtrIter iter;
    pdfObj *ptr;
    mArray = new vecObjPtr;

    for (iter=src.mArray->begin(); iter!=src.mArray->end(); iter++)
    {
        ptr = *iter;

        if (typeid(*ptr) == typeid(pdfString))
            addItem( (pdfString*)ptr );

        if (typeid(*ptr) == typeid(pdfInt))
            addItem( (pdfInt*)ptr );

        if (typeid(*ptr) == typeid(pdfFloat))
            addItem( (pdfFloat*)ptr );

        if (typeid(*ptr) == typeid(pdfArray))
            addItem( (pdfArray*)ptr );
    }
}
于 2012-10-11T07:03:17.290 に答える