Я думаю, что я мог придумать пример rvalue типа массива

C++03 §4.2 N°1:
Значение l или значение типа "массив N T" или "массив неизвестной границы T" может быть преобразовано в значение типа "указатель на T". Результатом является указатель на первый элемент массива.

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

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

Я предполагаю, что в противном случае это значение (при условии, что 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, потому что когда они говорят о преобразованиях функций в указатели, они упоминают только l-значения типов функций (очевидно, понимая, что таких значений не существует). Поэтому вполне вероятно, что они подумали о значениях типов массивов.

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

2 ответа

Решение

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

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

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

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

struct A { void f(); };

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

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

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

Фактически, используя 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 немедленно умирает. Не уверен в моем непосредственном мнении по этому поводу, но оно определенно не подходит для оценки.

Другие вопросы по тегам