VS2010: Temporaries can't be bound to non-const references [duplicate] - c++

This question already has answers here:
rvalue to lvalue conversion Visual Studio
(3 answers)
Closed 8 years ago.
I came to know that Temporaries connot be bound to non-const references.
class X
{
int i;
};
X fun()
{
return X();
}
void func(X &x)
{
}
int main()
{
func(fun());
return 0;
}
Isn't call to fun producing a temporary? Why can temporary be linked to non-const reference here. I am unable to comprehend as to why is this compiling fine.
EDIT:
I am using VS2010. I don't understand how should this matter.

Isn't call to fun producing a temporary?
Yes.
Why can temporary be linked to non-const reference here.
It can't.
I am unable to comprehend as to why is this compiling fine.
Because your compiler is faulty.
I am using VS2010. I don't understand how should this matter.
That compiler has many non-standard "extensions" to the language. This is just one example of dodgy code that's accepted by that compiler, but not a conformant one.

Related

Reference to lvalue or rvalue for fundamental types or object [duplicate]

This question already has answers here:
Reference a temporary in msvc
(2 answers)
Closed last year.
I observe a different behavior for the compiler with the 2 following snippets of code:
With the first one, all seems OK to me with fundamental type like int:
void fi1(int& a) {}
void fi2(int&& a) {}
void func1() {
fi1(2+2); // Do not compile: normal since '2+2' is temporary and is not a variable
int a = 5;
fi2(a); // Do not compile: normal since 'a' is an lvalue
}
But I do not understand the second one with object type:
void fs1(string& a) {}
void fs2(string&& a) {}
void func2() {
fs1(string{""}); // Compile: but weird for me since there is no variable to reference !
fs2(string{""}); // Compile: normal since 'string{""}' is temporary and is not a variable
}
In the following post:
Understanding lvalue/rvalue expression vs object type
it is explained that an lvalue is when you can take its address. For sure, string{""} shall have an address somewhere in memory. But for me a key-point with rvalue is that you can't use it afterwards, making 'move semantic' possible.
When you are in fs2 function, the argument is an rvalue and you can do whatever you want without any side effect. In fs1, you expect that some variable elsewhere will have some impact if you modify it. fs2 should only be called with variable argument.
And why is working as expected with int and not with object ?
This strange behavior is due to the usage of MSVC.

const reference argument of constexpr function: gcc/msvc vs clang/icc [duplicate]

This question already has answers here:
Static member access in constant expressions
(2 answers)
Closed 3 years ago.
I've discovered that calling a constexpr static method using a constant reference argument leads to an error "expression is not an integral constant" for both clang and icc, but not for gcc or msvc (https://godbolt.org/z/PewOVc):
struct S
{
static constexpr bool ok() { return true; }
};
constexpr void ff(const S &s) // OK for everyone if not a ref
{
static_assert(s.ok(), "oops!"); // ERROR clang/icc, OK gcc/msvc
static_assert(S::ok(), "oops!"); // OK for everyone
}
If argument is not a reference then code compiles by any of these compilers. Who is right/correct here?
The C++ standard disqualifies evaluated id-expressions that have reference types from participating in constant-expressions (unless some more constraints are met, which is not the case for this code).
However gcc seems to ignore this rule. The same result (gcc accepts, clang rejects) can be obtained with this simplified function:
constexpr void ff(const int &s)
{
static_assert((s, true), "oops!");
}
So the problem has nothing to do with static member functions. My interpretation is that this is a gcc bug.
I did not check msvc, maybe the bug is different there but it's still wrong.

Why is this variable considered an lvalue? [duplicate]

This question already has answers here:
Why are rvalues references variables not rvalue?
(3 answers)
Rvalue Reference is Treated as an Lvalue?
(4 answers)
Closed 3 years ago.
Considering this code
class T {
public:
T(T& x) = delete;
T(T&& x) {}
};
void foo(T&& b) {
T y(b);
}
I was expecting that b; which is an rvalue by declaration; and seemingly usage, should be passed into the move constructor of T in foo().
Instead; I get a compilation error reporting that T& has been deleted.
Replacing it with
void foo(T&& c) {
T y(std::move(c));
}
Results in the expected success; but obviously one doesn't want to litter their code with std::move everywhere.
As tempting as it is to blame visual studio - in this case I suspect it's my understanding that's wrong. Can someone please explain why move constructor isn't used?

Why Visual C++ compiler allows temporary assignments to lvalue references? [duplicate]

This question already has answers here:
Non-const reference bound to temporary, Visual Studio bug?
(2 answers)
Closed 5 years ago.
I have the following code on Visual C++ 17 compiler:
#include "stdafx.h"
class Foo {};
Foo FuncBar()
{
return Foo();
}
int main()
{
Foo &myFoo = FuncBar();
}
Normally IIRC, assigning temporaries to lvalues should be illegal. Here I am returning a temporary Foo() and binding it to an lvalue ref.
However this code compiles and even runs fine. Why is this allowed?
It is a Microsoft C++ extension. You can make the compilation fail by using the /Za flag.

Binding rvalue to const lvalue reference [duplicate]

This question already has answers here:
Why not non-const reference to temporary objects? [duplicate]
(4 answers)
Closed 6 months ago.
For some reason I didn't manage to find this exact question. Why is it allowed to bind an rvalue to const lvalue reference, although it is impossible to to the same without the const?
I do understand that the lifetime of the rvalue gets an extension somehow (in the first case) , but if so, why would the compiler disallow changing that 'rvalue', which is not really a temporary object anymore.
For example, consider the following code:
int main(){
int &i=3; //produces error
const int&j =3; //compiles
return 1;
}
You may find the following article useful:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf
I might be entirely wrong here, but this is how I rationalise it. An rvalue is constant, it cannot be changed. you cannot change the integer 5, fact. So when you bind the references the lvalue will have to be const. Otherwise your compiler will throw an error:
obj & a1 = bar();
invalid initialization of non-const reference of type ‘obj&’ from an rvalue of type ‘obj’
using g++
The only way to safely bind an rvalue to an lvalue is either by marking the lvalue as const, or using a mutable rvalue reference && (introduced in C++11 believe?)
struct obj {
};
obj bar() {
obj x;
return x;
}
int main() {
const obj & a1 = bar();
obj && a2 = bar();
return 0;
};
If you're asking about
void f(const int&);
f(1);
versus
void g(int&);
g(1);
the answer is to think about what happens if g looks like this:
void g(int& r) {
++r;
}
The name r-value comes from the right-value: which (roughly) means things that are on the right side of a x=y kind of statement. It is like: it can be read from, but it may not be suitable to be written on. For example a numeric literal can be on the right side (a=3) but it does not make sense to be on the left side (3=a).
With this reasoning, it looks logical to me why it is allowed to make const l-value references to r-values but not allowed to make non-const references.