вывод аргумента шаблона для производного класса - PullRequest
1 голос
/ 30 сентября 2019

Код от 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;
}

1 Ответ

1 голос
/ 30 сентября 2019
  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; }

LIVE

...