Microsoft C/C++ change history 2003 - 2015 (original) (raw)

This article describes all the breaking changes from Visual Studio 2015 going back to Visual Studio 2003, and in this article the terms "new behavior" or "now" refer to Visual Studio 2015 and later. The terms "old behavior" and "before" refer to Visual Studio 2013 and earlier releases.

For information about the latest version of Visual Studio, see What's new for C++ in Visual Studio and C++ conformance improvements in Visual Studio.

Note

There are no binary breaking changes between Visual Studio 2015 and Visual Studio 2017.

When you upgrade to a new version of Visual Studio, you might encounter compilation and/or runtime errors in code that previously compiled and ran correctly. Changes in the new version that cause such problems are known as breaking changes, and typically they're required by modifications in the C++ language standard, function signatures, or the layout of objects in memory.

To avoid run-time errors that are difficult to detect and diagnose, we recommend that you never statically link to binaries compiled by using a different version of the compiler. Also, when you upgrade an EXE or DLL project, make sure to upgrade the libraries that it links to. Don't pass CRT (C Runtime) or C++ Standard Library (C++ Standard Library) types between binaries, including DLLs, compiled by using different versions of the compiler. For more information, see Potential Errors Passing CRT Objects Across DLL Boundaries.

You should never write code that depends on a particular layout for an object that isn't a COM interface or a POD object. If you do write such code, then you must ensure that it works after you upgrade. For more information, see Portability At ABI Boundaries.

Additionally, ongoing improvements to compiler conformance can sometimes change how the compiler understands your existing source code. For example, you might find new or different errors during your build, or even behavioral differences in code that previously built and seemed to run correctly. Although these improvements aren't breaking changes like the ones discussed in this document, you may need to make changes to your source code to resolve these issues:

Visual Studio 2015 Conformance Changes

C Runtime Library (CRT)

General Changes

<locale.h>

<math.h>

warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of data  

The fix for this warning is to replace the call to abs with a floating point version of abs, such as fabs for a double argument or fabsf for a float argument, or include the <cmath> header and continue to use abs.

<new> and <new.h>

<process.h>

<stdarg.h>

<stdio.h> and <conio.h>

dumpbin.exe /LINKERMEMBER somelibrary.lib  
printf("%.0f\n", pow(2.0, 80))  

Old output:

1208925819614629200000000  

New output:

1208925819614629174706176  

The old parsing algorithms would consider only up to 17 significant digits from the input string and would discard the rest of the digits. This approach is sufficient to generate a close approximation of the value represented by the string, and the result is usually very close to the correctly rounded result. The new implementation considers all present digits and produces the correctly rounded result for all inputs (up to 768 digits in length). In addition, these functions now respect the rounding mode (controllable via fesetround). This is potentially a breaking behavior change because these functions might output different results. The new results are always more correct than the old results.

<stdlib.h>, <malloc.h>, and <sys/stat.h>

<string.h>

wchar_t* wcstok(wchar_t*, wchar_t const*)  

It used an internal, per-thread context to track state across calls, as is done for strtok. The function now has the signature wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**), and requires the caller to pass the context as a third argument to the function.
A new _wcstok function has been added with the old signature to ease porting. When compiling C++ code, there is also an inline overload of wcstok that has the old signature. This overload is declared as deprecated. In C code, you may define_CRT_NON_CONFORMING_WCSTOK to cause _wcstok to be used in place of wcstok.

<time.h>

C++ Standard Library

To enable new optimizations and debugging checks, the Visual Studio implementation of the C++ Standard Library intentionally breaks binary compatibility from one version to the next. Therefore, when the C++ Standard Library is used, object files and static libraries that are compiled by using different versions can't be mixed in one binary (EXE or DLL), and C++ Standard Library objects can't be passed between binaries that are compiled by using different versions. Such mixing emits linker errors about _MSC_VER mismatches. (_MSC_VER is the macro that contains the compiler's major version—for example, 1800 for Visual Studio 2013.) This check can't detect DLL mixing, and can't detect mixing that involves Visual Studio 2008 or earlier.

bool operator==(const MyAlloc& other)  

then you should update them and declare them as const members:

bool operator==(const MyAlloc& other) const  
bool operator()(const X& a, const X& b)  

To resolve this error, change the function declaration to:

bool operator()(const X& a, const X& b) const  

MFC and ATL

Concurrency Runtime

(concurrency::Context::Yield)();  

Compiler Conformance Improvements in Visual Studio 2015

When upgrading code from previous versions, you might also encounter compiler errors that are due to conformance improvements made in Visual Studio 2015. These improvements do not break binary compatibility from earlier versions of Visual Studio, but they can produce compiler errors where none were emitted before. For more information, see Visual C++ What's New 2003 through 2015.

In Visual Studio 2015, ongoing improvements to compiler conformance can sometimes change how the compiler understands your existing source code. As a result, you might encounter new or different errors during your build, or even behavioral differences in code that previously built and seemed to run correctly.

Fortunately, these differences have little or no impact on most of your source code. When source code or other changes are needed to address these differences, the fixes tend to be small and straight-forward. We've included many examples of previously acceptable source code that might need to be changed (before) and the fixes to correct them (after).

Although these differences can affect your source code or other build artifacts, they don't affect binary compatibility between updates to Visual Studio versions. A breaking change is more severe, and can affect binary compatibility, but these kinds of binary compatibility breaks only occur between major versions of Visual Studio, for example, between Visual Studio 2013 and Visual Studio 2015. For information on the breaking changes that occurred between Visual Studio 2013 and Visual Studio 2015, see Visual Studio 2015 Conformance Changes.

Conformance Improvements in Visual Studio 2015

Command line warning  D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future release  

Usually, this option was used in order to allow nonstandard code that uses loop variables after the point where, according to the standard, they should have gone out of scope. It was only necessary when you compiled with the /Za option, since without /Za, use of a for loop variable after the end of the loop is always allowed. If you don't care about standards conformance (for example, if your code isn't meant to portable to other compilers), you could turn off the /Za option (or set the Disable Language Extensions property to No). If you do care about writing portable, standards-conformant code, you should rewrite your code so that it conforms to the standard by moving the declaration of such variables to a point outside the loop.

// C2065 expected  
int main() {  
    // Uncomment the following line to resolve.  
    // int i;  
    for (int i = 0; i < 1; i++);  
    i = 20;   // i has already gone out of scope under /Za  
}  
struct S  
{  
    mutable int &r;  
};  

Previous versions of the compiler accepted this, but now the compiler gives the following error:

error C2071: 'S::r': illegal storage class  

To fix the error, remove the redundant mutable keyword.

#include <cstdint>  
typedef uint16_t char16_t; //C2628  
typedef uint32_t char32_t; //C2628  
int main(int argc, char* argv[])  
{  
    uint16_t x = 1; uint32_t y = 2;  
    char16_t a = x;  
    char32_t b = y;  
    return 0;  
}  

To update your code, remove the typedef declarations and rename any other identifiers that collide with these names.

struct S1  
{  
    void f(int);  
    void f(int, int);  
};  
struct S2  
{  
    template <class C, void (C::*Function)(int) const> void f() {}  
};  
void f()  
{  
    S2 s2;  
    s2.f<S1, &S1::f>();  
}  

The current compiler correctly gives an error, because the template parameter type doesn't match the template argument (the parameter is a pointer to a const member, but the function f is non-const):

error C2893: Failed to specialize function template 'void S2::f(void)'note: With the following template arguments:note: 'C=S1'note: 'Function=S1::f'  

To address this error in your code, make sure that the type of the template argument you use matches the declared type of the template parameter.

error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarations  

To fix this problem, remove __declspec(align) from the function declaration. Since it had no effect, removing it doesn't change anything.

struct S  
{  
public:  
    S();  
private:  
    S(const S &);  
};  
int main()  
{  
    throw S(); // error  
}  

The problem is that the copy constructor is private, so the object can't be copied as happens in the normal course of handling an exception. The same applies when the copy constructor is declared explicit.

struct S  
{  
    S();  
    explicit S(const S &);  
};  
int main()  
{  
    throw S(); // error  
}  

To update your code, make sure that the copy constructor for your exception object is public and not marked explicit.
Catching an exception by value also requires the exception object to be copyable. The following code compiled in Visual Studio 2013, but doesn't compile in Visual Studio 2015:

struct B  
{  
public:  
    B();  
private:  
    B(const B &);  
};  
struct D : public B {};  
int main()  
{  
    try  
    {  
    }  
    catch (D d) // error  
    {  
    }  
}  

You can fix this issue by changing the parameter type for the catch to a reference.

catch (D& d)  
{  
}  
#define _x "there"  
char* func() {  
    return "hello"_x;  
}  
int main()  
{  
    char * p = func();  
    return 0;  
}  

The compiler interpreted this code as a string literal "hello" followed by a macro, which is expanded into "there", and then the two string literals were concatenated into one. In Visual Studio 2015, the compiler interprets this sequence as a user-defined literal, but since there is no matching user-defined literal _x defined, it gives an error.

error C3688: invalid literal suffix '_x'; literal operator or literal operator template 'operator ""_x' not found  
note: Did you forget a space between the string literal and the prefix of the following string literal?  

To fix this problem, add a space between the string literal and the macro.

char * str = "abc""def";  

To fix this issue, add a space in between the two strings:

char * str = "abc" "def";  
void * operator new(std::size_t, std::size_t);  
void operator delete(void*, std::size_t) noexcept;  

The problem occurs because of the match in function signatures between a placement delete operator you've defined, and the new global sized delete operator. Consider whether you can use a different type other than size_t for any placement new and delete operators. The type of the size_t typedef is compiler-dependent; it's a typedef for unsigned int in MSVC. A good solution is to use an enumerated type such as this one:

enum class my_type : size_t {};  

Then, change your definition of placement new and delete to use this type as the second argument instead of size_t. You'll also need to update the calls to placement new to pass the new type (for example, by using static_cast<my_type> to convert from the integer value) and update the definition of new and delete to cast back to the integer type. You don't need to use an enum for this; a class type with a size_t member would also work.
An alternative solution is that you might be able to eliminate the placement new altogether. If your code uses placement new to implement a memory pool where the placement argument is the size of the object being allocated or deleted, then sized deallocation feature might be suitable to replace your own custom memory pool code, and you can get rid of the placement functions and just use your own two-argument delete operator instead of the placement functions.
If you don't want to update your code immediately, you can revert to the old behavior by using the compiler option /Zc:sizedDealloc-. If you use this option, the two-argument delete functions don't exist and won't cause a conflict with your placement delete operator.

union U1  
{  
    const int i;  
};  
union U2  
{  
    int & i;  
};  
union U3  
{  
    struct { int & i; };  
};  

The preceding code produces the following errors:

test.cpp(67): error C2625: 'U2::i': illegal union member; type 'int &' is reference type  
test.cpp(70): error C2625: 'U3::i': illegal union member; type 'int &' is reference type  

To address this issue, change reference types either to a pointer or a value. Changing the type to a pointer requires changes in the code that uses the union field. Changing the code to a value would change the data stored in the union, which affects other fields since fields in union types share the same memory. Depending on the size of the value, it might also change the size of the union.

struct S  
{  
    S();  
};  
union  
{  
    struct  
    {  
        S s;  
    };  
} u; // C2280  

The preceding code generates the following error in Visual Studio 2015:

error C2280: '<unnamed-type-u>::<unnamed-type-u>(void)': attempting to reference a deleted function  
note: compiler has generated '<unnamed-type-u>::<unnamed-type-u>' here  

To resolve this issue, provide your own definitions of the constructor and/or destructor.

struct S  
{  
    // Provide a default constructor by adding an empty function body.  
    S() {}  
};  
union  
{  
    struct  
    {  
        S s;  
    };  
} u;  
#include <stdio.h>  
struct S  
{  
    S() { printf("Creating S\n"); }  
    ~S() { printf("Destroying S\n"); }  
};  
union U  
{  
    struct {  
        S s;  
    };  
    U() {}  
    ~U() {}  
};  
void f()  
{  
    U u;  
    // Destructor implicitly called here.  
}  
int main()  
{  
    f();  
    char s[1024];  
    printf("Press any key.\n");  
    gets_s(s);  
    return 0;  
}  

In Visual Studio 2013, the constructor for S is called when the union is created, and the destructor for S is called when the stack for function f is cleaned up. But in Visual Studio 2015, the constructor and destructor aren't called. The compiler gives a warning about this behavior change.

warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly called  

To restore the original behavior, give the anonymous structure a name. The runtime behavior of non-anonymous structures is the same, regardless of the compiler version.

#include <stdio.h>  
struct S  
{  
    S() { printf("Creating S.\n"); }  
    ~S() { printf("Destroying S\n"); }  
};  
union U  
{  
    struct  
    {  
        S s;  
    } namedStruct;  
    U() {}  
    ~U() {}  
};  
void f()  
{  
    U u;  
}  
int main()  
{  
    f();  
    char s[1024];  
    printf("Press any key.\n");  
    gets_s(s);  
    return 0;  
}  

Alternatively, try moving the constructor and destructor code into new functions, and add calls to these functions from the constructor and destructor for the union.

#include <stdio.h>  
struct S  
{  
    void Create() { printf("Creating S.\n"); }  
    void Destroy() { printf("Destroying S\n"); }  
};  
union U  
{  
    struct  
    {  
        S s;  
    };  
    U() { s.Create(); }  
    ~U() { s.Destroy(); }  
};  
void f()  
{  
    U u;  
}  
int main()  
{  
    f();  
    char s[1024];  
    printf("Press any key.\n");  
    gets_s(s);  
    return 0;  
}  
#include <type_traits>  
template< typename T>  
struct S  
{  
    S() = default;  
    S(const S&);  
    S(S& &);  
    template< typename U, typename = typename std::enable_if< std::is_base_of< T, U> ::value> ::type>  
    S(S< U> & &);  
};  
struct D;  
void f1()  
{  
    S< D> s1;  
    S< D> s2(s1);  
}  
struct B  
{  
};  
struct D : public B  
{  
};  
void f2()  
{  
    S< D> s1;  
    S< D> s2(s1);  
}  

If you compile with the current compiler, you get the following error:

type_traits(1110): error C2139: 'D': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_base_of'  
..\t331.cpp(14): note: see declaration of 'D'  
..\t331.cpp(10): note: see reference to class template instantiation 'std::is_base_of<T,U>' being compiled  
with  
[  
    T=D,  
    U=D  
]  

This is because at the point of the first invocation of the is_base_of the class D hasn't been defined yet.
In this case, the fix is to not use such type traits until the class has been defined. If you move the definitions of B and D to the beginning of the code file, the error is resolved. If the definitions are in header files, check the order of the include statements for the header files to make sure that any class definitions are compiled before the problematic templates are used.

extern "C" __cdecl main(){} // C4430  

To fix the error, add the return type:

extern "C" int __cdecl main(){} // OK  
template<typename T>  
struct S1 : public T::type  
{  
    S1() : typename T::type() // C2059  
    {  
    }  
};  
struct S2 {  
    typedef S2 type;  
};  
S1<S2> s;  

To fix the error, remove typename from the initializer:

S1() : T::type() // OK  
...  
template <typename T>  
void myfunc(T h)  
{  
}  
template<>  
static void myfunc(double h) // static is ignored  
{  
}  
template <size_t some_value>  
struct S1  
{  
    static_assert(false, "default not valid"); // always invoked  
};  
//other partial specializations here  

To work around this issue, wrap the value in a struct:

template <size_t some_value>  
struct constant_false {  
    static const bool value = false;  
};  
template <size_t some_value>  
struct S1  
{  
    static_assert(constant_false<some_value>::value, "default not valid");  
};  
//other partial specializations here  
struct token_s;  
typedef int BOOL;  
typedef int INT;  
typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifier  

To fix this problem, add the proper forward declarations:

struct token_s;  
typedef int BOOL;  
typedef int INT;  
// forward declarations:  
typedef struct token_s TOKEN;  
typedef TOKEN *PTOKEN;  
typedef int(*PFNTERM)(PTOKEN, BOOL, INT);  
typedef int(*F1)(int);  
typedef int(*F2)(int, int);  
void func(F1 f, int v1, int v2)  
{  
    f(v1, v2); // C2197  
}  
template<typename R, typename T, typename T1, typename A1>  
void bind(R(T::*)(T1), A1&&);  
namespace N  
{  
    template <typename T, typename R, typename ... Tx>  
    void bind(R(T::*)(Tx...), T* ptr);  
}  
using namespace N;  
class Manager  
{  
public:  
    void func(bool initializing);  
    void mf()  
    {  
        bind(&Manager::func, this); //C2668  
    }  
};  

To fix the error, you can fully qualify the call to bind: N::bind(...). However, if this change is manifest through an undeclared identifier (C2065), then it may be appropriate to fix this with a using declaration instead.
This pattern happens frequently with ComPtr and other types in the Microsoft::WRL namespace.

// C  
typedef void (*type)(void);  
void f(int i, type p);  
void g(int);  
void h(void)  
{  
    f(0, &(type)g);  
}  
// C++  
typedef void(*type)(void);  
type f();  
void g(type);  
void h()  
{  
    g(&f());  
}  
void f(void *);  
void h(void)  
{  
    f(&__FUNCTION__);  
    void *p = &"";  
}  

To fix the error, change the function parameter type to const void*, or else change the body of h to look like this example:

void h(void)  
{  
    char name[] = __FUNCTION__;  
    f( name);  
    void *p = &"";  
}  
#define MACRO  
#define STRCAT(x, y) x\#\#y  
int main(){  
    auto *val1 = L"string"MACRO;  
    auto *val2 = L"hello "L"world";  
    std::cout << STRCAT(L"hi ", L"there");  
}  

To fix the error, change the code to add a space:

#define MACRO  
// Remove ##. Strings are automatically  
// concatenated so they aren't needed  
#define STRCAT(x, y) x y  
int main(){  
    //Add space after closing quote  
    auto *val1 = L"string" MACRO;  
    auto *val2 = L"hello " L"world";  
    std::cout << STRCAT(L"hi ", L"there");  
}  

In the example above, MACRO is no longer parsed as two tokens (a string followed by a macro). Now it's parsed as a single token UDL. The same applies to L""L"", which was parsed previously as L"" and L"", and is now parsed as L""L and "".
String concatenation rules were also brought into conformance with the standard, which means L"a" "b" is equivalent to L"ab". Previous editions of Visual Studio did not accept concatenation of strings with different character width.

bool check(wchar_t c){  
    return c == L''; //implicit null character  
}  

To fix the error, change the code to make the null explicit:

bool check(wchar_t c){  
    return c == L'\0';  
}  
struct B {  
public:  
    B();  
private:  
    B(const B &);  
};  
struct D : public B {  
};  
int main()  
{  
    try  
    {  
    }  
    catch (D) // C2316  
    {  
    }  
}  

To fix the code, you can change the catch block to catch (const D &) but the better solution is usually to use the MFC TRY/CATCH macros.

class alignof{}  
int constexpr() {return 1;}  
struct S{  
    S(int, int);  
    S(const S&) = delete;  
    S(S&&) = delete;  
};  
S s2 = S(2, 3); //C2280  

To fix the error, use direct initialization for S2:

struct S{  
    S(int, int);  
    S(const S&) = delete;  
    S(S&&) = delete;  
};  
S s2 = {2,3}; //OK  
void func(int(*)(int)) {}  
int main() {  
    func([=](int val) { return val; });  
}  

To fix the error, remove the = from the capture list.

struct S1 {  
    S1(int);  
};  
struct S2 {  
    operator S1();  
    operator int();  
};  
void f(S2 s2)  
{  
    (S1)s2;  
}  

To fix the error, explicitly call the conversion operator:

void f(S2 s2)  
{  
    //Explicitly call the conversion operator  
    s2.operator S1();  
    // Or  
    S1((int)s2);  
}  

The following code now produces error C2593: 'operator =' is ambiguous:

struct S1 {};  
struct S2 {  
    operator S1&();  
    operator S1() const;  
};  
void f(S1 *p, S2 s)  
{  
    *p = s;  
}  

To fix the error, explicitly call the conversion operator:

void f(S1 *p, S2 s)  
{  
    *p = s.operator S1&();  
}  
struct S1 {  
    explicit S1(bool);  
};  
struct S2 {  
    S1 s2 = true; // error  
};  

To fix the error, use direct initialization:

struct S2 {  
S1 s1{true}; // OK  
};  
class S {  
    S();  
public:  
    int i;  
};  
class S2 {  
    auto f() -> decltype(S().i);  
};  

To fix the error, add a friend declaration for S2 in S:

class S {  
    S();  
    friend class S2; // Make S2 a friend  
public:  
    int i;  
};  
void func(){  
    auto lambda = [](){};  
    decltype(lambda) other;  
}  

To fix the error, remove the need for the default constructor to be called. If the lambda doesn't capture anything, then it can be cast to a function pointer.

#include <memory>  
#include <type_traits>  
template <typename T, typename D>  
std::unique_ptr<T, typename std::remove_reference<D &&>::type> wrap_unique(T *p, D &&d);  
void f(int i)  
{  
    auto encodedMsg = wrap_unique<unsigned char>(nullptr, [i](unsigned char *p) {  
    });  
    encodedMsg = std::move(encodedMsg);  
}  

To fix the error, replace the lambda with a functor class or remove the need to use the assignment operator.

struct moveable {  
    moveable() = default;  
    moveable(moveable&&) = default;  
    moveable(const moveable&) = delete;  
};  
struct S {  
    S(moveable && m) :  
        m_m(m)//copy constructor deleted  
    {}  
    moveable m_m;  
};  

To fix the error, use std::move instead:

S(moveable && m) :  
    m_m(std::move(m))  
int main()  
{  
    struct S2;  
    struct S1 {  
        void f() {  
            S2 s;  
        }  
    };  
    struct S2 {};  
}  

To fix the error, move up the definition of S2:

int main()  
{  
    struct S2 { //moved up  
    };  
struct S1 {  
    void f() {  
        S2 s;  
        }  
    };  
}  
struct S1 {  
protected:  
    S1();  
};  
struct S2 : public S1 {  
    S2() {  
        S1();  
    }  
};  

To fix the error, in S2 remove the call to S1() from the constructor and if necessary put it in another function.

struct S {  
    S() : p({ 0 }) {}  
    void *p;  
};  

To fix the error, remove the braces from around the 0 or else use nullptr instead, as shown in this example:

struct S {  
    S() : p(nullptr) {}  
    void *p;  
};  
#define A; //cause of error  
struct S {  
    A(); // error  
};  

To fix the problem, change the top line to #define A();
The following code produces error C2059: syntax error: ')'

//notice the space after 'A'  
#define A () ;  
struct S {  
    A();  
};  

To fix the code, remove the space between A and ().
The following code produces error C2091: function returns function:

#define DECLARE void f()  
struct S {  
    DECLARE();  
};  

To fix the error, remove the parentheses after DECLARE in S: DECLARE;.
The following code produces error C2062: type 'int' unexpected

#define A (int)  
struct S {  
    A a;  
};  

To fix the problem, define A like this:

#define A int  
struct S {  
    int i;  
    (int)j;  
};  

To fix the error, remove the parentheses around j. If the parentheses are needed for clarity, then use a typedef.

auto testPositions{  
    std::tuple<int, int>{13, 33},  
    std::tuple<int, int>{-23, -48},  
    std::tuple<int, int>{38, -12},  
    std::tuple<int, int>{-21, 17}  
};  

To fix the error, one possibility is to initialize testPositions as follows:

std::tuple<int, int> testPositions[]{  
    std::tuple<int, int>{13, 33},  
    std::tuple<int, int>{-23, -48},  
    std::tuple<int, int>{38, -12},  
    std::tuple<int, int>{-21, 17}  
};  
struct B1 {  
private:  
    B1(const B1 &);  
};  
struct B2 : public B1 {};  
struct D : public B2 {};  
static_assert(std::is_convertible<D, B2>::value, "fail");  

To fix the error, change the static_assert so that it compares pointers to D and B2:

static_assert(std::is_convertible<D*, B2*>::value, "fail");  
//a.cpp  
class __declspec(dllexport)  
    A {  
public:  
    A();  
    A(const A&);  
    virtual ~A();  
private:  
    int i;  
};  
A::A() {}  
A::~A() {}  
A::A(const A&) {}  
//b.cpp  
// compile with cl.exe /nologo /LD /EHsc /Osx b.cpp  
#pragma comment(lib, "A")  
class __declspec(dllimport) A  
{  
public: A();  
        A(const A&);  
        virtual ~A();  
private:  
    int i;  
};  
struct __declspec(novtable) __declspec(dllexport) B  
    : virtual public A {  
    virtual void f() = 0;  
};  
//c.cpp  
#pragma comment(lib, "A")  
#pragma comment(lib, "B")  
class __declspec(dllimport) A  
{  
public:  
    A();  
    A(const A&);  
    virtual ~A();  
private:  
    int i;  
};  
struct  /* __declspec(novtable) */ __declspec(dllimport) B // Error. B needs to be novtable here also.  
    : virtual public A  
{  
    virtual void f() = 0;  
};  
struct C : virtual B  
{  
    virtual void f();  
};  
void C::f() {}  
C c;  

Conformance Improvements in Update 1

error C2280: 'void *S3::__delDtor(unsigned int)': attempting to reference a deleted function  

Example (before)

class base  
{  
protected:  
    base();  
    ~base();  
};  
class middle : private virtual base {}; class top : public virtual middle {};  
void destroy(top *p)  
{  
    delete p;  //  
}  

Example (after)

class base;  // as above  
class middle : protected virtual base {};  
class top : public virtual middle {};  
void destroy(top *p)  
{  
    delete p;  
}  

- or -

class base;  // as above  
class middle : private virtual base {};  
class top : public virtual middle, private virtual bottom {};  
void destroy(top *p)  
{  
    delete p;  
}  
error C2323: 'operator new': non-member operator new or delete functions may not be declared static or in a namespace other than the global namespace.  

Example (before)

static inline void * __cdecl operator new(size_t cb, const std::nothrow_t&)  // error C2323  

Example (after)

void * __cdecl operator new(size_t cb, const std::nothrow_t&)  // removed 'static inline'  

Additionally, although the compiler doesn't give a specific diagnostic, inline operator new is considered ill-formed.

error C2228: left of '.operator type' must have class/struct/union  

Example (before)

typedef int index_t;  
void bounds_check(index_t index);  
void login(int column)  
{  
    bounds_check(column.operator index_t());  // error C2228  
}  

Example (after)

typedef int index_t;  
void bounds_check(index_t index);  
void login(int column)  
{  
    bounds_check(column);  // removed cast to 'index_t', 'index_t' is an alias of 'int'  
}  
error C3406: 'typename' cannot be used in an elaborated type specifier  

Example (before)

template <typename class T>  
class container;  

Example (after)

template <class T>  // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case  
class container;  
error C2668: 'function' : ambiguous call to overloaded function.  

Example 1: Ambiguous call to overloaded function (before)

// In previous versions of the compiler, code written in this way would unambiguously call f(int, Args...)  
template < typename... Args>  
void f(int, Args...);  //  
template < int N, typename... Args>  
void f(const int(&)[N], Args...);  
int main()  
{  
    // The compiler now considers this call ambiguous, and issues a compiler error  
     f({ 3 });   error C2668 : 'f' ambiguous call to overloaded function  
}  

Example 1: ambiguous call to overloaded function (after)

template < typename... Args>  
void f(int, Args...);  //  
template < int N, typename... Args>  
void f(const int(&)[N], Args...);  
int main()  
{  
    // To call f(int, Args...) when there is just one expression in the initializer list, remove the braces from it.  
    f(3);  
}  

When this new behavior causes overload resolution to consider an additional candidate that's a better match than the historic candidate, the call resolves unambiguously to the new candidate, causing a change in program behavior that's probably different than the programmer intended.
Example 2: change in overload resolution (before)

// In previous versions of the compiler, code written in this way would unambiguously call f(S, Args...)  
struct S  
{  
    int i;  
    int j;  
};  
template < typename... Args>  
void f(S, Args...);  
template < int N, typename... Args>  
void f(const int *&)[N], Args...);  
int main()  
{  
    // The compiler now resolves this call to f(const int (&)[N], Args...) instead  
     f({ 1, 2 });  
}  

Example 2: change in overload resolution (after)

struct S;  // as before  
template < typename... Args>  
void f(S, Args...);  
template < int N, typename... Args>  
void f(const int *&)[N], Args...);  
int main()  
{  
    // To call f(S, Args...), perform an explicit cast to S on the initializer list.  
    f(S{ 1, 2 });  
}  
warning C4060: switch statement contains no 'case' or 'default' labels  
warning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case label  
warning C4062: enumerator 'bit1' in switch of enum 'flags' is not handled  
warning C4063: case 'bit32' is not a valid value for switch of enum 'flags'  
warning C4064: switch of incomplete enum 'flags'  
warning C4065: switch statement contains 'default' but no 'case' labels  
warning C4808: case 'value' is not a valid value for switch condition of type 'bool'  
Warning C4809: switch statement has redundant 'default' label; all possible 'case' labels are given  

Example of C4063 (before)

class settings  
{  
public:  
    enum flags  
    {  
        bit0 = 0x1,  
        bit1 = 0x2,  
        ...  
    };  
    ...  
};  
int main()  
{  
    auto val = settings::bit1;  
    switch (val)  
    {  
    case settings::bit0:  
        break;  
    case settings::bit1:  
        break;  
         case settings::bit0 | settings::bit1:  // warning C4063  
            break;  
    }  
}  

Example of C4063 (after)

class settings { ... };  // as above  
int main()  
{  
    // since C++11, use std::underlying_type to determine the underlying type of an enum  
    typedef std::underlying_type< settings::flags> ::type flags_t;  
        auto val = settings::bit1;  
    switch (static_cast< flags_t> (val))  
    {  
    case settings::bit0:  
        break;  
    case settings::bit1:  
        break;  
    case settings::bit0 | settings::bit1:  // ok  
        break;  
    }  
};  

Examples of the other restored warnings are provided in their documentation.

warning C4464: relative include path contains '..'  

Example (before)

#include "..\headers\C4426.h"  // emits warning C4464  

Example (after)

#include "C4426.h"  // add absolute path to 'headers\' to your project's include directories  

Additionally, although the compiler doesn't give a specific diagnostic, we also recommend that the parent-directory specifier ".." shouldn't be used to specify your project's include directories.

warning C4426: optimization flags changed after including header, may be due to #pragma optimize()  

Example (before)

// C4426.h  
#pragma optimize("g", off)  
...  
// C4426.h ends  
// C4426.cpp  
#include "C4426.h"  // warning C4426  

Example (after)

// C4426.h  
#pragma optimize("g", off)  
            ...  
#pragma optimize("", on)  // restores optimization flags set via command-line arguments  
// C4426.h ends  
// C4426.cpp  
#include "C4426.h"  
warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different file  

Example (before)

// C5031_part1.h  
#pragma warning(push)  
#pragma warning(disable:####)  
...  
// C5031_part1.h ends without #pragma warning(pop)  
// C5031_part2.h  
...  
#pragma warning(pop)  // pops a warning state not pushed in this source file  
...  
// C5031_part1.h ends  
// C5031.cpp  
#include "C5031_part1.h" // leaves #pragma warning(push) 'dangling'  
...  
#include "C5031_part2.h" // matches 'dangling' #pragma warning(push), resulting in warning C5031  
...  

Example (after)

// C5031_part1.h  
#pragma warning(push)  
#pragma warning(disable:####)  
...  
#pragma warning(pop)  // pops the warning state pushed in this source file  
// C5031_part1.h ends without #pragma warning(pop)  
// C5031_part2.h  
#pragma warning(push)  // pushes the warning state pushed in this source file  
#pragma warning(disable:####)  
...  
#pragma warning(pop)  
// C5031_part1.h ends  
// C5031.cpp  
#include "C5031_part1.h" // #pragma warning state changes are self-contained and independent of other source files or their #include order.  
...  
#include "C5031_part2.h"  
...  

Though uncommon, code written in this way is sometimes intentional. Code written in this way is sensitive to changes in #include order; when possible, we recommend that source code files manage warning state in a self-contained way.

warning C5032: detected #pragma warning(push) with no corresponding #pragma warning(pop)  

Example (before)

// C5032.h  
#pragma warning(push)  
#pragma warning(disable:####)  
...  
// C5032.h ends without #pragma warning(pop)  
// C5032.cpp  
#include "C5032.h"  
...  
// C5032.cpp ends -- the translation unit is completed without #pragma warning(pop), resulting in warning C5032 on line 1 of C5032.h  

Example (after)

// C5032.h  
#pragma warning(push)  
#pragma warning(disable:####)  
...  
#pragma warning(pop) // matches #pragma warning (push) on line 1  
// C5032.h ends  
// C5032.cpp  
#include "C5032.h"  
...  
// C5032.cpp ends -- the translation unit is completed without unmatched #pragma warning(push)  
warning C4720: unreachable code  

In many cases, this warning might only be issued when compiling with optimizations enabled, since optimizations may inline more function calls, eliminate redundant code, or otherwise make it possible to determine that certain code is unreachable. We have observed that new instances of warning C4720 have frequently occurred in try/catch blocks, especially in relation to use of std::find.
Example (before)

try  
{  
    auto iter = std::find(v.begin(), v.end(), 5);  
}  
catch (...)  
{  
    do_something();   // ok  
}  

Example (after)

try  
{  
    auto iter = std::find(v.begin(), v.end(), 5);  
}  
catch (...)  
{  
    do_something();   // warning C4702: unreachable code  
}  

Conformance Improvements in Update 2

error C2039: 'type': is not a member of 'global namespace'  

Example 1: use of an undeclared type (before)

struct s1  
{  
    template < typename T>  
    auto f() - > decltype(s2< T> ::type::f());  // error C2039  
    template< typename>  
    struct s2 {};  
}  

Example 1 (after)

struct s1  
{  
    template < typename>  // forward declare s2struct s2;  
        template < typename T>  
    auto f() - > decltype(s2< T> ::type::f());  
    template< typename>  
    struct s2 {};  
}  

When this new behavior parses a decltype expression that's missing a necessary use of the typename keyword to specify that a dependent name is a type, the compiler issues compiler warning C4346 together with compiler error C2923.

warning C4346: 'S2<T>::Type': dependent name is not a type  
error C2923: 's1': 'S2<T>::Type' is not a valid template type argument for parameter 'T'  

Example 2: dependent name isn't a type (before)

template < typename T>  
struct s1  
{  
    typedef T type;  
};  
template < typename T>  
struct s2  
{  
    typedef T type;  
};  
template < typename T>  
T declval();  
struct s  
{  
    template < typename T>  
    auto f(T t) - > decltype(t(declval< S1< S2< T> ::type> ::type> ()));  // warning C4346, error C2923  
};  

Example 2 (after)

template < typename T> struct s1 { ... };  // as above  
template < typename T> struct s2 { ... };  // as above  
template < typename T>  
T declval();  
struct s  
{  
    template < typename T>  
    auto f(T t) - > decltype(t(declval< S1< typename S2< T> ::type> ::type> ()));  
};  
error C2280: 'B::B(const B &)': attempting to reference a deleted function  

Example (before)

struct A  
{  
    volatile int i;  
    volatile int j;  
};  
extern A* pa;  
struct B  
{  
    union  
    {  
        A a;  
        int i;  
    };  
};  
B b1{ *pa };  
B b2(b1);  // error C2280  

Example (after)

struct A  
{  
    int i; int j;  
};  
extern volatile A* pa;  
A getA()  // returns an A instance copied from contents of pa  
{  
    A a;  
    a.i = pa - > i;  
    a.j = pa - > j;  
    return a;  
}  
struct B;  // as above  
B b1{ GetA() };  
B b2(b1);  // error C2280  
error C2511: 'void A::func(void) const': overloaded member function not found in 'A'  

Example (before)

struct A  
{  
    static void func();  
};  
void A::func() const {}  // C2511  

Example(after)

struct A  
{  
    static void func();  
};  
void A::func() {}  // removed const  
error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowed  
error C3197: 'public': can only be used in definitions  

Example (before)

namespace A {  
    public enum class CustomEnum : int32;  // forward declaration; error C2599, error C3197  
}  
namespace A {  
    public enum class CustomEnum : int32  
    {  
        Value1  
    };  
}  
public ref class Component sealed  
{  
public:  
    CustomEnum f()  
    {  
        return CustomEnum::Value1;  
    }  
};  

Example (after)

          // forward declaration of CustomEnum removed  
namespace A {  
    public enum class CustomEnum : int32  
    {  
        Value1  
    };  
}  
public ref class Component sealed  
{  
public:  
    CustomEnum f()  
    {  
        return CustomEnum::Value1;  
    }  
};  
warning C4595: 'operator new': non-member operator new or delete functions may not be declared inline  

Example (before)

inline void* operator new(size_t sz)  // warning C4595  
{  
    ...  
}  

Example (after)

void* operator new(size_t sz)  // removed inline  
{  
    ...  
}  

Fixing code that's written in this way might require that the operator definitions be moved out of a header file and into a corresponding source file.

Conformance Improvements in Update 3

#include <type_traits>  
class X1  
{  
            public:  
            X1(const X1&) = delete;  
            };  
class X2  
{  
            private:  
            X2(const X2&);  
            };  
static_assert(std::is_convertible<X1&, X1>::value, "BOOM");static_assert(std::is_convertible<X2&, X2>::value, "BOOM");  

In previous versions of the compiler, the static assertions at the bottom of this example pass because std::is_convertable<>::value was incorrectly set to true. Now, std::is_convertable<>::value is correctly set to false, causing the static assertions to fail.

error C2248: 'S::S' cannot access private member declared in class 'S'  

Example (before)

class S {  
public:  
    S() = default;  
private:  
    S(const S&) = default;  
};  
void f(S);  // pass S by value  
int main()  
{  
    S s;  
    f(s);  // error C2248, can't invoke private copy constructor  
}  

Example (after)

class S {  
public:  
    S() = default;  
private:  
    S(const S&) = default;  
};  
void f(const S&);  // pass S by reference  
int main()  
{  
    S s;  
    f(s);  
}  
warning C4467: Usage of ATL attributes is deprecated  

If you want to continue using attributed ATL code until support is removed from the compiler, you can disable this warning by passing the /Wv:18 or /wd:4467 command-line arguments to the compiler, or by adding #pragma warning(disable:4467) in your source code.
Example 1 (before)

          [uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")]  
class A {};  

Example 1 (after)

__declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) A {};  

Sometimes you might need or want to create an IDL file to avoid the use deprecated ATL attributes, as in the example code below
Example 2 (before)

[emitidl];  
[module(name = "Foo")];  
[object, local, uuid("9e66a290-4365-11d2-a997-00c04fa37ddb")]  
__interface ICustom {  
    HRESULT Custom([in] long l, [out, retval] long *pLong);  
    [local] HRESULT CustomLocal([in] long l, [out, retval] long *pLong);  
};  
[coclass, appobject, uuid("9e66a294-4365-11d2-a997-00c04fa37ddb")]  
class CFoo : public ICustom  
{  
    // ...  
};  

First, create the *.idl file; the vc140.idl generated file can be used to obtain an *.idl file containing the interfaces and annotations.
Next, add a MIDL step to your build to make sure that the C++ interface definitions are generated.
Example 2 IDL (after)

import "docobj.idl";  
[  
    object, local, uuid(9e66a290 - 4365 - 11d2 - a997 - 00c04fa37ddb)  
]  
interface ICustom : IUnknown {  
    HRESULT  Custom([in] long l, [out, retval] long *pLong);  
    [local] HRESULT  CustomLocal([in] long l, [out, retval] long *pLong);  
};  
[version(1.0), uuid(29079a2c - 5f3f - 3325 - 99a1 - 3ec9c40988bb)]  
library Foo  
{  
    importlib("stdole2.tlb");  
importlib("olepro32.dll");  
[  
    version(1.0),  
    appobject,uuid(9e66a294 - 4365 - 11d2 - a997 - 00c04fa37ddb)  
]  
coclass CFoo {  
    interface ICustom;  
};  
}  

Then, use ATL directly in the implementation file, as in the example code below.
Example 2 Implementation (after)

#include <idl.header.h>  
#include <atlbase.h>  
class ATL_NO_VTABLE CFooImpl :  
    public ICustom,  
    public ATL::CComObjectRootEx< CComMultiThreadModel>  
{  
public:  
    BEGIN_COM_MAP(CFooImpl)  
        COM_INTERFACE_ENTRY(ICustom)  
    END_COM_MAP()  
};  
warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that position  

Example (before):
X.cpp (-Ycc.h)

#include "a.h"  
#include "b.h"  
#include "c.h"  

Z.cpp (-Yuc.h)

#include "b.h"  
#include "a.h"  // mismatched order relative to X.cpp  
#include "c.h"  

Example (after)
X.cpp (-Ycc.h)

#include "a.h"  
#include "b.h"  
#include "c.h"  

Z.cpp (-Yuc.h)

#include "a.h"  
#include "b.h" // matched order relative to X.cpp  
#include "c.h"  
warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that position  

Example (before)

cl /c /Wall /Ycc.h -I.. X.cpp  
cl /c /Wall /Yuc.h Z.cpp  

Example (after)

cl /c /Wall /Ycc.h -I.. X.cpp  
cl /c /Wall /Yuc.h -I.. Z.cpp  

Visual Studio 2013 Conformance Changes

Compiler

struct S1 {  
    virtual void f() = 0;  
};  
struct S2 final : public S1 {  
    virtual void f();  
};  
int main(S2 *p)  
{  
    p->f();  
}  

In earlier versions, an error wasn't issued because the call was a virtual call; nevertheless, the program would crash at runtime. Now, a linker error is issued because the class is known to be final. In this example, to fix the error, you would link against the obj that contains the definition of S2::f.

namespace NS {  
    class C {  
        void func(int);  
        friend void func(C* const) {}  
    };  
    void C::func(int) {  
        NS::func(this);  // error  
    }  
}  

To correct this code, declare the friend function:

namespace NS {  
    class C {  
        void func(int);  
        friend void func(C* const) {}  
    };  
    void func(C* const);  // conforming fix  
    void C::func(int) {  
        NS::func(this);  
    }  
template < int N>  
class S {  
public:  
    template  void f(T& val);  
    template < > void f(char val);  
};  
template class S< 1>;  

To correct this code, modify the second function:

template <> void f(char& val);  
template< typename T> void Func(T* t = nullptr);  
template< typename T> void Func(...);  
int main() {  
    Func< int>(); // error  
}  

To correct this code, clarify the call:

template< typename T> void Func(T* t = nullptr);  
template< typename T> void Func(...);  
int main() {  
    Func< int>(nullptr); // ok  
}  
auto x = {0};  
int y = x;  

This code now resolves x to a type of std::initializer_list<int> and causes an error on the next line that tries to assign x to type int. (There is no conversion by default.) To correct this code, use int to replace auto:

int x = {0};  
int y = x;  
int i = 0;  
char c = {i}; // error  

To correct this code, add an explicit narrowing conversion:

int i = 0;  
char c = {static_cast<char>(i)};  
void *p = {{0}};  

To correct this code, use either of these forms:

void *p = 0;  
// or  
void *p = {0};  
enum class E1 { a };  
enum class E2 { b };  
int main()  
{  
    typedef E2 E1;  
    E1::b;  
}  

In Visual Studio 2012, the E1 in expression E1::b resolved to ::E1 in the global scope. In Visual Studio 2013, E1 in expression E1::b resolves to the typedef E2 definition in main() and has type ::E2.

__declspec(align(16)) struct S1 {  
};  
struct S2 {  
    virtual ~S2();  
    void *p;  
    S1 s;  
};  
__declspec(align(16)) struct S1 {  
};  
struct dummy {  
    virtual ~dummy() {}  
};  
struct S2 : public dummy {  
    virtual ~S2();  
    void *p;  
    S1 s;  
};  

To find places in your code that an earlier release would have tried to optimize, use a compiler from that release together with the /W3 compiler option and turn on warning C4370. For example:

#pragma warning(default:4370)  
__declspec(align(16)) struct S1 {  
};  
struct S2 {  
    virtual ~S2();  
    void *p;  
    S1 s;  
};  

Before Visual Studio 2013, this code outputs this message: "warning C4370: 'S2' : layout of class has changed from a previous version of the compiler due to better packing".
The x86 compiler has the same suboptimal layout issue in all versions of the compiler. For example, if this code is compiled for x86:

struct S {  
    virtual ~S();  
    int i;  
    double d;  
};  

The result of sizeof(S) is 24. However, it can be reduced to 16 if you use the workaround mentioned for x64:

struct dummy {  
    virtual ~dummy() {}  
};  
struct S : public dummy {  
    virtual ~S();  
    int i;  
    double d;  
};  

Standard Library

The C++ compiler in Visual Studio 2013 detects mismatches in _ITERATOR_DEBUG_LEVEL, which was implemented in Visual Studio 2010, and RuntimeLibrary mismatches. These mismatches occur when compiler options /MT (static release), /MTd (static debug), /MD (dynamic release), and /MDd (dynamic debug) are mixed.

template < typename T> struct Identity {  
    typedef T type;  
};  

MFC and ATL

Visual Studio 2012 Breaking Changes

Compiler

template < typename X = "", typename = "" AY = "">  
struct Container { typedef typename AY::template Rebind< X> ::Other AX; };  
template<float n=3.14>  
struct B {};  // error C2993: 'float': illegal type for non-type template parameter 'n'  
char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminate  

IDE

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 Library

CRT

MFC and ATL

Visual Studio 2010 Breaking Changes

Compiler

CLR

Visual Studio C++ projects and MSBuild

IDE

Libraries

Standard Library

CRT, MFC, and ATL Libraries

Macros and Environment Variables

Microsoft Macro Assembler Reference

Visual Studio 2008 Breaking Changes

Compiler

Visual Studio C++ projects

CRT

Standard Library

ATL

ATL/MFC Shared Classes

MFC

Visual Studio 2005 Breaking Changes

CRT

Standard Library (2005)

Visual C++ .NET 2003 Breaking Changes

Compiler

See also

What's New for Visual C++ in Visual Studio