Oli*_*ain 24 c++ templates c++11
考虑以下:
template <class T> void Foo(const T* x) {
std::cout << "I am the pointer overload" << std::endl;
}
template <class T> void Foo(const T& x) {
std::cout << "I am the reference overload" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
鉴于上述情况,我希望以下内容可以调用指针重载:
int* x;
Foo(x);
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.这对我来说似乎很奇怪,因为它const T*可以清楚地绑定到非const T和const T&can,但是指针变体似乎是"更适合".
对于我的应用程序,我希望调用指针变体.我可以通过额外的专业化来完成这项工作:
template <class T> void Foo(T* x) {
const T* const_x = x;
Foo(const_x);
}
Run Code Online (Sandbox Code Playgroud)
但那感到错误和不必要.有没有更好的办法?我不理解的是什么(除了标准的xyz部分说这是这样的)?
bol*_*lov 26
你在想:如果我的参数不是常量(或者如果参数是常量的)那么指针将是一个完美的匹配.那是正确的.我所拥有的不同之处在于const.所以只是添加const到上面的场景我也应该得到指针重载.那也是对的.现在怎么可能因为你明显得到了引用过载?嗯,代码与您的想法不符.以下是与您的思路一致的代码,并且确实会选择指针重载:
template <class T> void Foo(T* const x);
template <class T> void Foo(T const &x);
Run Code Online (Sandbox Code Playgroud)
密切关注的地方const.我已添加const为顶级限定符.虽然T const &x与你所拥有的相同const T& x,T* const x但却不一样const T* x.
让我们看看在这种情况下的重载决议:
fun | T | parameter | argument
-----------------------------------------+------+--------------+-----------
template <class T> void Foo(T* const x) | int | int* const | int*
template <class T> void Foo(T const &x) | int* | int* const & | int*
Run Code Online (Sandbox Code Playgroud)
让我们看看你的版本的重载:
fun | T | parameter | argument
-----------------------------------------+------+--------------+-----------
template <class T> void Foo(const T* x) | int | const int* | int*
template <class T> void Foo(T const &x) | int* | int* const & | int*
Run Code Online (Sandbox Code Playgroud)
正如您在第一个版本中所看到的那样,首选添加顶级const并选择指针重载.不需要指针转换.
在第二种情况下,指针重载将需要指针转换pointer to mutable为pointer to const.这些是不同类型的指针.但是在第二次重载时,不需要指针转换.只需添加顶级const.
简而言之,我能解释的最好,而不是标准的xyz部分
小智 5
您的问题是,编译时Foo(x);将执行模板类型推导,并且由于您的 x 是一个,所以int*这将首先被解释为调用Foo<int*>(x),并且您的template <class T> void Foo(const T& x)重载与此完美匹配,因此类型推导在此结束。
如果您要处理类(而不是模板函数),您可以使用部分模板特化来区分指针类型和非指针类型,但对于函数仅允许完全特化。
您可以使用SFINAE技术,例如:
template <class T> void Foo(const T* x) {
std::cout << "I am the pointer overload" << std::endl;
}
template <class T>
typename std::enable_if<!std::is_pointer<T>::value>::type
Foo(const T& x) {
std::cout << "I am the reference overload" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果 T 是指针类型,则引用重载将不匹配(在推导类型时),因此编译器也会尝试,Foo<int>(x)并且您的template <class T> void Foo(const T* x)重载将是完美匹配(正是您所期望的)。
样本:
int x = 12;
int* pX = new int(5);
Foo(x);
Foo(pX);
Run Code Online (Sandbox Code Playgroud)
输出:
I am the reference overload
I am the pointer overload
Run Code Online (Sandbox Code Playgroud)