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)。我不想将 function1 拆分为两个不同的函数,因为会有很多重复的代码。还有其他方法吗?

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_xxMatrix_1D,重载将选择第一个重载,如果是 Matrix_2D,重载将选择第二个重载,如果是其他,则不会编译。但是如果有人提供了新类型的矩阵,他们可以通过为它定义来编译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

您不能将参数作为对readFromFilea 的引用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 回答