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

Является ли результат отливки rvalue?

Пусть

int a = 0;

Тогда (int)a значение r в стандартном С++?

Различные компиляторы показывают разные результаты для этого кода:

#include <iostream>
using namespace std;

void f(int& x)
{
    cout << "l value" << endl;
}

void f(int&& x)
{
    cout << "r value" << endl;
}

int main()
{
    int a = 0;
    f((int)a);
}

с разными результатами:

1) http://cpp.sh/2r6

2) http://webcompiler.cloudapp.net/

4b9b3361

Ответ 1

Значение должно быть rvalue, но webcompiler работает с Visual Studio, а Visual Studio имеет расширение которое позволяет связать временные объекты с неконстантными ссылками lvalue. ошибка/расширение, которое вызывает его при генерации lvalue в этом случае Как указывает Игорь, выше можно отключить с помощью /Za (посмотреть его в прямом эфире).

Мы можем видеть, что это должно быть rvalue (в частности, prvalue) из черновика стандартного раздела С++ 5.4 Явное преобразование типа (литая нотация), пункт 1, в котором говорится (выделено мной):

Результат выражения (T) выражения-выражения имеет тип T. результатом является lvalue, если T - ссылочный тип lvalue или rvalue ссылка на тип функции и значение x, если T является ссылкой на rvalue к типу объекта; в противном случае результат будет prvalue. [Примечание: если T тип неклассов, имеющий квалификацию cv, cv-квалификаторы игнорируются при определении типа возвращаемого значения; см. 3.10. -конец примечание]

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

В стороне, я бы рекомендовал использовать rextester через webcompiler, поскольку рекстестер позволяет вам делиться своей программой, а также осуществлять совместное использование в реальном времени.

Обновить

Бен Фойгт отметьте этот отчет об ошибке, и поэтому кажется, что Visual Studio фактически производит lvalue. Таким образом, это не просто случай расширения который позволяет связать временные объекты с неконстантными ссылками l.

Как указывает dyp gcc также используется для добавления в lvalue extension.

Обновление 2

Mgetz подал сообщение об ошибке ответ был тот, что это исправлено с помощью /Zc: флаг rvalueCast, описание флага выглядит следующим образом:

Когда задана опция /Zc: rvalueCast, компилятор правильно идентифицирует ссылочный тип rvalue в результате операции литья в соответствии со стандартом С++ 11. Когда опция не указано, что поведение компилятора такое же, как в Visual Studio 2012. По умолчанию /Zc: rvalueCast выключен. Для соответствия и устранения ошибки при использовании бросков, мы рекомендуем использовать /Zc: rvalueCast.

Неясно, будет ли этот флаг включен по умолчанию в будущих версиях.

Ответ 2

Да, результат приведения к типу объекта - это rvalue, как указано в С++ 11 5.4/1:

Результатом является lvalue, если T является ссылкой на lvalue тип или ссылку rvalue для типа функции и xvalue, если T является ссылкой rvalue на тип объекта; В противном случае результатом будет prvalue.

Ответ 3

В стандартном С++ int(a) и (int)a имеются значения r (другие ответы содержат стандартные ссылки).

В вашем примере кода используется ошибка/расширение в MSVC, но не то, что кажется на первый взгляд. Как мы видим из этого кода, который работает в MSVC:

#include <iostream>

int main()
{
    int x = 0;
    (int)x = 1;
    std::cout << x << std::endl;
}

MSVC рассматривает (int)x как lvalue.

Несмотря на то, что MSVC имеет расширение, позволяющее rvalues ​​связываться с неконстантными ссылками; это расширение по-прежнему делает ссылки rvalue более подходящими, чем ссылки lvalue для rvalues.