1

我正在尝试以下代码来重载一个简单的函数以适用于多种类型。但是,它无法编译。有人可以告诉我出了什么问题以及如何解决这个问题吗?

typedef struct str1_type
{
    int f1;
    int f2;
} STR1;

typedef struct str2_type
{
    char f1[100];
    char f2[100];
}STR2;

template <typename T1, typename T2>
T2 getFieldOffset(const T1& t, int i);

int main() {

    STR1 str1;
    STR2 str2;

    int i = getFieldOffset(str1,0);

    const char* test = getFieldOffset(str2,0);

}

template <typename T1, typename T2>
T2 getFieldOffset(const T1& t, int i)
{
    switch (i) {
        case 0:
            return t.f1;
        case 1:
            return t.f2;
        default:
        {
            cout << "Invalid index passed: i" << i << endl;
            return null;
        }
    }
}

这是错误消息:

test2.cpp:在函数'int main()'中:
test2.cpp:73:错误:没有匹配函数调用'getFieldOffset(STR1&,int)'
test2.cpp:75:错误:没有匹配函数调用' getFieldOffset(STR2&, int)'

test2.cpp:在函数'T2 getFieldOffset(const T1&,int)'中:
test2.cpp:90:错误:'null'未在此范围内声明

4

4 回答 4

8
template <typename T1, typename T2> 
T2 getFieldOffset(const T1& t, int i); 

只能从参数T1中推导出模板参数,因此您必须在T2调用时在模板参数列表中显式提供模板参数。

但是,如果您使用编写的函数模板,则必须为两个模板参数提供参数。您应该交换T1T2在模板参数列表中的位置,以便您只需要指定T2

template <typename T2, typename T1> 
T2 getFieldOffset(const T1& t, int i);   

或者,为模板参数使用更好的名称:

template <typename TReturn, typename T> 
TReturn getFieldOffset(const T& t, int i);  

现在您可以将其称为:

getFieldOffset<ReturnType>(str1,0); 
于 2011-04-11T15:57:04.190 回答
4

编译器无法推断返回类型。一个原因是因为getFIeldOffset可能返回的值不是int,但可以转换为int。您必须指定返回类型何时为:

getFieldOffset<STR2,int>(str2,0);
于 2011-04-11T15:54:28.683 回答
2

看起来你应该写 NULL 而不是 null 并且所有这些都可以正常工作。

In function 'T2 getFieldOffset(const T1&, int)': test2.cpp:90: error: 'null' was not declared in this scope

问题在于模板实例化,编译器由于不正确的“null”而无法实例化模板,因此他没有考虑将模板用作函数调用的候选者的能力。

于 2011-04-11T15:56:38.790 回答
1
int i = getFieldOffset(str1,0);
const char* test = getFieldOffset(str2,0);

getFieldOffset是一个接受两种类型参数的函数模板。但是在上面的代码中,您没有提供类型参数。您希望编译器推断它们。但是编译器只能推导出函数参数类型,不能推导出返回类型。因此错误。

您必须提供两个类型参数:

int i = getFieldOffset<STR1, int>(str1,0);
const char* test = getFieldOffset<STR2, char*>(str2,0);

但是,如果您将函数模板中的类型顺序颠倒

template <typename T1, typename T2>
T1 getFieldOffset(const T2& t, int i); //T1 (i.e 1st type) becomes returnType!!

那么你可以在调用函数时只提供一种类型,即返回类型;另一种类型可以从函数参数中推导出来:

int i = getFieldOffset<int>(str1,0);
const char* test = getFieldOffset<char*>(str2,0);
于 2011-04-11T15:56:24.650 回答