Какой тип константной ссылки?

Я знаю, что передача ссылочной переменной 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"}
  1. Почему шаблон функции работает даже для аргументов, которые уже int const&? (В примере кода это работало даже для вызова, который имел int const& переменная в качестве первого параметра и int переменная как вторая.) Разве это не должно быть недействительным, потому что C ++ не
    разрешить «ссылка на ссылку»?

  2. Не должен typeid«s name() из int const& быть int const&, вместо int?

  3. Если нет, то это не значит int const& псевдоним int; что не имеет никакого смысла, потому что оба являются разными типами (не именами переменных)?

  4. Возвращаясь к именам переменных, учитывая:

    int num = 8;
    int const& ref = num;
    std::cout << typeid(ref).name() << std::endl;
    

    почему выход int, и не int const&?

2

Решение

Аргументы функции выражения, не объекты. Даже если вы предоставляете один объект в качестве аргумента функции, он все равно является выражением. Процесс вывода аргументов шаблона не будет работать с объявленным типом этого объекта. Это не заботится о его точном объявленном типе. Что его волнует, так это тип выражение.

Выражения в 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,

2

Другие решения

  1. Поскольку ссылки свернуты в контексте вывода типа, как и consts. Посмотрите, как разваливается ссылка, на нее уже много ответов.

  2. Нет, потому что ссылки прозрачны, вы не можете смотреть на них; когда вы называете переменную, которая является ссылкой, язык всегда думает, что вы имеете в виду рефери. Когда ты typeid ссылки или const это игнорирует это.

  3. Избегайте наглых неважных слов, таких как переменная, это затрудняет чтение вашего вопроса 🙂

3

По вопросам рекламы [email protected]