8

当我有两个这样的模板化函数重载时:

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

4 回答 4

5

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

如果barconst合格的,那么它将与T const*版本完全匹配。

于 2013-05-15T15:02:56.857 回答
3
#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 的声明是模棱两可的。编译器无法在它们之间做出决定。

于 2013-05-15T15:11:59.390 回答
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 *

于 2013-05-15T15:15:40.767 回答
0

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

推断template<class T> void foo( T const& )的类型是通过引用函数给出的。Tint*

于 2013-05-15T15:05:49.663 回答