I was told that references work with const pointers deep down so shouldn't this be legal code?
I think you misinterpreted what you were told. References may be implemented "under the hood" as pointers (or may not be.) But, references are never pointers. They are always references.
A car may use a particular engine for propulsion or may not. A car is not an engine.
Does that mean that the compiler thinks of them as different types except deep down a reference is implemented with a pointer?
Is this right?
Compilers don't have opinions about code. References are references. Pointers are pointers. They are different types.
Before C++11 it was, because multiple &'s were combined into single &. In C++11 && started to mean r-value reference and multiple & (like int & & & x) is now allowed only in template argument deduction stage (Info from Scott Meyers' "Overview of new C++11") or typedefs.
Edit:standard 8.5.3p5:
If T1 is reference-related to T2 and the reference is an rvalue reference, the initializer expression shall not be an lvalue. Example:
1 2 3 4 5 6 7 8
constdouble& rcd2 = 2; // rcd2 refers to temporary with value 2.0
double&& rrd = 2; // rrd refers to temporary with value 2.0constvolatileint cvi = 1;
constint& r2 = cvi; // error: type qualifiers dropped
double d2 = 1.0;
double&& rrd2 = d2; // error: copying lvalue of related typeint i3 = 2;
double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0
Looks like your compiler is not standard comliant. Gcc 4.8 will issue an error (and GCC 4.7.2 too: http://ideone.com/BYkCA0 ).
I have posted standard quote above as a proof that GCC behavior there is standard compliant.
I don't know of any compilers that would agree with you. If it did work that way, std::move wouldn't be necessary for non-temporary arguments to functions that take rvalue references, which would lead to all sorts of problems.
I think you might be confusing this with how the template stuff works with regard to rvalue references.
In the Standard there is written that "In general, the effect of this rule is that named rvalue references are treated as lvalues" And further there is an example
A a;
A&& ar = static_cast<A&&>(a);
The expression ar is an lvalue
EDIT: Try the following code
1 2 3 4 5 6 7 8 9
void f( int &x ) { x = 10; }
int main()
{
int x = 0;
int &&r = static_cast<int &&>( x );
f( r );
}
You are misunderstood that rvalue-references can be lvalues or rvalues depending on context but they are not stop being rvalue-references. There is some misleading naming here. Rvalue-references are just a method to implement optimal way to say "This value is not needed anymore, do whatever you like with it" and use faster implementations if told to (again explained in "Overview of new C++11"). It is just like const: you can throw it away if you want to, but why are you declared it const in first place? As compiler doesnt let you to call a member function on const object unless it explicitly defined as const, it won't let you to assign lvalue to rvalue reference until you explicitly say so (by manual cast or move()). std::move does exactly what you posted: static_cast to rvalue-reference. Two following snippets are similar in spirit:
1 2 3 4 5 6 7 8
constint x = 1;
const_cast<int>(x) = 2; //I know that I removing const here, but I need to do this
int x = 0;
int &&r = std::move(x); //or static_cast<int &&>( x ); move does almost exactly that
//I use move semantic here and I know that use of x after that will lead to undefined behavior
//I just want to make sure that fastest way of assigment will be used
//(Doesn't make sense for int, but it is intended to use on complex types after all)
indeed there is some confusion in the naming because similar-sounding names are used to describe two non-overlapping concepts:
rvalue/lvalue is a quality of an expression. A type is never lvalue or rvalue. An object is never lvalue or rvalue. A function cannot "return an lvalue". value category is orthogonal to type system.
lvalue reference/rvalue reference is a property of a type. A variable (but not an object) can have lvalue/rvalue reference type. A function may return lvalue/rvalue reference. An expression never has a reference type (this is the bit that many people don't realize).