Я думаю, что я мог придумать пример rvalue типа массива - PullRequest
11 голосов
/ 30 октября 2010

C ++ 03 §4.2 N ° 1:
Значение l или значение типа «массив NT» или «массив неизвестной границы 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.

Я предполагаю, что в противном случае это r-значение (при условии, что 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 ]

11 голосов
/ 30 октября 2010

Да, вы правы.Выражение является значением типа массива.Это не является недостатком - комитет знает об этом, и это было также распространенной проблемой в 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(); }
0 голосов
/ 30 октября 2010

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

В последней версии черновика вы можете перегрузить функции в 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 ​​и rvalue. В качестве альтернативы рассмотрите это:

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

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

...