Microsoft & .NET.NETVisual C++ 2008 Feature Pack: MFC Enhancements

Visual C++ 2008 Feature Pack: MFC Enhancements

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Although the pace of managed language development appears to dwarf the rate of change in the C++ language, the development of new language features in C++ continues at the same measured pace that characterizes the language as a whole. Compared to languages such as Visual Basic that buckle and morph with each new trend, long-term stability is one of the C++ language’s key features, and changes happen at a steadier pace and with greater scrutiny. Work is currently underway on additions to the C++ language currently referred to as the C++0x Standard, reflecting the expected ratification of the standard this decade. Technical Report 1 (TR1) is an interim step in this standardization process, and incorporates many of the new features that are likely to form part of the final standard.

In a previous article, the MFC Feature Pack and its installation was covered is some depth. These instructions and tips won’t be repeated here.

STL Array

One of the most noticeable omissions in the current STL collection of containers is a fixed-length array. Even though there are plenty of work-arounds (C-style arrays, vector and third-party libraries), adding a fixed length array to the STL is a no-brainer in terms of collections that a typical C++ programmer would require. Using the new array collection is quite simple—the array length is nominated as a template parameter, and the collection behaves much like the STL vector collection:

#include <array>
#include <iostream>
#include <string>

std::tr1::array<int, 3> intArray = {4, 8, 10};

std::tr1::array<int, 3> intArray2 = {4, 8};
intArray2[2] = 10;

std::cout << ((intArray == intArray2)?
   std::string("Arrays are equal"):
   std::string("Arrays aren't equal")
);

std::cout << std::endl;

for (std::tr1::array<int, 3>::const_iterator it =
   intArray2.begin();
   it != intArray2.end();
   ++it) {
   std::cout << " " << *it;
}

There are a few noteworthy points in the code sample: The contents of an array can be fully or partially specified with initializers, and the compiler can check both the type and length of the initializer to ensure that the initializer is compatible with the array’s definition. Operator == has also been overridden to allow a value-by-value comparison of each element in the array to be performed, and iterators works in exactly the same way as other STL collections. It is also worth noting that all the TR1 extensions that ship as part of the Visual C++ 2008 feature pack are contained in the std::tr1 namespace.

Regular Expressions

Although many third-party toolkits for executing regular expressions in C++ exist, they often fail to deliver the desired degree of integration with the Standard C++ library. By directly adding regular expressions to C++, it is possible to use the results of regular expression execution in the algorithms that form part of the STL, and to write code that will compile across a wide variety of compilers.

The regular expression library follows a similar pattern to the Standard C++ basic_string class—the most important class in the TR1 regular expression library is basic_regex, which wraps a regular expression, and a template parameter of basic_regex that specifies whether char or wchar characters will be used. As with basic_string, a typedef is pre-defined for the char and wchar basic_regex varieties. The basic_regex class is typically constructed with the regular expression string and any flags that specify behavior such as case-sensitivity and the regular expression language to use (basic, extended, ECMAScript, awk, grep, and egrep are all supported), and the regular expression object is then passed with a target string to one of the regular expression template functions.

Three template functions are available: regex_match, regex_search and regex_replace. The regex_match template function is used to determine whether a target string matches the basic_regex object passed in. regex_search determines whether the regular expression matches any text in the target string and can optionally populate a match_results object that will contain the regular expression capture groups. The final template function is regex_replace, which is used to do string replacements based on the results of the regular expression’s execution.

This code sample shows the execution of a very simple email validation regular expression against two string constants (the point of the example is not the regular expression, which is overly simple for real email validation). The example prints whether the regular expression matches the target string.

#include <regex>
#include <iostream>
#include <string>

basic_regex<char> regex("[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}",
                        basic_regex<char>::icase);

cout<< std::boolalpha  << regex_match("GoOD@DOMAIN.COM", regex)
    << std::endl;

cout<< std::boolalpha  << regex_match("@DOMAIN.COM", regex)
    << std::endl;

Function Objects

Function objects will be familiar to C++/CLI developers who have previously used delegates—function objects offer type-safe function pointers that also can contain additional data that needs to be accessed as part of the functions execution. In contrast to raw function pointers that are not type-safe, the TR1 function template allows a function to be defined in terms of its return type and parameters, and for functions that meet this signature to be instantiated as part of the template instance and called without the need for a cast. The code below shows the use of a function object to call a function.

bool PrintData(int i, double d){
   cout << i;
   cout << endl;
   cout << scientific << d;
   cout << endl;

   return true;
}

{
   function<bool (int, double)> myPrint(PrintData);
   bool res = myPrint(1, 2.0);
}

The obvious benefit of function objects is the lack of casting required. The myPrint object can call the PrintData function without the need for a messy and potentially dangerous cast to a function point.

Other Additions

The TR1 updates also include a comprehensive random number generation library. There are a number of random number generations schemes included in TR1, including bernoulli_distribution, binomial_distribution, exponential_distribution, gamma_distribution, geometric_distribution, normal_distribution, and poisson_distribution. The distribution classes are used by random number generation algorithms, such as linear_congruential and mersenne_twister, which are included as part of the TR1 library. The following code snippet shows random number generation with the mersenne_twister algorithm and gamma_distribution.

using namespace std::tr1;
...
//use TR1 typedef mt19937 for Mersenne twister algorithm
mt19937 randomAlg;
gamma_distribution <double> randomDist;
double d = randomDist(randomAlg);

Joining the new array collection in TR1 are the new collections unordered_set, unordered_map, and unordered_multimap. As the type name suggests, these new collections differ from the existing STL set and map collections by not ordering the sequence that they maintain. The advantage of avoiding ordering is that the cost of element insertion, deletion, and location is an O(1) operation (in other words, the computational cost is independent of the collection size). The main disadvantage of the lack of ordering is that collection equality is harder to determine, because a collection containing the same elements could have them located in different positions.

Conclusion

The TR1 updates are an exciting step towards C++0x, and represent a significant evolution in Standard C++ that ensures that the C++ language remains strong, relevant, and modern for the foreseeable future. TR1 brings many of the benefits and features to C++ that programmers in managed languages have come to expect, and still maintains the massive investment that the software industry has in C++ code.

The release of the TR1 updates in the Visual C++ 2008 Feature Pack demonstrates Microsoft’s continued support of and investment in the Visual C++ product, and shows that native code developers still have many good years ahead of them at the keyboard.

About the Author

Nick Wienholt is an independent Windows and .NET consultant based in Sydney. He is the author of Maximizing .NET Performance and co-author of A Programmers Introduction to C# 2.0 from Apress, and specialises in system-level software architecture and development, with a particular focus of performance, security, interoperability, and debugging.

Nick is a keen and active participant in the .NET community. He is the co-founder of the Sydney Deep .NET User group and writes technical articles for Australian Developer Journal, ZDNet, Pinnacle Publishing, CodeGuru, MSDN Magazine (Australia and New Zealand Edition) and the Microsoft Developer Network. An archive of Nick’s SDNUG presentations, articles, and .NET blog is available at www.dotnetperformance.com.

In recognition of his work in the .NET area, he was awarded the Microsoft Most Valued Professional Award from 2002 through 2007.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories