【问题标题】:function template overloading: const* vs. const&函数模板重载:const* 与 const
【发布时间】:2013-05-15 14:50:17
【问题描述】:
当我有两个这样的模板化函数重载时:
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"
【问题讨论】:
标签:
c++
templates
overloading
【解决方案1】:
原因是因为bar是一个非常量指针,所以int* const&实际上是比int const*更好的匹配,因为它不必在指针类型上加上const。
如果bar 是const 合格,那么它将与T const* 版本完全匹配。
【解决方案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 的声明是模棱两可的。编译器无法在它们之间做出决定。
【解决方案3】:
您可以使用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 *。
【解决方案4】:
template<class T> void foo( T const* ) 需要 T 上的 const 指针。好吧,如果它是您拥有的唯一声明,那么当您尝试将非 const 指针作为参数传递时,将会出现编译错误。
使用template<class T> void foo( T const& ),推断出T 的类型是int*,它是通过引用函数给出的。