Я знаю, что передача ссылочной переменной const в ссылочный параметр const функции не приводит к тому, что параметр функции имеет тип «постоянная ссылка на постоянную ссылку типа рефери». Имя переменной аргумента ссылки const просто рассматривается как другой псевдоним для рефери, но прославляется защитой, что указанный псевдоним не может использоваться для изменения рефери.
Идея использования имени ссылочной переменной, как если бы он был псевдонимом переменной-рефери, хорошо применима к переменные, давая еще один слой косвенности. Кажется, не имеет смысла применять аналогичные идеи:
typedef
из константный тип ссылки используется в качестве псевдонима своего судьи тип,template
Параметр получает свой тип, интерпретируемый как тип его рефери, когда параметр шаблона typename T
и его функциональный параметр T const&
,Но вот что, похоже, происходит в следующем:
#include <typeinfo>
#include <iostream>
template <typename T>
T const& min(T const& a, T const& b) {
std::cout << typeid(a).name() << std::endl;
std::cout << typeid(b).name() << std::endl;
return a < b ? a : b;
}
int main() {
int x = 6, y = 7;
int const& rx = x;
std::cout << typeid(rx).name() << std::endl; // "int"int z = ::min(rx, y); //output shows both "a" and "b" are of type "int"std::cout << z << std::endl; // “6”
typedef int const& icr;
std::cout << typeid(icr).name() << std::endl; // "int"std::cout << typeid(int const&).name() << std::endl; // "int"}
Почему шаблон функции работает даже для аргументов, которые уже int const&
? (В примере кода это работало даже для вызова, который имел int const&
переменная в качестве первого параметра и int
переменная как вторая.) Разве это не должно быть недействительным, потому что C ++ не
разрешить «ссылка на ссылку»?
Не должен typeid
«s name()
из int const&
быть int const&
, вместо int
?
Если нет, то это не значит int const&
псевдоним int
; что не имеет никакого смысла, потому что оба являются разными типами (не именами переменных)?
Возвращаясь к именам переменных, учитывая:
int num = 8;
int const& ref = num;
std::cout << typeid(ref).name() << std::endl;
почему выход int
, и не int const&
?
Аргументы функции выражения, не объекты. Даже если вы предоставляете один объект в качестве аргумента функции, он все равно является выражением. Процесс вывода аргументов шаблона не будет работать с объявленным типом этого объекта. Это не заботится о его точном объявленном типе. Что его волнует, так это тип выражение.
Выражения в C ++ никогда не интерпретируются как имеющие ссылочный тип. Каждое выражение, которое физически имеет ссылочный тип, всегда интерпретируется как именующий (или xvalue) не ссылочного типа. «Ссылочная» часть немедленно и необратимо отбрасывается и забывается.
Вот как это сформулировано в стандарте (5/5)
5 Если выражение изначально имеет тип «ссылка на T» (8.3.2,
8.5.3), тип корректируется до T перед любым дальнейшим анализом. Выражение обозначает объект или функцию, обозначенную ссылкой,
и выражение является lvalue или xvalue, в зависимости от
выражение.
Например, в вашем коде rx
объявлен как int const &
, Тем не менее, каждый раз, когда вы используете rx
как выражение, результат этого выражения всегда сразу корректируется из int const &
в int const
и рассматривается как именующий из int const
тип. В контексте «выражения результата» язык полностью игнорирует тот факт, что rx
была ссылка.
Часто говорят, что ссылка может рассматриваться как просто другое имя для существующего объекта. Это именно тот принцип, который работает здесь. В контексте «выражения результата» нет никакой разницы между rx
а также x
(кроме const-квалификации).
Возвращаясь к вашему коду, в этом звонке
int z = ::min(rx, y);
аргументы функции интерпретируются как l-значения int const
а также int
тип соответственно. (То есть первый аргумент на самом деле не рассматривается как имеющий int const &
типа, вопреки вашим ожиданиям). Эти типы используются для вывода аргументов шаблона. Как следствие, T
выводится как int
, Ни в одной точке этого процесса попытка создать «ссылку на ссылку» не имеет шансов иметь место.
typeid
работает так, как вы наблюдаете по той же причине. typeid
не дает вам заявленный тип объекта. Аргумент typeid
в вашем случае это выражение. typeid
в этой форме дает тип результата выражения, поэтому typeid
не может «видеть» ссылки. const
часть отбрасывается, потому что это только как typeid
работает: cv-qulifiers верхнего уровня всегда отбрасываются typeid
,
Поскольку ссылки свернуты в контексте вывода типа, как и const
s. Посмотрите, как разваливается ссылка, на нее уже много ответов.
Нет, потому что ссылки прозрачны, вы не можете смотреть на них; когда вы называете переменную, которая является ссылкой, язык всегда думает, что вы имеете в виду рефери. Когда ты typeid
ссылки или const
это игнорирует это.
Избегайте наглых неважных слов, таких как переменная, это затрудняет чтение вашего вопроса 🙂