【问题标题】:template argument deduction for Derived class派生类的模板参数推导
【发布时间】:2019-09-30 13:10:36
【问题描述】:

代码来自https://en.cppreference.com/w/cpp/language/template_argument_deduction,现在我添加void 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;
}

【问题讨论】:

  • f(static_cast&lt;B&lt;int&gt;*&gt;(&amp;d)); 是一种方式。
  • 为什么是因为将T(在情况1)推断为D&lt;int&gt;是完全匹配的。
  • f&lt;int&gt;(d)

标签: c++ templates template-argument-deduction


【解决方案1】:
  1. 您能解释一下为什么调用f(T*) 吗?

因为它是完全匹配的(当T 被推断为D&lt;int&gt; 时)。要调用f(B&lt;int&gt;*),需要从D&lt;int&gt;*B&lt;int&gt;* 的隐式转换。

  1. 我应该进行哪些更改才能拨打f(&amp;d) 以拨打f(B&lt;T&gt;*)

您可以申请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; }

LIVE

【讨论】:

    猜你喜欢
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多