函数模板重载:const * vs. const&

时间:2013-05-15 14:50:18

标签: c++ templates overloading

当我有两个模板化函数重载时,如下所示:

template<class T>
void foo( T const& )
{
    // do something with a const reference
    cout << "const reference version";
}

template<class T>
void foo( T const* )
{
    // do something with a const pointer
    cout << "const pointer version";
}

为什么编译器在使用非常量指针类型实例化时会选择第一个版本?

int* bar;
foo( bar ); // prints "const reference version"

char const* baz;
foo( baz ); // prints "const pointer version"

4 个答案:

答案 0 :(得分:4)

原因是因为bar是一个非常量指针,所以int* const&实际上比int const*更好,因为它不必添加const指针类型。

如果bar符合const条件,那么它将与T const*版本完全匹配。

答案 1 :(得分:2)

#include <iostream>
using namespace std;
void foo(int const&) {
    cout << "const reference" << endl;
}

void foo(int const*) {
    cout << "const pointer" << endl;
}

int main() {
    int *hi;
    foo (hi);   //const pointer
    foo((*hi)); //const reference
    foo(&(*hi));//const pointer
}

这里的交易是参考和指针是不同的。指针是一种唯一类型,其中作为对值的引用与值本身没有区别,或者更确切地说,是对象的别名。因此,例如,上面代码的这个版本将无法编译。

#include <iostream>
using namespace std;
void foo(int const&) {
    cout << "const reference" << endl;
}

void foo(int) {
    cout << "hi there" << endl;
}

int main() {
    int hi;
    foo(hi); //const reference
}

因为foo的声明含糊不清。编译器无法在它们之间做出决定。

答案 2 :(得分:1)

您可以使用typeid确定模板类型的内容。

#include <iostream>
#include <typeinfo>
using namespace std;

template<class T> void foo( T const& ) {
    cout << "const reference version T="<< typeid(T).name()<<endl;
}

template<class T> void foo( T const* ) {
    cout << "const pointer version T="<<typeid(T).name()<<endl;
}

int main() {
    int* i_ptr=0;
    foo(i_ptr);

    const int* ci_ptr=0;
    foo(ci_ptr);    
}

此输出(注意确切输出将取决于您的编译器)

const reference version T=Pi
const pointer version T=i

这表明在第一种情况T = int*中,完整参数类型为int* const&,在第二种T=int中,完整参数类型为int const *

答案 3 :(得分:0)

template<class T> void foo( T const* )需要T上的const指针。好吧,如果这是你唯一的声明,那么当你试图将非常量指针作为参数传递时,会出现编译错误。

使用template<class T> void foo( T const& )T类型推断为int*,它是通过引用该函数给出的。