2014-10-22 4 views
15

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

Тогда это (int)aRvalue в стандартном 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/

+0

Кто-нибудь проверил, есть ли еще ошибка [connect] (http://connect.microsoft.com)? Беглый поиск не перевернул. – Mgetz

+0

@Mgetz Я искал, но я не нашел ничего очевидного. –

+0

[Подано как дефект при подключении] (https://connect.microsoft.com/VisualStudio/feedback/details/1008261) против VS2013 с использованием тестового примера @ ShafikYaghmour – Mgetz

ответ

10

должен быть Rvalue но WebCompiler работает Visual Studio и Visual Studio имеет extension which allows temporary objects to be bound to non-const lvalue references.a bug/extension that casues it to generate an lvalue in this case Как указывает Игорь, это можно отключить, используя /Za (see it live).

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

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

gcc Как и clang результат в RValue который является ожидаемым результатом.

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

Update

Бен Фойгт указывают эту bug report и поэтому кажется, что Visual Studio действительно производит именующее выражение. Так что это не просто случай extension which allows temporary objects to be bound to non-const lvalue references.

As dyp указывает gcc used to have a cast to lvalue extension также.

Обновление 2

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

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

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

+0

+1 для вашей рекомендации. как долго живет живая передача? – user2029077

+0

@MinimusHeximus не уверен, я использовал только короткие периоды, и сайт не документировал его. –

+0

Этот ответ на самом деле неправильный. Visual C++ не использует недостоверность, которая связывает ссылку lvalue с временным ... она полностью не создает временного вообще. См. Ответ Мэтта и мой отчет об ошибке. Https://connect.microsoft.com/VisualStudio/Feedback/Details/615622 –

4

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

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

+6

Ключ в том, что нет правила, делающего исключение для трансляции из 'T' в' T'. –

3

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

В вашем примере кода используется ошибка/расширение в 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.

+1

Я сообщил об этом и нескольких других вариантах подключения Connect четыре года назад: https://connect.microsoft.com/VisualStudio/Feedback/Details/615622 –