代码来自https://en.cppreference.com/w/cpp/language/template_argument_deduction,现在我添加空白f(T*)
,f(&d)
将调用f(T*)
。
(1)您能解释为什么叫f(T*)
吗?
在https://en.cppreference.com/w/cpp/language/function_template中 它提到“模板参数推导发生在函数模板名称查找之后(可能涉及依赖于参数的查找)并且在重载解析之前。”
选择f(T *)是因为“过载分辨率”中的“完全匹配”,对吧? 因此,在模板参数推导阶段,选择f(B ),然后在以后的重载解决阶段,选择f(T )并接管f(B *),这是否正确?
谢谢
(2)我应该进行哪些更改以使呼叫f(&d)
呼叫f(B<T>*)
?我还需要一个f(T*)
,所以必须保留f(T*)
。
#include <iostream>
using namespace std;
template<class T> struct B { };
template<class T> struct D : public B<T> { };
template<class T> void f(T*) { cout<< "T*"<< endl; }
template<class T> void f(B<T>*) { cout<< "B<T>*"<< endl; }
int main() {
D<int> d;
f(&d);
return 0;
}
答案 0 :(得分:1)
- 您能解释为什么叫
f(T*)
吗?
因为这是完全匹配(当T
被推导为D<int>
时)。要调用f(B<int>*)
,需要从D<int>*
到B<int>*
的隐式转换。
- 我应该进行哪些更改才能使呼叫
f(&d)
呼叫f(B<T>*)
?
您可以申请SFINAE。例如
// type trait to get the template parameter from template instantiation
template <typename T>
struct get_template_parameter {
using type = T;
};
template <template <typename> class X, typename T>
struct get_template_parameter<X<T>> {
using type = T;
};
template <typename T>
using get_template_parameter_t = typename get_template_parameter<T>::type;
// only usable when T is B's instantiation or derived class of B's instantiation
template<class T>
std::enable_if_t<!std::is_base_of_v<B<get_template_parameter_t<T>>, T>>
f(T*) { cout<< "T*"<< endl; }
template<class T> void f(B<T>*) { cout<< "B<T>*"<< endl; }