Является ли результат броска значимым?

Позволять

int a = 0;

Тогда это (int)a значение в стандарте 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/

3 ответа

Решение

Значение должно быть значением r, но веб-компилятор работает с 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 игнорируются при определении типа результирующего значения; см. 3.10. —Конечная записка]

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

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

Обновить

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

Как указывает dyp, у gcc также есть расширение cast to lvalue.

Обновление 2

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

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

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

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

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

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

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

#include <iostream>

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

MSVC лечит (int)x как lvalue.

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

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