【模板】类型转换与模板类型参数

  与非模板函数一样,我们在一次调用中传递给模板的实参被用来初始化函数的形参。如果一个函数形参的类型使用了模板类型参数,那么它采用特殊的初始化规则。只有很有限的几种类型转换会自动地用于这些实参。编译器通常不是对实参进行类型转换,而是生成一个新的模板实例。

  与往常一样,顶层const无论是在形参还是在实参中,都会被忽略。在其它类型转换中,能在调用中应用于函数模板的包括如下两项。

  • const转换:可以将一个非const对象的引用(或指针)传递给一个const引用(或指针)形参。
  • 数组或函数指针转换:如果函数形参不是引用类型,则可以对数组或函数类型的实参应用正常的指针转换。一个数组的实参可以转换为一个指向其首元素的指针。类似的,一个函数实参可以转换为一个该函数类型的指针。

其它类型转换,如算数转换、派生类向基类的转换以及用户自定义转换,都不能应用于函数模板。

  作为一个例子,考虑对函数fobj和fref的调用。fobj拷贝它的参数,而fref的参数是引用类型:

template <typename T> T fobj(T, T); //实参被拷贝
template <typename T> T fref(const T &, const T &); //引用

int main()
{
    string s1("a value");
    const string s2("another value");

    fobj(s1, s2); //调用fobj(string, string); const被忽略
    fref(s1, s2); //调用freg(const string &, const string &)
                  //将s1转换为const是允许的

    int a[10], b[42];
    fobj(a, b); //调用f(int *, int *)
    //fref(a, b); //错误,数组类型不匹配
}

  在第一对调用中,我们传递一个string和一个const string。虽然这些类型不是严格匹配,但两个调用都是合法的。在fobj调用中,实参被拷贝,因此原对象是否const没有关系。在fref调用中,参数类型是const的引用。对于一个引用参数来说,转换为const是允许的,因此这个调用时合法的。

  在下一组调用中,我们传递了数组实参,两个数组大小不同,因此是不同类型。在fobj调用中,数组大小不同无关紧要。两个数组都被转换为指针。fobj中的模板类型为int*。但是,fref是不合法的。如果形参是一个引用,则数组不会转换为指针。a和b的类型不匹配,因此调用是错误的。

猜你喜欢

转载自www.cnblogs.com/bootblack/p/11419049.html