Breaking Changes in Visual C++

This document lists the breaking changes in Visual C++ in Visual Studio 2012.

Visual C++ Compiler

  • The /Yl compiler option has changed. By default, the compiler uses this option, which can lead to LNK2011 errors under certain conditions. For more information, see /Yl (Inject PCH Reference for Debug Library).

  • In code that's compiled by using /clr, the enum class keyword defines a C++11 enum, not a common language runtime (CLR) enum. To define a CLR enum, you must be explicit about its accessibility. The following example demonstrates this.

    enum class ArrivalStatus // C++11 scoped enum
    {
        Late, OnTime, Early
    };
    
    private enum class DepartureStatus // CLR enum (because of explicit accessibility)
    {
        Late, OnTime, Early
    };
    
    void PrintStatus(ArrivalStatus arrival, DepartureStatus departure)
    {
        Console.WriteLine("Departure: {0}, Arrival: {1}", 
            departure.ToString(), 
            arrival.ToString() // ERROR: not a CLR enum; does not support .ToString()
            );
    } 
    
  • Use the template keyword to explicitly disambiguate a dependent name (C++ Language Standard compliance). In the following example, the highlighted template keyword is mandatory to resolve the ambiguity. For more information, see Name Resolution for Dependent Types.

    template <typename X, typename AY> struct Container {
        typedef typename AY::template Rebind<X>::Other AX;
    };
    
  • Constant expression of type float is no longer allowed as a template argument, as shown in the following example.

    template<float n>
    struct B {};  // error C2762: 'float': illegal type for non-type template parameter 'n'
    
    template<int n>
    struct A {};
    
    A<1.1> a1; // error C2762: 'A': invalid expression as a template argument for 'n'
    A<(int)1.1> a2; // ok
    
  • Code that's compiled by using the /GS command-line option and that has an off-by-one vulnerability may lead to process termination at runtime, as shown in the following pseudocode example.

    char buf[MAX];
    int cch;
    ManipulateString(buf, &cch);
    // ...
    buf[cch] = '\0'; // if cch >= MAX, process will terminate
    
  • The default architecture for x86 builds is changed to SSE2; therefore, the compiler may emit SSE instructions, and will use the XMM registers to perform floating-point calculations. If you want to revert to previous behavior, then use the /arch:IA32 compiler flag to specify the architecture as IA32.

  • The compiler may issue warnings C4703 and C4701 where previously it did not. The compiler applies stronger checks for use of uninitialized local variables of pointer type.

  • When the new linker flag /HIGHENTROPYVA is specified, Windows 8 typically causes memory allocations to return a 64-bit address. (Prior to Windows 8, such allocations more often returned addresses that were less than 2 GB.)  This may expose pointer truncation bugs in existing code. By default, this switch is on.  To disable this behavior, specify /HIGHENTROPYVA:NO.

  • The managed compiler (Visual Basic/C#) also supports /HIGHENTROPYVA for managed builds.  However, in this case, the /HIGHENTROPYVA switch is off by default.

Integrated Development Environment

  • The following project templates no longer exist:

    • Windows Forms Application

    • Windows Forms Control Library

  • Although we recommend that you do not create Windows Forms applications in C++/CLI, maintenance of existing C++/CLI UI applications is supported. If you have to create a Windows Forms application, or any other .NET UI application, use C# or Visual Basic. Use C++/CLI for interoperability purposes only.

Visual C++ Libraries

Parallel Patterns Library and Concurrency Runtime Library

The SchedulerType enumeration of UmsThreadDefault is deprecated. Specification of UmsThreadDefault produces a deprecated warning, and internally maps back to the ThreadScheduler.

Standard Template Library

  • Following a breaking change between the C++98/03 and C++11 standards, using explicit template arguments to call make_pair()—as in make_pair<int, int>(x, y)—typically does not compile in Visual C++ in Visual Studio 2012. The solution is to always call make_pair() without explicit template arguments—as in make_pair(x, y). Providing explicit template arguments defeats the purpose of the function. If you require precise control over the resulting type, use pair instead of make_pair—as in pair<short, short>(int1, int2).

  • Another breaking change between the C++98/03 and C++11 standards: When A is implicitly convertible to B and B is implicitly convertible to C, but A is not implicitly convertible to C, C++98/03 and Visual C++ 2010 permitted pair<A, X> to be converted (implicitly or explicitly) to pair<C, X>. (The other type, X, is not of interest here, and this is not specific to the first type in the pair.) Because C++11 and Visual C++ in Visual Studio 2012 detect that A is not implicitly convertible to C, they remove the pair conversion from overload resolution. This is a positive change for many scenarios. For example, overloading func(const pair<int, int>&) and func(const pair<string, string>&), and calling func() with pair<const char *, const char *> will compile with this change. However, this change breaks code that relied on aggressive pair conversions. Such code can typically be fixed by performing one part of the conversion explicitly—for example, by passing make_pair(static_cast<B>(a), x) to a function that expects pair<C, X>.

  • Visual C++ 2010 simulated variadic templates—for example, make_shared<T>(arg1, arg2, argN)—up to a limit of 10 arguments, by stamping out overloads and specializations with preprocessor machinery. In Visual C++ in Visual Studio 2012, this limit is reduced to 5 arguments to improve compile times and compiler memory consumption for the majority of users. However, you can set the previous limit by explicitly defining _VARIADIC_MAX as 10, project-wide.

  • C++11 17.6.4.3.1 [macro.names]/2 forbids macro-izing keywords when C++ Standard Library headers are included. The headers now emit compiler errors if they detect macro-ized keywords. (Defining _ALLOW_KEYWORD_MACROS allows such code to compile, but we strongly discourage that usage.) As an exception, macro-ized new is permitted by default, because the headers comprehensively defend themselves by using #pragma push_macro("new")/#undef new/#pragma pop_macro("new"). Defining _ENFORCE_BAN_OF_MACRO_NEW does exactly what its name implies.

  • To implement various optimizations and debugging checks, the C++ Standard Library implementation intentionally breaks binary compatibility among versions of Visual Studio (2005, 2008, 2010, 2012). When the C++ Standard Library is used, this forbids the mixing of object files and static libraries that are compiled by using different versions into one binary (EXE or DLL), and forbids the passing of C++ Standard Library objects between binaries that are compiled by using different versions. The mixing of object files and static libraries (using the C++ Standard Library) that were compiled by using Visual C++ 2010 with those that were compiled by using Visual C++ in Visual Studio 2012 emits linker errors about _MSC_VER mismatch, where _MSC_VER is the macro that contains the compiler's major version (1700 for Visual C++ in Visual Studio 2012). This check cannot detect DLL mixing, and cannot detect mixing that involves Visual C++ 2008 or earlier.

  • In addition to detecting _ITERATOR_DEBUG_LEVEL mismatches, which was implemented in Visual C++ 2010, Visual C++ in Visual Studio 2012 detects Runtime Library mismatches. These occur when the compiler options /MT (static release), /MTd (static debug), /MD (dynamic release), and /MDd (dynamic debug) are mixed.

  • operator<(), operator>(), operator<=(), and operator>=() were previously available for the std::unordered_map and stdext::hash_map families of containers, although their implementations were not actually useful. These non-standard operators have been removed in Visual C++ in Visual Studio 2012. Additionally, the implementation of operator==() and operator!=() for the std::unordered_map family has been extended to cover the stdext::hash_map family. (We recommend that you avoid the use of the stdext::hash_map family in new code.)

  • C++11 22.4.1.4 [locale.codecvt] specifies that codecvt::length() and codecvt::do_length() should take modifiable stateT& parameters, but Visual C++ 2010 took const stateT&. Visual C++ in Visual Studio 2012 takes stateT& as mandated by the standard. This difference is significant for anyone who is attempting to override the virtual function do_length().

CRT Library

  • The C Runtime (CRT) heap, which is used for new and malloc(), is no longer private. The CRT now uses the process heap. This means that the heap is not destroyed when a DLL is unloaded, so DLLs that link statically to the CRT must ensure memory that's allocated by the DLL code is cleaned up before it’s unloaded.

  • The iscsymf() function asserts with negative values.

  • The threadlocaleinfostruct struct has changed to accommodate the changes to locale functions.

  • CRT functions that have corresponding intrinsics such as memxxx(), strxxx() are removed from intrin.h. If you included intrin.h only for these functions, you must now include the corresponding CRT headers.

MFC and ATL Libraries

Removed Fusion support (afxcomctl32.h); therefore, all methods that are defined in afxcomctl32.h have been removed. Header files afxcomctl32.h and afxcomctl32.inl have been deleted.

Changed the name of CDockablePane::RemoveFromDefaultPaneDividier to CDockablePane::RemoveFromDefaultPaneDivider.

Changed the signature of CFileDialog::SetDefExt to use LPCTSTR; therefore, Unicode builds are affected.

Removed obsolete ATL tracing categories.

Changed the signature of CBasePane::MoveWindow to take a const CRect.

Changed the signature of CMFCEditBrowseCtrl::EnableBrowseButton.

Removed m_fntTabs and m_fntTabsBold from CMFCBaseTabCtrl.

Added a parameter to the CMFCRibbonStatusBarPane constructors. (It is a default parameter, and so it is not source-breaking.)

Added a parameter to the CMFCRibbonCommandsListBox constructor. (It is a default parameter, and so it is not source-breaking.)

Removed the AFXTrackMouse API (and related timer proc). Use the Win32 TrackMouseEvent API instead.

Added a parameter to the CFolderPickerDialog constructor. (It is a default parameter, and so it is not source-breaking.)

CFileStatus structure size changed: The m_attribute member changed from BYTE to DWORD (to match the value that's returned from GetFileAttributes).

CRichEditCtrl and CRichEditView use MSFTEDIT_CLASS (RichEdit 4.1 control) instead of RICHEDIT_CLASS (RichEdit 3.0 control) in Unicode builds.

Removed AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground because it is always TRUE on Windows Vista, Windows 7, and Windows 8.

Removed AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable because it is always TRUE on Windows Vista, Windows 7, and Windows 8.

Removed AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. Call Windows API directly on Windows Vista, Windows 7, and Windows 8.

Removed AFX_GLOBAL_DATA::DwmDefWindowProc. Call Windows API directly on Windows Vista, Windows 7, and Windows 8.

Renamed AFX_GLOBAL_DATA::DwmIsCompositionEnabled to IsDwmCompositionEnabled to eliminate name collision.

Changed identifiers for a number of MFC internal timers and moved the definitions to afxres.h (AFX_TIMER_ID_*).

Changed the signature of OnExitSizeMove method to agree with the ON_WM_EXITSIZEMOVE macro:

  • CFrameWndEx

  • CMDIFrameWndEx

  • CPaneFrameWnd

Changed the name and signature of OnDWMCompositionChanged to agree with the ON_WM_DWMCOMPOSITIONCHANGED macro:

  • CFrameWndEx

  • CMDIFrameWndEx

  • CPaneFrameWnd

Changed the signature of OnMouseLeave method to agree with the ON_WM_MOUSELEAVE macro:

  • CMFCCaptionBar

  • CMFCColorBar

  • CMFCHeaderCtrl

  • CMFCProperySheetListBox

  • CMFCRibbonBar

  • CMFCRibbonPanelMenuBar

  • CMFCRibbonRichEditCtrl

  • CMFCSpinButtonCtrl

  • CMFCToolBar ReplaceThisText

  • CMFCToolBarComboBoxEdit

  • CMFCToolBarEditCtrl

  • CMFCAutoHideBar

Changed the signature of OnPowerBroadcast to agree with the ON_WM_POWERBROADCAST macro:

  • CFrameWndEx

  • CMDIFrameWndEx

Changed the signature of OnStyleChanged to agree with the ON_WM_STYLECHANGED macro:

  • CMFCListCtrl

  • CMFCStatusBar

Renamed the internal method FontFamalyProcFonts to FontFamilyProcFonts.

Removed numerous global static CString objects to eliminate memory leaks in some situations (replaced with #defines), and the following class member variables:

  • CKeyBoardManager::m_strDelimiter

  • CMFCPropertyGridProperty::m_strFormatChar

  • CMFCPropertyGridProperty::m_strFormatShort

  • CMFCPropertyGridProperty::m_strFormatLong

  • CMFCPropertyGridProperty::m_strFormatUShort

  • CMFCPropertyGridProperty::m_strFormatULong

  • CMFCPropertyGridProperty::m_strFormatFloat

  • CMFCPropertyGridProperty::m_strFormatDouble

  • CMFCToolBarImages::m_strPngResType

  • CMFCPropertyGridProperty::m_strFormat

Changed the signature of CKeyboardManager::ShowAllAccelerators and removed the accelerator delimiter parameter.

Added CPropertyPage::GetParentSheet, and in the CPropertyPage class, call it instead of GetParent to get the correct parent sheet window, which may be the parent or a grandparent window to CPropertyPage. You might have to change your code to call GetParentSheet instead of GetParent.

Fixed unbalanced #pragma warning(push) in ATLBASE.H, which caused warnings to be disabled incorrectly. Those warnings are now enabled correctly after ATLBASE.H has been parsed.

Moved D2D-related methods from AFX_GLOBAL_DATA to _AFX_D2D_STATE:

  • GetDirectD2dFactory

  • GetWriteFactory

  • GetWICFactory

  • InitD2D

  • ReleaseD2DRefs

  • IsD2DInitialized

  • D2D1MakeRotateMatrix

  • Instead of calling, for example, afxGlobalData.IsD2DInitialized, call AfxGetD2DState->IsD2DInitialized.

Removed obsolete ATL*.CPP files from the \atlmfc\include\ folder.

Moved afxGlobalData initialization to on-demand instead of at CRT initialization time, to satisfy DLLMain requirements.

Added the RemoveButtonByIndex method to the CMFCOutlookBarPane class.

Corrected CMFCCmdUsageCount::IsFreqeuntlyUsedCmd to IsFrequentlyUsedCmd.

Corrected several instances of RestoreOriginalstate to RestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).

Removed unused methods from CDockablePane: SetCaptionStyle, IsDrawCaption, IsHideDisabledButtons, GetRecentSiblingPaneInfo, and CanAdjustLayout.

Removed CDockablePane static member variables m_bCaptionText and m_bHideDisabledButtons.

Added an override DeleteString method to CMFCFontComboBox.

Removed unused methods from CPane: GetMinLength and IsLastPaneOnLastRow.

Renamed CPane::GetDockSiteRow(CDockingPanesRow *) to CPane::SetDockSiteRow.

See Also

Other Resources

Getting Started with Visual C++ in Visual Studio 2012