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

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.

Related

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?

Is this valid C++ code? (Using local type outside scope of declaration) [duplicate]

This question already has an answer here:
type defined in free function, accessible through auto outside. Language Bug or Feature?
(1 answer)
Closed 4 years ago.
Is the following code valid according to (any) C++ ISO standards?
#include <functional>
auto a() {
struct Foo {
};
return []() {return Foo{}; };
}
int main()
{
auto l = a()();
decltype(l) ll;
//Foo f; //error: unknown type name 'Foo'
return 0;
}
The compilers (Visual studio 2015, latest Clang and latest GCC) accept this but it seems weird that decltype should give me access to Foo.
Yes.
It is actually the name of the type that is scoped, not the type itself.
You're not using its name, so everything is fine.

Calling non static function or constructor using "class::func()" from outside [duplicate]

This question already has answers here:
Program being compiled differently in 3 major C++ compilers. Which one is right?
(2 answers)
Closed 7 years ago.
I saw this snippet on Meeting C++ (#meetingcpp)
Following code compiles fine on clang and MSVC (Can try here) but fails on gcc and icc.
#include <iostream>
using namespace std;
struct B {};
struct C {
C() { cout << "C()\n"; }
C(B *) { cout << "C(B *)\n"; }
};
B *p = nullptr;
int main() {
C::C(p);
return 0;
}
Is this a known bug in Clang and MSVC or there are any chances this code may be legal?
Type of p is B *, but C::C should not compile?
This is a known bug in Clang, bug reports 23253, 23254 and 13403 are all reports of the issue. Ironically, this question is actually a duplicate of Program being compiled differently in 3 major C++ compilers. Which one is right?.
According to the standard 12.1/p2 Constructors [class.ctor] (Emphasis Mine):
A constructor is used to initialize objects of its class type.
Because constructors do not have names, they are never found during name lookup; however an explicit type conversion using the
functional notation (5.2.3) will cause a constructor to be called to
initialize an object. [ Note: For initialization of objects of class
type see 12.6. — end note ]
Thus, you can't call a constructor directly, because constructors do not have names and they are never found during name lookup.
Consequently, GCC is conforming while CLANG and VC++ are not.

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

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.