почему нельзя добавить низкоуровневый тип const к локальной переменной в функции шаблона - PullRequest
3 голосов
/ 13 июня 2019

Я изучаю шаблон c ++ и напишу пример, как показано ниже:

  #include <vector>
  #include <iostream>
  #include <type_traits>
  #include <typeinfo>

  using namespace std;

  template <typename T>
  void fcn(T &&val)
  {
      cout << is_same<T, int&>::value << endl;
      const T t = val;
      //T const t = val;
      cout << typeid(t).name() << endl;
      t = 10;
      cout << "val: " << val;
      cout << ", t: " << t << endl;
      return;
  }

  int main()
  {
      cout << boolalpha;

      int i{};

      fcn(i);
   }

Я ожидаю, что этот код не может успешно скомпилироваться, но нет ошибок, вывод:

true
i
val: 10, t: 10

У меня есть два вопроса:

  1. gcc вывести T is int& type, строка const T t = val, означает t const bind to val, например: const int &t = valпочему конст не имеет эффекта?Значение t и i можно изменить?

  2. Я использовал typeid(t).name(), чтобы показать тип t, зачем просто печатать i?

Ответы [ 3 ]

3 голосов
/ 13 июня 2019
  1. В вашем случае const T с T = int& означает, что g - это ссылка, которую я не могу переназначить .Но ссылка никогда не присваивается, она всегда указывает на один и тот же объект.Таким образом, он падает до T, что в этом случае int&.

Чтобы все заработало как положено, используется std::remove_reference

См .: константные ссылки в шаблонах c ++

name возвращает что-то, что определено реализацией, так что тут особо нечего сказать.
2 голосов
/ 13 июня 2019
  1. gcc выводит T типа int&, const T t = val, означает t const bind to val, почему const не имеет эффекта?

Эта подпись шаблона функции

template <typename T> void fcn(T &&val);

использует ссылку для пересылки.Короче говоря, при выводе экземпляра с lvalue int (ваш случай) вы получите T = int&, то есть, включая ссылку.Свертывание ссылок преобразует void fcn(T& &&val) в void fcn(T& val).

Когда вы объявляете const T t, это означает, что T& const (const изменяет то, что слева, и если слева ничего нет, оно модифицируетчто справа).Но это недопустимо, поскольку не существует такой вещи, как const -качественная ссылка, следовательно, const -квалификатор отбрасывается.

Я использовал typeid(t).name(), чтобы показать тип т. Почему просто вывести i?

typeid(t).name() не требуется для вывода понятного человеку идентификатора.i означает int, поэтому, в зависимости от компилятора, это то, что вы должны ожидать.Однако при работе с clang или gcc часто лучше отображать тип через

template <class T> p(T&&) { std::cout << __PRETTY_FUNCTION__; }

p(t); // prints out understandable type info
0 голосов
/ 13 июня 2019

Я пишу другую программу для исследования const T, которая использует "псевдоним типа":

  #include <iostream>                                                                                 

  using namespace std; 

  int main()                                                                                          
  {
    int i {};
    using T = int *;                                                                                
    const T t = &i;     // same with T const t = &i;                                                                                                                                                                                                                                     

    *t = 10;                                                                                                                                                                                                                                                                             
    cout << i << endl;                                                                                                                                                                                                                                                                   
    int j{};                                                                                                                                                                                                                                                                             
    //t = &j;   // error, t is int * const                                                                                                                                                                                                                                                
  } 

, она успешно компилируется, вывод: 10.

Теперь я могу понять, почему компиляторconst T считает int * const, но не const int *, потому что этот компилятор обрабатывает T как общий тип, такой как int, char, а не int *, это не замена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...