Почему при выводе типа отбираются квалификаторы аргументов шаблона? - PullRequest
7 голосов
/ 12 ноября 2010

При создании небольшого примера программы с Microsoft VisualStudio 2008 я заметил странную вещь о выводе типов, передаваемых шаблонам. Рассмотрим этот пример:

template<class T>
void f( T v ) {
    x; // trigger a compile error
    (void)v;
}

template<class T>
void g( T v ) {
    f( v );
}

void h() {
  int i;
  g<const int &>( i );
}

Компиляция этого примера с использованием cl /c foo.cpp приводит к ошибке компиляции (как и предполагалось). Что интересно, так это значение параметра шаблона «Т». Вот что печатает VisualStudio 2008:

mini.cpp(3) : error C2065: 'x' : undeclared identifier
        mini.cpp(9) : see reference to function template instantiation 'void f<int>(T)' being compiled
        with
        [
            T=int
        ]
        mini.cpp(14) : see reference to function template instantiation 'void g<const int&>(T)' being compiled
        with
        [
            T=const int &
        ]

Обратите внимание, что в g тип аргумента const int &, но в f это просто int. Очевидно, что ссылка на константную часть была удалена при определении типа для использования при создании шаблона f. При настройке примера так, чтобы f вызывался как

f<T>( v );

тип const int & в f и g. Это почему? Это указанное поведение? Я тайно полагался на тип аргумента функции v, передаваемого на f, но, очевидно, это не так.

Ответы [ 2 ]

6 голосов
/ 12 ноября 2010

Ответ таков: хотя переменная v имеет тип const int &, выражение v представляет собой выражение lvalue с типом const int.

litb предоставляет текст(5/6): «Если выражение изначально имеет тип« ссылка на T »(8.3.2, 8.5.3), тип настраивается на« T »перед любым дальнейшим анализом, выражение обозначает объект или функциюобозначается ссылкой, а выражение является lvalue. "

" Аргумент "- это" выражение в списке через запятую, ограниченное скобками в выражении вызова функции "(1.3.1).Таким образом, в 14.8.2.1:

  • "соответствующий тип аргумента вызова (назовите его A)" равен const int.
  • "Если A является cv-квалифицированным типом,cv-квалификаторы верхнего уровня типа A игнорируются для вывода типа "(следовательно, int).
  • " процесс вывода пытается найти значения аргументов шаблона, которые сделают выведенный A идентичным A "(так что T int)
1 голос
/ 12 ноября 2010

http://accu.org/index.php/journals/409 - довольно обширная статья, но она объясняет процесс.Из параметров шаблона выводится тип параметра P, который соответствует типу аргумента A.Соответствующая часть описывает, как целевой тип A получается из аргумента функции: для типов, не являющихся массивами, ссылки просто удаляются.Следовательно, если тип аргумента int&, тогда тип цели A просто int.

Это простая причина: потому что стандарт говорит нам об этом.Каково обоснование?Как это бывает, в статье есть сноска, указывающая на это тоже.В вашем примере typeid(v)==typeid(const int).При использовании в контекстах без значения значения ссылочные типы ведут себя как нереферентные типы.

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