Подтвердить что ты не робот

Я думаю, что, возможно, придумал пример rvalue типа массива

С++ 03 §4.2 № 1:
Lvalue или rvalue типа "массив из N T" или "массив неизвестной границы T" могут быть преобразованы в rvalue типа "указатель на T". Результатом является указатель на первый элемент массива.

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

С++ 03 §5.2.5 N ° 4: (речь идет о выражении E1.E2)
Если E2 - нестатический элемент данных, а тип E1 - "cq1 vq1 X", а тип E2 - "cq2 vq2 T", выражение обозначает именованный элемент объекта, обозначенный первым выражением. Если E1 является lvalue, то E1.E2 является lvalue.

Я предполагаю, что в противном случае это rvalue (если E2 не является ссылкой, этот случай покрывается §5.2.5 N°3) и поэтому...

struct A
{
   int a[4];
};
A f()
{
   A a;
   return a; 
}
int main()
{
   f().a; //I think this is an rvalue of array type...
}

Я вижу два варианта:
Вариант 1: Я прав, ура, гей, круто. В этом случае возникает вопрос: существуют ли другие примеры?
Вариант 2: Я ошибаюсь, в этом случае возникает вопрос: является ли это дефектом стандарта?

Я не знаю около 1, но я действительно сомневаюсь в 2, потому что, когда они говорят о конверсиях между указателями, они упоминают только lvalues ​​типов функций (очевидно, учитывая, что таких значений нет). Поэтому, скорее всего, они думали о избыточных значениях типов массивов.

Итак, в основном, мой вопрос заключается в том, действительно ли я придумал пример значения rvalue типа массива, а если нет, укажите действующий, который, как я полагаю, существует.

4b9b3361

Ответ 1

Да, вы правы. Выражение представляет собой rvalue типа массива. Это не недостаток - комитет знает об этом, и это также является распространенной проблемой на C89, которая позволяет конвертировать только указатели для lvalues ​​типов массивов. Как следствие, вы не можете индексировать или разыменовывать массив вроде f().a. C99 исправил это, и С++ не имеет с этим проблем.

Обратите внимание, что независимо от того, является ли оно rvalue независимым от того, обозначает ли выражение объект. С++ 03 случайно не указал, что выражение rvalue, относящееся к типу массива, обозначает объект. Это было исправлено в С++ 0x с помощью DR # 450.

(очевидно, учитывая, что таких значений нет)

Существуют фактические значения типов функций. Это происходит для нестатических функций-членов, обозначенных выражением доступа к члену класса

struct A { void f(); };

/* A().f is an rvalue of type "void()" */
int main() { A().f(); }

Ответ 2

A - значение r. Массив внутри него нет. Представьте себе случай, когда у вас есть цепочка методов на этом временном объекте - переменные внутри него живут более чем для одного вызова метода и возвращаются, и они могут передавать ссылки (действительные для продолжительности цепочки) на другие функции. Эти функции не могут заранее знать, что они должны быть вызваны на rvalue.

В последней версии проекта вы можете перегружать функции по rvalue/lvalue * this. Однако даже тогда ссылка rvalue не делает содержимое того, что называется rvalue, и я не совсем уверен, что ANY-компилятор в настоящее время поддерживает это, и я знаю, что MSVC этого не делает.

Infact, используя decltype, вы можете легко определить, что компилятор вызывает этот массив lvalue.

Рассмотрим:

template<typename A, typename B> auto sum(A&& a, B&& b) -> decltype(std::forward<A>(a) + std::forward<B>(b)) {
    return std::forward<A>(a) + std::forward<B>(b);
}

То, для чего был тип decltype, и он определенно различает lvalues ​​и rvalues. В качестве альтернативы рассмотрим это:

int main()
{
    auto var = f().a;
}

Var - это int *. То мгновение терпит неудачу, так как f(). A сразу же умирает. Не уверен в моем непосредственном мнении по этому поводу, но он, безусловно, недействителен для rvalue.