Visual C++ is so Liberal

Warning! Some information on this page is older than 5 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Jan 2012

Here is an issue in C++ code I've came across some time ago and recently I've found again in some other code. This code is invalid according to language standard, still it compiles in Visual C++/Visual Studio and works correctly. Can you see what's wrong with it?

class Class1
    int m_Number;
    Class1( int number ) : m_Number( number ) { }

void Function1( Class1& obj1 )
    obj1.m_Number = 2;

int main()
    Function1( Class1( 1 ) );

The problem is that we pass a temporary object of Class1 to the Function1, while this function takes object by reference, not by reference to const. Such R-value shouldn't be converted to non-const reference, or else we could modify the temporary object - which we actually do inside the function.

Visual C++ 2008 and 2010 with default project options compiles this without any warning. Setting Warning Level to 4 (/W4) generates a warning:

warning C4239: nonstandard extension used : 'argument' : conversion from 'Class1' to 'Class1 &'

Using Disable Language Extensions (/Za) makes it an error:

error C2664: 'Function1' : cannot convert parameter 1 from 'Class1' to 'Class1 &' A non-const reference may only be bound to an lvalue

It means we are dealing with a nonstandard Microsoft extension here. GCC refuses to compile this code, even with standard options:

error: invalid initialization of non-const reference of type 'Class1&' from an rvalue of type 'Class1' error: in passing argument 1 of 'void Function1(Class1&)'

Another story: Today I've learned that C++ standard doesn't have forward declarations of enums. I used it for long time and now I know it's another nonstandard Microsoft extension.

My conclusion is that programming in C++ using Visual C++ is like programming in DirectX using NVIDIA graphics cards: the platform is so liberal that your code may work even if you do something invalid. It also means that to use portable libraries instead of WinAPI is not enought to write code portable from Windows to Linux and other platform. You should also check if your code is accepted by other compilers. Increasing warning level in project options can also help with that, just like using Debug Version of Direct3D in DiectX Control Panel and observing debugger Output to find possible problems in calls to Direct3D API. It's better to ensure early that your code is valid instead of later complain that alternative (GCC) compiler or alternative (AMD) GPU driver causes problems.

On the other hand I believe that platform independence and strict C++ standard correctness is not a great value in itself. If you know your code is supposed to just work under Windows and be compiled in Visual C++, why not make use of available extensions and rely on specific compiler behavior? It can be convenient, while maintaining code that have to work with different compilers and platforms is a lot of additional work, possibly unnecesary.

Comments | #c++ #visual studio Share


[Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2020