Является ли следующий код допустимым (в соответствии со стандартами С++ 11 и/или С++ 14))?
#include <iostream>
#include <utility>
using namespace std;
void foo(int &a) {
cout << a << endl;
}
int main() {
foo(reinterpret_cast<int &>(move(5)));
}
- Если да, то это неопределенное поведение?
- Если это не неопределенное поведение, могу ли я даже изменить
a
внутриfoo
, не превратившись в UB?
Он компилируется на clang 3.5, а не на gcc 4.9. Ошибка GCC:
➤ g++-4.9 -std=c++1y sample.cpp -o sample
sample.cpp: In function 'int main()':
sample.cpp:11:40: error: invalid cast of an rvalue expression of type 'std::remove_reference<int>::type {aka int}' to type 'int&'
foo(reinterpret_cast<int &>(move(5)));
^
РЕДАКТИРОВАТЬ
К вашему сведению, специально созданное приведение, менее сложное, чем предыдущее, и работающее на C++11 как для GCC, так и для Clang, будет следующей функцией lvalue
:
#include <iostream>
namespace non_std {
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }
}
void divs(int &a, int &b) {
int t = a;
a /= b;
b /= t;
}
int main() {
using namespace std;
using namespace non_std;
int i_care_for_this_one = 4;
divs(i_care_for_this_one, lvalue(2));
cout << i_care_for_this_one << endl;
}
error C2102: '&' requires l-value
. - person Retired Ninja   schedule 07.11.20145
... это prvalue согласно 3.10/1. Значение литерала, такого как12
,7.3e5
илиtrue
, также является цена. (Обратите внимание, что значения prvalue не являются значениями gl). - person Tony Delroy   schedule 07.11.2014move
d. - person Brian Bi   schedule 07.11.2014std::move()
- это библиотечная функция, получающая аргумент prvalue - обычно вы ожидаете, что значениеint
будет передано в регистр ЦП. И, с другой стороны, вы обычно ожидаете, чтоint&
будет реализована какint*
, поэтому мы рассматриваем необходимость того, чтобыmove
каким-то образом выделил адрес памяти для копирования значения. Я нахожу весьма примечательным, что clang, по-видимому, делает это... предполагает, чтоmove()
использует какой-то встроенный компилятор, который фактически запрашивает дополнительную записьint
в стеке... смутно похоже на (фиксированную)alloca
? - person Tony Delroy   schedule 07.11.2014reinterpret_cast<T&>(x)
имеет тот же эффект, что и преобразование*reinterpret_cast<T*>(&x)
со встроенными операторами&
и*
в сочетании с cppreference's для rvalue, включая prvalues &std::move(val) недействительны, но я не могу найти стандартные кавычки поддерживая утверждение cppreference. Я думаю, что ответ Дитмара Кюля ближе всего к этому.... - person Tony Delroy   schedule 07.11.2014const &T
, не являются чем-то новым и никогда не были проблемой, так что это просто небольшое расширение, и Брайан хорошо процитировал [dcl.init.ref] в своем ответе. - person pepper_chico   schedule 07.11.2014move
не принимает prvalue, он принимает универсальную ссылку. Я не уверен, что это должно быть абсолютно законно, но мне нравится ваш вопрос. проголосовал за это. - person v.oddou   schedule 21.11.2014