Reputation: 1062
this is more of an ask for opinions, rather than a specific difficulty that I'm having with my codebase. Take the following simple example:-
class Ref
{
public:
Ref(char* s, size_t l) : _s(s), _l(l) {}
private:
char* _s;
size_t _l;
};
std::stringstream ss;
char a[256];
ss >> Ref(a, sizeof(a)); // <-------- here is the discussion line
friend std::stringstream& operator>>(std::stringstream& ss, Ref& r)
{
// perform some functionality
}
Now when using Visual Studio the above compiles fine... It seems to figure out that when I use the operator >>, that because I have an override that takes a reference that I mean to pass the created object as a reference. However, when using gcc, it throws a wobbly. It complains that I have no operator overload for the operation.
Technically, I think gcc is correct because I am creating the object and essentially passing the object to the operator and not a reference to the object. I'm just wondering why the Microsoft compiler would allow this, or why gcc can't figure out that I'm intending to pass it by reference? In the above case, where the Ref object is fairly trivial, passing by reference or the object itself matters little, but if Ref was something more complex and heavy, then it probably could end up being an issue.
So, I'm asking people what they think about the above... and give some recommendations. Obviously you could construct Ref and pass by reference, or change the operator overload to take the object rather than a reference, but it's really a more about this difference between Visual Studio and gcc and what your opinion is.
Upvotes: 0
Views: 117
Reputation: 227400
The problem is that you are attempting to bind a temporary to a non-const lvalue reference, which is not allowed in standard C++. Visual studio has an extension that makes your code compile, whereas GCC sticks to the standard.
You can bypass the problem entirely by not passing a temporary:
Ref r(a, sizeof(a));
ss >> r;
Upvotes: 1
Reputation: 55395
MSVC has got an extension that allows binding a reference to non-const to a temporary object. This is non-standard behaviour. Gcc doesn't have such an extension and rightfuly complains.
ss >> Ref(a, sizeof(a));
// ^^^^^^^^^^^^^^^^^^
// temporary
friend std::stringstream& operator>>(std::stringstream& ss, Ref& r)
// reference to non-const ^^^^^^
Obviously you could construct Ref and pass by reference, or change the operator overload to take the object rather than a reference.
The latter isn't really an option if you need to use Ref
object after the call to operator>>
. The former is the way to go.
Upvotes: 2
Reputation: 52365
gcc is correct, you need const Ref& r
for it to compile.
Ref(a, sizeof(a))
creates a temporary and this can only be bound to constant lvalue references.
The reason Microsoft compiles the code, is due to its non-conforming evil extension which allows non-const lvalue references to bind to temporaries. Compile with /W4
to get a warning about it.
Upvotes: 2