Если я принимаю параметр с помощью универсальной ссылки, является ли значение is_rvalue_reference и is_lvalue_reference истинным? - PullRequest
0 голосов
/ 12 июля 2019

Возможно ли когда-нибудь для этого кода напечатать "ни"?

using namespace std;
template<typename T>
void foo(T&& t) {
    if constexpr (is_lvalue_reference_v<T>) {
        cout << "lv" << endl;
    } else if constexpr (is_rvalue_reference_v<T>) {
        cout << "rv" << endl;
    } else {
        cout <<"neither" << endl;
    }
}

Ответы [ 3 ]

3 голосов
/ 12 июля 2019

Возможно ли, чтобы этот код печатал "ни"?

Да, "ни" не будет печататься каждый раз, когда значение передается в foo и нет явного шаблоназадан параметр:

foo(42);  // "neither" is printed because T is deduced as int

Или когда явно указан не ссылочный тип:

int i=0;
// "neither" is printed because T is explicitly specified as int:
foo<int>(std::move(i));

Хотя T может быть не ссылочным типом, типt всегда будет ссылочным типом.Существует три возможности для типа t:

  1. T является типом значения (т. Е. int): тип t равен int&&;rvalue-ссылка на int.
  2. T является lvalue-ссылкой (т. е. int&): тип t равен int& &&, который сворачивается до int&;lvalue-ссылка на int.
  3. T является rvalue-ссылкой (то есть int&&): тип t равен int&& &&, который сворачивается до int&&;rvalue-ссылка на int.

Это механизм, с помощью которого работают пересылочные ссылки.Если вы передадите rvalue в foo, тогда T будет выведено как тип значения.Если вы передадите lvalue, то T будет выведен как тип lvalue-reference.

2 голосов
/ 12 июля 2019

Возможно ли когда-нибудь для этого кода напечатать "ни"?

Да.

foo(5); // neither

Если я принимаю параметр с помощью универсальной ссылки, является ли значение is_rvalue_reference равным is_lvalue_reference?

Параметр t будет иметь тип ссылки rvalue или тип ссылки lvalue. Тип T, с другой стороны, будет отличаться в зависимости от вычета и правила свертывания ссылок . Если вместо этого вы измените is_lvalue/rvalue_reference<T> на is_lvalue/rvalue_reference<decltype(t)>, тогда путь else не может быть выполнен.

1 голос
/ 12 июля 2019

Возможно ли когда-нибудь для этого кода напечатать "ни"?

Да. В соответствии с правилом удержания типа для ссылки для пересылки , при передаче lvalue, T будет выводиться как тип ссылки-lvalue, при передаче rvalue, T будет выводиться как не тип ссылки. например,

int i;
foo(i); // T is deduced as int&
foo(0); // T is deduced as int

ЖИТЬ

С другой стороны, "rv" не будет напечатан, если явно не указан аргумент шаблона.

С другой стороны (опять же), если вы проверите тип параметра функции t, это будет либо тип lvalue-reference, либо тип rvalue-reference; "neither" не будет напечатан.

int i;
foo(i);        // T is deduced as int&, the type of t is int& (int& && -> int&)
foo(0);        // T is deduced as int, the type of t is int&&
foo<int&&>(0); // T is specified as int&&, the type of t is int&& (int&& && -> int&&)

ЖИТЬ

...