body { margin:0px; padding:0px; background:#f6f6f6; color:#000000; font-size: small; } #outer-wrapper { font:normal normal 100% 'Trebuchet MS',Trebuchet,Verdana,Sans-Serif; } a { color:#DE7008; } a:hover { color:#9E5205; } a img { border-width: 0; } #content-wrapper { padding-top: 0; padding-right: 1em; padding-bottom: 0; padding-left: 1em; } @media all { div#main { float:right; width:66%; padding-top:30px; padding-right:0; padding-bottom:10px; padding-left:1em; border-left:dotted 1px #e0ad12; word-wrap: break-word; /* fix for long text breaking sidebar float in IE */ overflow: hidden; /* fix for long non-text content breaking IE sidebar float */ } div#sidebar { margin-top:20px; margin-right:0px; margin-bottom:0px; margin-left:0; padding:0px; text-align:left; float: left; width: 31%; word-wrap: break-word; /* fix for long text breaking sidebar float in IE */ overflow: hidden; /* fix for long non-text content breaking IE sidebar float */ } } @media handheld { div#main { float:none; width:90%; } div#sidebar { padding-top:30px; padding-right:7%; padding-bottom:10px; padding-left:3%; } } #header { padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; border-bottom:dotted 1px #e0ad12; background:#F5E39e; } h1 a:link { text-decoration:none; color:#F5DEB3 } h1 a:visited { text-decoration:none; color:#F5DEB3 } h1,h2,h3 { margin: 0; } h1 { padding-top:25px; padding-right:0px; padding-bottom:10px; padding-left:5%; color:#F5DEB3; background:#DE7008; font:normal bold 300% Verdana,Sans-Serif; letter-spacing:-2px; } h3.post-title { color:#9E5205; font:normal bold 160% Verdana,Sans-Serif; letter-spacing:-1px; } h3.post-title a, h3.post-title a:visited { color: #9E5205; } h2.date-header { margin-top:10px; margin-right:0px; margin-bottom:0px; margin-left:0px; color:#777777; font: normal bold 105% 'Trebuchet MS',Trebuchet,Verdana,Sans-serif; } h4 { color:#aa0033; } #sidebar h2 { color:#B8A80D; margin:0px; padding:0px; font:normal bold 150% Verdana,Sans-serif; } #sidebar .widget { margin-top:0px; margin-right:0px; margin-bottom:33px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-size:95%; } #sidebar ul { list-style-type:none; padding-left: 0; margin-top: 0; } #sidebar li { margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; list-style-type:none; font-size:95%; } .description { padding:0px; margin-top:7px; margin-right:12%; margin-bottom:7px; margin-left:5%; color:#9E5205; background:transparent; font:bold 100% Verdana,Sans-Serif; } .post { margin-top:0px; margin-right:0px; margin-bottom:30px; margin-left:0px; } .post strong { color:#000000; font-weight:bold; } pre,code { color:#999999; } strike { color:#999999; } .post-footer { padding:0px; margin:0px; color:#444444; font-size:80%; } .post-footer a { border:none; color:#968a0a; text-decoration:none; } .post-footer a:hover { text-decoration:underline; } #comments { padding:0px; font-size:110%; font-weight:bold; } .comment-author { margin-top: 10px; } .comment-body { font-size:100%; font-weight:normal; color:black; } .comment-footer { padding-bottom:20px; color:#444444; font-size:80%; font-weight:normal; display:inline; margin-right:10px } .deleted-comment { font-style:italic; color:gray; } .comment-link { margin-left:.6em; } .profile-textblock { clear: both; margin-left: 0; } .profile-img { float: left; margin-top: 0; margin-right: 5px; margin-bottom: 5px; margin-left: 0; border: 2px solid #DE7008; } #sidebar a:link { color:#999999; text-decoration:none; } #sidebar a:active { color:#ff0000; text-decoration:none; } #sidebar a:visited { color:sidebarlinkcolor; text-decoration:none; } #sidebar a:hover { color:#B8A80D; text-decoration:none; } .feed-links { clear: both; line-height: 2.5em; } #blog-pager-newer-link { float: left; } #blog-pager-older-link { float: right; } #blog-pager { text-align: center; } .clear { clear: both; } .widget-content { margin-top: 0.5em; } /** Tweaks for layout editor preview */ body#layout #outer-wrapper { margin-top: 0; } body#layout #main, body#layout #sidebar { margin-top: 10px; padding-top: 0; } -->

Monday, May 5, 2008

Visual Studio 2008 Feature Pack

Origin article : http://msdn.microsoft.com/en-us/magazine/cc507634.aspx

What's New in the Standard C++ Library
As I've mentioned, the feature pack also includes significant additions to the Standard C++ Library as a part of TR1. This includes support for reference-counted smart pointers, polymorphic function wrappers, hashtable-based containers, regular expressions, and much more. In the following scenarios, I'll take a look at some of these new TR1 features.
Polymorphic Function Objects
The ability to refer to a function as a value that can be passed as a parameter or stored for later use is a vital part of many applications. This concept can be used to implement various common constructs including callback functions, event handlers and asynchronous programming facilities. Functions, however, can be quite unwieldy in C++. The design of functions was primarily driven by the need for compatibility with C and for great performance. Although these goals were achieved, it didn't make it any easier to treat functions as objects that can be stored, passed around and ultimately called asynchronously. Let's take a look at a few common function-like constructs in C++.
First, there is the good old non-member function:

int Add(int x, int y)
{
return x + y;
}

Naturally, it can be called as follows:

int result = Add(4, 5);
ASSERT(4 + 5 == result);

Another common function-like construct is the function object, or functor:

AddFunctor
{
public:
int operator()(int x, int y) const
{
return
x + y;
}
};

Since it implements the call operator, a function object can be used as if it were a function:

AddFunctor fo;
int result = fo(4, 5);
ASSERT(4 + 5 == result);

Then there is the non-static member function:

class Adder
{
public:
int Add(int x, int y) const
{
return x +
y;
}
};

Of course, calling the member function requires an object:

Adder adder;
int result = adder.Add(4, 5);
ASSERT(4 + 5 == result);

So far, so good. Now let's say you need to store these function-like constructs for later use. You can define a type that is capable of storing a pointer to a non-member function as follows:

typedef int (*FunctionPointerType)(int x, int y);

A function pointer can also be used as if it were a function:

FunctionPointerType fp = &Add;
int result = fp(4, 5);
ASSERT(4 + 5 == result);

Although the function object can also be stored, it cannot be stored polymorphically along with a function pointer.
The member function can be stored in a pointer-to-member-function:

Adder adder;
typedef int (Adder::*MemberFunctionPointerType)(int x, int
y);
MemberFunctionPointerType mfp = &Adder::Add;


But the pointer-to-member-function type is not compatible with the pointer-to-non-member-function type and thus cannot be stored polymorphically alongside its non-member function rival. Even if that were possible, the member function still would require an object to provide the context for the member function call:

int result = (adder.*mfp)(4, 5);
ASSERT(4 + 5 == result);

I could go on, but I think you get the idea. Fortunately, a solution is provided by the new tr1::function class template. The tr1::function class template holds a callable object for the function type defined in its template parameter. Here I'm initializing it with the non-member function:

function f = &Add;
int result = f(4, 5);
ASSERT(4 + 5 == result);

You can just as easily initialize it with the function object:

function f = AddFunctor();


You can even use the new function binding facility to initialize it with the member function:

function f = bind(&Adder::Add, &adder, _1, _2);

I'll talk about the bind function in a moment but the beauty here is that now there is a single function wrapper that you can bind to non-member functions, function objects, or even member functions. You can store it and call it at some point in the future, and it's all done polymorphically.
The function wrapper is also rebindable and can be set to nothing just like normal function pointers:

function f;
ASSERT(0 == f);
f =
&Add;
ASSERT(0 != f);
f = bind(&Adder::Add, &adder, _1, _2);

The bind function template provides a much more powerful alternative to the function object adapters in the Standard C++ Library—specifically std::bind1st() and std::bind2nd(). In this example, the first parameter of bind is the address of the member function. The second parameter is the address of the object on which the member is to be called. The last two parameters in this example define placeholders that will be resolved when the function is called.
Of course, bind is not limited to member functions. You can create a squaring function by binding the Standard C++ Library's multiplies function object to produce a function with a single parameter that will produce the result of the parameter squared:

function square = bind(multiplies(), _1, _1);
int
result = square(3);
ASSERT(9 == result);

Note that the tr1::function class template works great with Standard C++ Library algorithms. Given a container of integers, you can produce the sum of all the values using the member function, as follows:

function f = // initialize
int result =
accumulate(numbers.begin(),
numbers.end(),
0, // initial value
f);

Keep in mind that the tr1::function class template can inhibit compiler optimizations (such as inlining) that may be possible if you simply use a function pointer or function object directly. Therefore, you should only use the tr1::function class template when necessary, such as in the case of algorithms like accumulate where it may be called repeatedly. When possible, you should pass function pointers, member function pointers (adapted with mem_fn from TR1), and function objects (such as those returned by bind) directly to Standard C++ Library algorithms and other templated algorithms.
Let's not stop there. Here's a more interesting problem. Say you have a Surface class representing some drawing surface and a Shape class that is capable of drawing itself onto the surface:

class Surface
{
//...
};
class Shape
{
public:
void
Draw(Surface& surface) const;
};

Now consider how you might draw each shape in a container onto a given surface. You might want to use the for_each algorithm, as shown in the following:

Surface surface = // initialize
for_each(shapes.begin(),
shapes.end(),
bind(&Shape::Draw,
_1, surface)); // wrong

Here I'm taking advantage of the bind function template to invoke the member function on each element of the shapes container, binding the surface as the parameter to the Draw member function. Unfortunately, depending on how Surface is defined, it may not work as expected or even compile. The trouble is that the bind function template will try to make a copy of surface when what you really want is a reference. Fortunately, TR1 also introduces the reference_wrapper class template that allows you to treat a reference as a value that may be freely copied. The ref and cref function templates simplify the creation of reference_wrapper objects thanks to their type inference.
With the help of reference_wrapper, the for_each algorithm is now able to successfully draw the shapes to the surface both simply and efficiently:

for_each(shapes.begin(),shapes.end(), bind(&Shape::Draw, _1, ref(surface)));

As you can imagine, the new function wrappers, binding features, and reference wrappers can be combined in a myriad of ways to solve all kinds of problems elegantly.
Smart Pointers
Smart pointers are an essential tool for C++ developers. I routinely use ATL's CComPtr for handling COM interface pointers and the Standard C++ Library's auto_ptr for handling raw C++ pointers. The latter is useful for scenarios where you need to dynamically create C++ objects and ensure the object is safely deleted when the auto_ptr object goes out of scope.
As useful as auto_ptr is, it can only be used safely in a few scenarios. This is because of the transfer-of-ownership semantics that it implements. That is, if you copy or assign an auto_ptr object, the ownership of the underlying resource is transferred and lost by the originating auto_ptr object. Although this is clearly useful in scenarios where you have fine-grained control over resource allocations, there are many scenarios where you might need to share objects, and a smart pointer implementing shared-ownership semantics would be very useful indeed. More importantly, auto_ptr cannot be used with Standard C++ Library containers.
TR1 introduces two new smart pointers that work together to provide a multitude of uses. The shared_ptr class template works in much the same way as auto_ptr but instead of transferring ownership of a resource it merely increases a reference count on the resource. When the last shared_ptr object that holds a reference to the object is destroyed or reset, the resource is automatically deleted. The weak_ptr class template works with shared_ptr to allow callers to reference a resource without affecting its reference count. This is useful for object models where you might have cyclical relationships or perhaps if you're implementing a caching service. It also works great with Standard C++ Library containers!
As a comparison, consider the following use of auto_ptr:

auto_ptr ap(new int(123));
ASSERT(0 != ap.get());
// transfer
ownership from ap to ap2
auto_ptr ap2(ap);
ASSERT(0 !=
ap2.get());
ASSERT(0 == ap.get());

The auto_ptr copy constructor transfers the ownership from ap to ap2. The behavior of shared_ptr is equally predictable:

shared_ptr sp(new int(123));
ASSERT(0 != sp);
// increase
reference count of shared object
shared_ptr sp2(sp);
ASSERT(0 != sp2);
ASSERT(0 != sp);

Internally, all shared_ptr objects that refer to the same resource share a control block that tracks the number of shared_ptr objects that jointly own the resource as well as the number of weak_ptr objects that refer to it. I'll show you how to use the weak_ptr class template in a moment.
Member functions similar to auto_ptr are provided by shared_ptr. They include the dereference and arrow operators, the reset member function to replace the resource, and the get member function that returns the address of the resource. A few unique member functions, including one coincidentally named unique, are also provided. The unique member function tests whether the shared_ptr object is the only smart pointer to hold a reference to the resource. Here's an example:

shared_ptr sp(new
int(123));
ASSERT(sp.unique());
shared_ptr
sp2(sp);
ASSERT(!sp.unique());
ASSERT(!sp2.unique());

You can also get the number of shared_ptr objects that own the resource with the use_count member function:

shared_ptr sp;
ASSERT(0 == sp.use_count());
sp.reset(new
int(123));
ASSERT(1 == sp.use_count());
shared_ptr
sp2(sp);
ASSERT(2 == sp.use_count());
ASSERT(2 == sp2.use_count());

You should, however, limit the use of use_count to debugging only as it is not guaranteed to be a constant time operation on all implementations. Note that you can rely on the provided operator unspecified-bool-type to determine whether the shared_ptr owns anything, and you can use the unique function to determine whether the shared_ptr is the unique owner of something.
The weak_ptr class template stores a weak reference to a resource owned by a shared_ptr object. Once all of the shared_ptr objects owning the resource are destroyed or reset, the resource is deleted regardless of whether any weak_ptr objects are referring to it. To ensure that you cannot use a resource referred to only by a weak_ptr object, the weak_ptr class template does not provide the familiar get member function to return the resource's address or the member access operator. Instead, you need to first convert the weak reference into a strong reference in order to access the resource. This functionality is provided by the lock member function, as shown in Figure 8.
Figure 8 Convert to Strong Reference

shared_ptr sp(new Shape);ASSERT(1 ==
sp.use_count());
weak_ptr wp(sp);ASSERT(1 == sp.use_count()); //
still 1
// arbitrary application logic...
if (shared_ptr sp2
= wp.lock()){ sp2->Draw(surface);}


shared_ptr sp(new Shape);
ASSERT(1 == sp.use_count());
weak_ptr wp(sp);
ASSERT(1 == sp.use_count()); // still 1
// arbitrary application logic...
if (shared_ptr sp2 = wp.lock())
{
sp2->Draw(surface);
}
If in the interim the resource is released, the weak_ptr object's lock member function will return a shared_ptr object that does not own a resource. As you can probably imagine, shared_ptr and weak_ptr can dramatically simplify resource management in many applications.
It's pretty clear that Visual C++ 2008 Feature Pack is a welcome upgrade to the Visual C++ libraries and is sure to come in handy! There's so much more to explore but I hope that this introduction has piqued your interest and that you'll set aside a few moments to take a closer look yourself.

Visual Studio 2008 Feature Pack download from here :
http://www.microsoft.com/downloads/details.aspx?FamilyId=D466226B-8DAB-445F-A7B4-448B326C48E7&displaylang=en

No comments:

Powered By Blogger