Является ли результат приведения rvalue?

Позволять

int a = 0;

Тогда является ли (int)a rvalue в стандартном C++?

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

#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/


person Minimus Heximus    schedule 22.10.2014    source источник
comment
Кто-нибудь проверял, есть ли ошибка connect? Беглый поиск ничего не дал.   -  person Mgetz    schedule 22.10.2014
comment
@Mgetz Я искал, но ничего очевидного не нашел.   -  person Shafik Yaghmour    schedule 22.10.2014
comment
Зарегистрировано как дефект при подключении против VS2013 с использованием тестового примера @ShafikYaghmour   -  person Mgetz    schedule 22.10.2014
comment
Давняя особенность MSVC заключается в том, что временному объекту разрешено привязываться к неконстантной ссылке. Отключите его с помощью параметра /Za.   -  person Igor Tandetnik    schedule 22.10.2014
comment
@IgorTandetnik хорошо, что теперь это зарегистрировано как ошибка, MS может решить сохранить или удалить это расширение по своему усмотрению. Однако их компилятор не соответствует требованиям, если они оставляют его включенным по умолчанию.   -  person Mgetz    schedule 22.10.2014
comment
Похожая тема со вчерашнего дня   -  person M.M    schedule 23.10.2014
comment
примечание: удален тег language-lawyer, так как юрист не требуется, он черно-белый; и добавил тег visual-c++ и lvalue, так как я уверен, что та же проблема отвечает за множество других вещей.   -  person M.M    schedule 23.10.2014
comment
MS, наконец, ответила, это, по-видимому, контролируется /Zc:rvalueCast (принудительное преобразование типов правила) они пометили мою ошибку как исправленную. Я все еще ищу разъяснений, будет ли это включено по умолчанию в будущем.   -  person Mgetz    schedule 08.11.2014


Ответы (3)


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

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

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

Как gcc, так и clang приводит к rvalue, что является ожидаемым результатом.

Кроме того, я бы рекомендовал использовать rextester поверх веб-компилятора, поскольку rextester позволяет вам программа, а также имеет живой обмен.

Обновить

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

Как указывает dyp, gcc также имел приведение к расширению lvalue.

Обновление 2

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

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

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

person Shafik Yaghmour    schedule 22.10.2014
comment
+1 за вашу рекомендацию. как долго живет ссылка на прямой эфир? - person Minimus Heximus; 23.10.2014
comment
@MinimusHeximus не уверен, я использовал только в течение коротких периодов времени, и сайт не документирует это. - person Shafik Yaghmour; 23.10.2014
comment
Этот ответ неверен, на самом деле. Visual C++ не использует неправильную функцию, которая привязывает ссылку lvalue к временному объекту... он вообще не может создать временный объект. См. ответ Мэтта и мой отчет об ошибке connect.microsoft.com/VisualStudio/Feedback/Details/615622. - person Ben Voigt; 23.10.2014
comment
@BenVoigt спасибо, что поделились этой ссылкой, хотя странно, что использование /Za исправляет это, так что это больше не похоже на поведение по умолчанию, и на самом деле, когда я использую /Za, это (int)a = 2 ; является ошибкой. Я добавлю вашу ссылку к моему ответу. - person Shafik Yaghmour; 23.10.2014
comment
Расширение языка, связывающее rvalue со ссылкой на lvalue, работает, только если есть объект; это неверно для значений prvalue основных типов rextester.com/TOJWJL48414. Как ни странно, у gcc когда-то было похожее расширение, которое позволяло использовать результат приведения в качестве lvalue: gcc.gnu.org/gcc-3.4/changes.html (преобразование в виде lvalue) - person dyp; 23.10.2014
comment
@dyp, это странно, вы знаете, как это использовать? - person Shafik Yaghmour; 23.10.2014
comment
@ShafikYaghmour Для расширения MSVC или GCC? - person dyp; 23.10.2014
comment
@dyp для приведения к lvalue, которое gcc раньше имело, а MSVC все еще имеет. - person Shafik Yaghmour; 23.10.2014
comment
Я могу только предположить, что (char) i = 5; удобнее писать, чем *((char*)&i) = 5; (на C). Вы можете найти некоторое обсуждение при поиске cast-as-lvalue. Например. кажется, это было в ранних проектах C89. - person dyp; 23.10.2014
comment
@BenVoigt хм, может быть, они, наконец, исправят это с помощью моего отчета об ошибке. - person Mgetz; 24.10.2014
comment
@Mgetz, если вы сообщите мне, когда получите обновление, я также обновлю свой ответ. - person Shafik Yaghmour; 24.10.2014
comment
@ShafikYaghmour MS исправила ошибку как исправленную, очевидно, мы все ошибались: /Zc :rvalueCast (Применить правила преобразования типов) - person Mgetz; 08.11.2014

В стандартном С++ 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 имеет расширение, позволяющее привязывать rvalue к неконстантным ссылкам; это расширение по-прежнему делает ссылки на rvalue более подходящими, чем ссылки на lvalue для rvalue.

person M.M    schedule 23.10.2014
comment
Я сообщил об этом и нескольких других вариантах в Connect четыре года назад: connect.microsoft.com/VisualStudio /Отзыв/Подробности/615622 - person Ben Voigt; 23.10.2014

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

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

person Mike Seymour    schedule 22.10.2014
comment
Суть в том, что нет правила, делающего исключение для приведения от T к T. - person Lightness Races in Orbit; 22.10.2014