ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


What's New in Visual C++ .NET 2003

by Sam Gentile
11/18/2002

The Visual C++ .NET 2003 release (code-named Everett) that has been released to MSDN today is perhaps the most significant and exciting release of the product since Visual C++ 4.0! Many changes have been made, resulting in a vastly different product from its predecessor. Why should you care? Well, there are important features that have been added for both unmanaged and managed code developers that illustrate a new and serious commitment by Microsoft to the C++ language. The main enhancements come in four major areas:

ISO/ANSI C++ Standards Compliance

Many of Microsoft's core products have been and are built with C++, and the language has been central to Microsoft. Regrettably, Standard C++ has not been. The compiler has lagged behind the standard for most of the 90s, and the impression that many developers have is that Microsoft could care less about the standard. The good news is that with the new compiler, Microsoft has finally taken the standard very seriously, leading to this version being one of the most standards-compliant C++ compilers running today on any platform. This turnaround is nothing short of amazing.

Related Reading

.NET Framework Essentials
By Thuan L. Thai, Hoang Lam

New features include Partial Template Specialization, Partial Ordering, Member Template Definitions, and much more. Andrei Alexandrescu's book Modern C++ Design and his Loki library have been the gold-plate example of using the C++ standard to its full potential. This library has consistently "broken" many compilers and, in particular, Visual C++. Visual C++ .NET fully compiles this library and runs 100% of its tests. Other popular 3rd party libraries like BOOST and BLITZ that use advanced template techniques also now build fully.

Let's look at a simple sample in which Partial Template Specialization is useful. This example is from chapter 3 of Alexandrescu's Modern C++ Design. A TypeList is a C++ tool for manipulating collections of types. It holds two types accessible through its Head and Tail inner elements, and looks like this:


template <class T, class U>
struct Typelist
{
typedef T Head;
     typedef U Tail;
};

One of the operations we might want to perform is, given a TypeList, obtain a compile-time constant that evaluates its length. We can first define a NullType to mark the end of a TypeList:


class NullType {};

Then, the code to compute a Typelist's length is:


template <class TList> struct Length;
template <> struct Length<NullType>
{
    enum { value = 0 };
};
template <class T, class U>
struct Length< Typelist<T, U> >
{
    enum { value = 1 + Length<U>::value };
};

The first specialization of Length is for NullType. This is a total specialization, or an Explicit Specialization. The second is a partial template specialization, that matches any TypeList<T, U>.

On Visual C++.NET 2002, this code will not compile because of the partial template specialization:


c:\Code\OReilly\LokiTypeList\LokiTypeList.h(9): 
  error C2065: 'T' : undeclared identifier
c:\Code\OReilly\LokiTypeList\LokiTypeList.h(9): 
  error C2065: 'Typelist' : undeclared identifier
c:\Code\OReilly\LokiTypeList\LokiTypeList.h(9): 
  error C2065: 'U' : undeclared identifier
c:\Code\OReilly\LokiTypeList\LokiTypeList.h(9): 
  error C2687: cannot define a nested UDT of 
               a template class out of line
c:\Code\OReilly\LokiTypeList\LokiTypeList.h(9): 
  fatal error C1903: unable to recover from previous 
                     error(s); stopping compilation

This is a familiar set of errors for C++ developers trying to compile their code that uses partial template specialization. Indeed, this is used throughout the standard C++ library. The good news is that this feature is completely implemented in the new compiler. If we recompile the same code with Visual C++ .NET 2003, all is fine:


    Build: 1 succeeded, 0 failed, 0 skipped

Certainly, this is welcome news for the community of unmanaged C+ developers who will now be able to make full use of the C++ Standards as well as third-party libraries.

Performance Enhancements

Microsoft has significantly enhanced optimization performance with two new compiler options, and has made improvements to some enhancements made to the previous version.

The first of these is the /G7 flag. This flag instructs the compiler to optimize code for the Intel Pentium 4 and AMD Athlon processors. The numbers can vary when you recompile your code with /G7 and I don't want to quote performance numbers, but its is not unusual to see 5-10% reduction in execution time for typical programs, and even 10-15% for programs that contain a lot of floating-point code. Recompiling with this flag will not produce code that only executes on the Intel Pentium 4 or AMD Athlon, but the code produced may have a minor performance penalty on older generations of these processors.

The second performance related option is /arch:[argument], where the argument is either SSE or SSE2. This option allows the compiler to make use of the Streaming SIMD Extensions (SSE) and Streaming SIMD Extensions 2 (SSE2_) instructions, as well as other instructions that support SSE or SSE2. Please note that the resulting code with these flags will only execute on processors that support these options. Again, performance improvements vary widely, but are in the range of 2-3%.

Finally, several of the optimizations introduced in previous versions of the product were enhanced in Visual C++ .NET 2003. One of these is the ability to eliminate the passing of dead parameters. Dead parameters are those that are not directly referenced in the code.

Security Enhancements

Buffer overruns are a serious problem for C and C++ programs, since unmanaged code does not perform array bounds checking or type-safety checking. Of course, this kind of "close to the metal" programming gives C++ an advantage for certain classes of applications. The downside is that buffer overruns become security holes and opportunities for several kinds of security attacks. Recognizing this problem, Microsoft has added the /GS compiler option. A simple example of "vulnerable" code is the following (which sadly is all too common):


#include <string.h>
void flawed(char * str)
{
    char buffer[10];
    strcpy(buffer, str);
}

void main()
{
    flawed("This string is too long");
}

This code, when run, has the wonderful effect of causing an Access Violation (unless one has the stack check flag /RTC1, in which case there is an assert and then the violation) and becomes fodder for a distributed denial-of-service attack.

Access violation caused by flawed code
Figure 1. Access violation caused by flawed code

Without going into the details, the /GS flag creates a new stack layout and "catches" many of these types of buffer overruns:

Detecting a buffer overrun
Figure 2. Detecting a buffer overrun.

Managed C++ Windows Form Visual Designer

Last, but certainly not least, is the welcome addition of visual designer support for creating Windows Forms in the Managed C++ language. Managed C++ programmers desiring to do this in the previous version of the product were forced to code these forms by hand without the considerable benefits of drag-and-drop placement and layout capabilities.

Managed C++ Windows Forms Application Wizard
Figure 3. Managed C++ Windows Forms Application Wizard

In the current release, the designer generates the code in the .h file and it looks something like the following:


#pragma once

namespace WinFormsDemo
{
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;

    /// <summary> 
    /// Summary for Form1
    ///
    /// WARNING: If you change the name of this class,
    /// you will need to change the 'Resource File 
    /// Name' property for the managed resource 
    /// compiler tool associated with all .resx files 
    /// this class depends on.  Otherwise, the 
    /// designers will not be able to interact properly
    /// with localized resources associated with this 
    /// form. 
    /// </summary>
    public __gc class Form1 
      : public System::Windows::Forms::Form
    {    
    public:
        Form1(void)
        {
            InitializeComponent();
        }
  
    protected:
        void Dispose(Boolean disposing)
        {
            if (disposing && components)
            {
                components->Dispose();
            }
            __super::Dispose(disposing);
        }

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container * components;

        /// <summary>
        /// Required method for Designer support - do 
        /// not modify the contents of this method 
        /// with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->components = 
              new System::ComponentModel::Container();
            this->Size = 
              System::Drawing::Size(300,300);
            this->Text = S"Form1";
        }    
    };
}

As you can see, it looks very much like the C# code that its Form Designer generates. The notable exception is the class declaration, which may look a little funny to those who have not seen Managed C++ syntax:


public __gc class Form1

The __gc keyword signifies that class Form1 is a Managed class, a garbage-collected class, and is thus controlled by the CLR.

Of course, there is much one could do from this point that is outside of the scope of this introductory article. Certainly one can drag and drop controls and all of the things that a C# or VB.NET Windows Form can do. The interesting possibilities come from combining unmanaged and managed code in this type of application. One possible scenario, for example, would be having a Managed C++ Windows Form using IJW and Managed C++ to use Direct/X without incurring the COM Interop penalty.

Summary

All in all, this is a very significant release, with features to please virtually all types of C++ developers. Microsoft has long suffered a (deserved) bad reputation for ignoring the ISO/ANSI C++ standards. Those unable to do such work with this compiler before will find welcome relief and support when using Visual C++ .NET 2003. Additionally, code recompiled for the new release will perform better, at least on new processors. Security concerns are addressed with the new option of detecting buffer overruns. Finally, the managed developer will also have welcome functionality in the form of Visual Designer support, enabling a whole new class of applications.

Sam Gentile is a well-known .NET consultant and is currently working with a large firm, using Visual C++ .NET 2003 to develop both unmanaged and managed C++ applications.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.