Вывод типа шаблона в C++
Когда мы говорим о C++, auto
должно быть привлекательной функцией. Тем не менее, чтобы понять вывод типа auto
, мы должны сначала взглянуть на template type deduction
. Содержание этого поста заимствовано из 'Пункт 1. Понимание вывода типа шаблона' в Effective Modern C++.
Вывод типа шаблона происходит, когда аргументы шаблона не указаны явно. Ниже приведен один из простых примеров, показывающих явно заданные аргументы шаблона.
template<typename T> void f(const T& param)
int x = 0; f<double>(x);
Чтобы подробнее объяснить вывод типа шаблона, мы будем использовать два ключевых слова: T
и ParameterType
, как показано ниже.
template<typename T>
void f(ParameterType param)
T
— тип аргумента шаблона, аParameterType
— тип аргумента функцииparam
.T
иParameterType
могут быть, но не обязательно одинаковыми.
Для вызова функции f(expr)
ниже
template<typename T> void f(const T& param)
int x = 0; f(x);
T
выводится как int
, а ParameterType
выводится как const int &
.
Чтобы вывести тип для T
, он зависит не только от типа expr
, но и от формы ParameterType
.
Есть три случая, когда
ParameterType
— это тип указателя или ссылки, но не универсальная ссылкаParameterType
— это универсальная ссылкаParameterType
не является ни указателем, ни ссылкой
ParameterType — это тип указателя или ссылки, но не универсальная ссылка.
template<typename T>
void f1(T&) {
std::cout << "T is ";
if (std::is_const_v<T>) {
std::cout << "const ";
}
std::cout << typeid(T).name() << std::endl;
}
Если теперь мы запустим код
int main() {
int x = 27;
const int cx = x;
const int& rx = x;
f1(x);
f1(cx);
f1(rx);
}
Результат будет
T is i
T is const i
T is const i
Справочность rx игнорируется во время вывода типа, и это работает так же для указателя.
Если мы явно напишем const
для аргумента функции шаблона, давайте проверим, что T будет выведено как
template <typename T>
void f2(const T&) {
std::cout << "T is ";
if (std::is_const_v<T>) {
std::cout << "const ";
}
std::cout << typeid(T).name() << std::endl;
}
Если мы снова запустим код, используя f2
, вывод будет
T is i
T is i
T is i
Для трех случаев T
выводится как int
, другими словами, вызываемая функция на самом деле void f2(const int &)
.
ParameterType — универсальная ссылка
- Для универсальной справки мы можем использовать совершенную пересылку, чтобы проверить, какой тип функции вызывается. Пожалуйста, обратитесь к моему предыдущему сообщению Идеальная переадресация
- Теперь давайте воспользуемся идеальной пересылкой вместе с некоторой перегрузкой функций, чтобы проверить, какой тип функции вызывается.
void f(int&) { std::cout << "calling f(int &)" << std::endl; }
void f(const int&) { std::cout << "calling f(const int &)" << std::endl; }
void f(int&&) { std::cout << "calling f(int &&)" << std::endl; }
template <typename T> void f3(T&& param) { f(std::forward<T>(param)); }
Если мы выполним код
int main() {
int x = 27;
const int cx = x;
const int& rx = x;
f3(x);
f3(cx);
f3(rx);
f3(27);
}
Мы получим вывод
calling f(int &)
calling f(const int &)
calling f(const int &)
calling f(int &&)
Ценность и ценность остались.
ParameterType не является ни указателем, ни ссылкой
template <typename T>
void f4(T) {
std::cout << "T is ";
if (std::is_const_v<T>) {
std::cout << "const ";
}
std::cout << typeid(T).name() << std::endl;
}
Когда он передается по значению, const
, volatile
и ссылка игнорируются.
Если мы снова запустим код, используя f4
, вывод будет
T is i
T is i
T is i
Спасибо за прочтение! Код доступен здесь. Надеюсь, теперь вы лучше понимаете вывод типа шаблона.