Как вычитание шаблона и decltype (T) работает с ссылкой? - PullRequest
0 голосов
/ 12 июня 2018

Я изучаю шаблон на C ++.Что-то, чего я не понимаю, это то, что: учитывая тип X и создавая объект X a;, если я определяю ссылку на a с помощью X& b = a;, то std::is_reference<decltype(b)>::value возвращает true.Однако, если я принимаю b в качестве аргумента функции шаблона, вычтенный тип не является ссылкой.

#include <iostream>

class X {};

template<typename T>
void
F(T t)
{
    if (std::is_reference<T>::value)
        std::cout << "T is a reference" << std::endl;
}

int
main()
{
    X a;
    X &b = a;
    std::cout << std::is_reference<decltype(b)>::value << std::endl; // return true
    F(b); //return false
}

У меня вопрос, почему код работает так.

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Попытка ответить на вопрос «почему»: функция

void someFunc(int arg) { /* ... */ }

явно получает свой аргумент по значению.Имея в виду int, какую семантику вы ожидаете от этой функции?

template<class T> void someFunc(T arg) { /* ... */ }

Я бы также ожидал, что аргумент будет также передаваться по значению.Теперь рассмотрим фрагменты вызова, в первом случае

int i;
int& j = i;

someFunc(j); /* j passed by value. */

, а во втором случае

X a;
X& b = a;

someFunc(b); /* b passed by reference? Luckily not. */

, где вместо подписи шаблона функции

template<class T> someFunc(T& arg) { /* ... */ }

не так много потенциальных недоразумений в момент вызова - аргумент передается по ссылке.В конце концов, это сводится к целым числам, являющимся обычными типами , а ссылки - нет (см. этот пост для недавнего трактата, также охватывающего указатели).

0 голосов
/ 12 июня 2018

Тип b в качестве выражения равен X из-за [expr.type] / 1 :

Если выражениеизначально имеет тип «ссылка на T» ([dcl.ref], [dcl.init.ref]), тип корректируется до T перед любым дальнейшим анализом.

Итак Tвыводится как X.Однако decltype(b) - это не просто тип b в качестве выражения.Согласно [dcl.type.simple] / 4 (не относящаяся к делу часть исключена мной):

Для выражения e тип, обозначенный decltype(e), равенопределяется следующим образом:

  • ...

  • в противном случае, если e не выражено в скобках id-выражение или не заключено в скобки* доступ к элементу класса, decltype(e) - это тип сущности, названной e....

  • ...

Обратите внимание, что это тип сущности, названный b (то есть X&), а не тип выражения b.

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